Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    1. Home
    2. FM2020
    3. Posts
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/
    F
    • Profile
    • Following 0
    • Followers 0
    • Topics 1
    • Posts 1
    • Best 0
    • Groups 0

    Posts made by FM2020

    • Issue with the optimizing

      Hi there,
      While backtesting works well for me, I run into problems with optimizing with respect to sharpe ratio when using my below code, see the below output.
      It seems that the final_results_list does get only NoneType values for the Sharpe Rations. Any idea what went wrong? Thanks!

      Unbenannt.JPG

      Output:

      File "C:\Users\User\Desktop\Python for Finance\MACD_Strategy\BackTrader_MACD_Example\btmain.py", line 174, in <module>
        sort_by_sharpe = sorted(final_results_list, key=lambda x: x[3], reverse=True)
      
      TypeError: '<' not supported between instances of 'NoneType' and 'NoneType'
      
      from __future__ import (absolute_import, division, print_function,
                              unicode_literals)
      
      import datetime  # For datetime objects
      import os.path  # To manage paths
      import sys  # To find out the script name (in argv[0])
      
      # Import the backtrader platform
      import backtrader as bt
      import backtrader.indicators as btind
      
      import pandas as pd
      import numpy as np
      
      from strategies import *
      
      ###--------------------------------
      ###--------------------------------
      ###--------------------------------
      ### FOR OPTIMIZATION
      
      #Instantiate Cerebro engine
      cerebro = bt.Cerebro(optreturn=False, optdatas=True)
      
      modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
      datapath = os.path.join(modpath, 'C:/Users/User/Desktop/Python for Finance/MACD_Strategy/BackTrader_MACD_Example/ohlc.csv')
      
      data = bt.feeds.GenericCSVData(
          dataname=datapath,
          #add or remove do in-sample and out-of-sample tests (i.e. optimize in one and backtest in next years)
          #settings for in-sample optimization
          #fromdate=datetime.datetime(2020, 5, 4, 0, 0, 0),
          #todate=datetime.datetime(2020, 6, 4, 0, 0, 0),
          #settings for out-of-sample backtest
          #fromdate=datetime.datetime(2020, 6, 4, 0, 0, 0),
          #todate=datetime.datetime(2020, 6, 23, 0, 0, 0),  
          nullvalue=0.0,
          dtformat=('%Y-%m-%d %H:%M:%S'),
          datetime=0,
          time=-1,
          high=2,
          low=3,
          open=1,
          close=4,
          volume=5,
          openinterest=-1,
          timeframe=bt.TimeFrame.Minutes)
      
      cerebro.adddata(data)
      
      #Add strategy to Cerebro
      cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe_ratio')
      cerebro.optstrategy(MAcrossover, pfast=range(5, 20), pslow=range(50, 100)) 
      
      #Default position size / 1 = 1 underlying share
      cerebro.addsizer(bt.sizers.SizerFix, stake=1)
      
      if __name__ == '__main__':
          optimized_runs = cerebro.run()
      
          final_results_list = []
          for run in optimized_runs:
              for strategy in run:
                  PnL = round(strategy.broker.get_value() - 10000,2)
                  sharpe = strategy.analyzers.sharpe_ratio.get_analysis()
                  final_results_list.append([strategy.params.pfast, 
                      strategy.params.pslow, PnL, sharpe['sharperatio']])
      
          sort_by_sharpe = sorted(final_results_list, key=lambda x: x[3], reverse=True)
           
          for line in sort_by_sharpe[:5]:
               print(line)
      

      Strategy:

      class MAcrossover(bt.Strategy): 
          #Moving average parameters
          params = (('pfast',20),('pslow',50),)
          
          def log(self, txt, dt=None):
              ''' Logging function fot this strategy'''
              dt = dt or self.datas[0].datetime.datetime(0)
              #print('%s, %s' % (dt.isoformat(), txt))
              print("%s, %s" % (dt, txt))
              
          def __init__(self):     
              self.dataclose = self.datas[0].close     
              # Order variable will contain ongoing order details/status
              self.order = None     
              # Instantiate moving averages     
              self.slow_sma = bt.indicators.MovingAverageSimple(self.datas[0],                                       
                              period=self.params.pslow)     
              self.fast_sma = bt.indicators.MovingAverageSimple(self.datas[0], 
                              period=self.params.pfast)
          
          def notify_order(self, order):
              if order.status in [order.Submitted, order.Accepted]:
                  #Active Buy/Sell order submitted/accepted - Nothing to do
                  return
              #Check if an order has been completed
              #Attention: broker could reject order if not enough cash
              if order.status in [order.Completed]:
                  if order.isbuy():             
                      self.log('BUY EXECUTED, %.2f' % order.executed.price)         
                  elif order.issell():             
                      self.log('SELL EXECUTED, %.2f' % order.executed.price)
                      self.bar_executed = len(self)
              elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                  self.log('Order Canceled/Margin/Rejected')     
                  #Reset orders  
                  self.order = None
      
      
          def next(self):
              if self.order:
                  return
              #Check if we are in the market
              if not self.position:
              #We are not in the market, look for a signal to OPEN trades
                  #If the 20 SMA is above the 50 SMA
                  if self.fast_sma[0] > self.slow_sma[0] and self.fast_sma[-1] < self.slow_sma[-1]:
                       self.log('BUY CREATE, %.2f' % self.dataclose[0])
                       #Keep track of the created order to avoid a 2nd order
                       self.order = self.buy()
                  #Otherwise if the 20 SMA is below the 50 SMA
                  elif self.fast_sma[0] < self.slow_sma[0] and self.fast_sma[-1] > self.slow_sma[-1]:
                      self.log('SELL CREATE, %.2f' % self.dataclose[0])
                      #Keep track of the created order to avoid a 2nd order
                      self.order = self.sell()
              else:
                  # We are already in the market, look for a signal to CLOSE trades
                  if len(self) >= (self.bar_executed + 5):
                     self.log('CLOSE CREATE, %.2f' % self.dataclose[0])
                     self.order = self.close()
      
      posted in General Code/Help
      F
      FM2020
    • 1 / 1