Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

    Optomisation giving different results

    Indicators/Strategies/Analyzers
    2
    3
    1196
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • J
      j45p41 last edited by

      Hi,

      first of all thank you all for all your hard work.

      I have gone from knowing very little python a few weeks ago to writing my first strategy in backtrader. I started with gekko but then said to myself that it was worth learning a platform with greater potential.

      I am however scratching my head at the moment. When I run my code and vary the optomisation parameters I get different results. E.g. when I find a set of optimal paramaters and then squeeze my ranges to near the optimal values something seems wrong.

      Here are some of my results:

      Period: 13, rsi_low: 32, rsi_high: 72, PnL: 2150.7
      cerebro.optstrategy(firstStrategy, period=range(10, 15), rsi_low=range(30, 35), rsi_high=range(55, 75))

      Period: 13, rsi_low: 32, rsi_high: 72, PnL: 2466.8
      cerebro.optstrategy(firstStrategy, period=range(13, 14), rsi_low=range(32, 33), rsi_high=range(72, 73))

      Period: 13, rsi_low: 32, rsi_high: 72, PnL: 2207.9
      cerebro.optstrategy(firstStrategy, period=range(12, 14), rsi_low=range(31, 33), rsi_high=range(71, 73))

      Here is my code:

      import backtrader as bt
      import ccxt
      import datetime
      import time
      import backtrader.feeds as btfeed
      import math
      import pandas as pd
      import os.path
      import sys
      
      class dataFeed(btfeed.GenericCSVData):
          params = (
              ('dtformat', '%Y-%m-%d %H:%M:%S'),
              ('datetime', 0),
              ('open', 1),
              ('high', 2),
              ('low', 3),
              ('close', 4),
              ('volume', 5),
              ('openinterest', -1)
          )
      
      class firstStrategy(bt.Strategy):
          params = (
              ("period", 21),
              ("rsi_low", 41),
              ("rsi_high", 66),
          )
      
          def __init__(self):
              self.startcash = self.broker.getvalue()
              self.rsi = bt.indicators.RSI_SMA(self.data.close, period=self.params.period)
      
          def next(self):
              if not self.position:
                  if self.rsi < self.params.rsi_low:
                      self.buy(size=100)
              else:
                  if self.rsi > self.params.rsi_high:
                      self.sell(size=100)
      
      # INPUT CONDITIONS TO FEED INTO CEREBRO IS ADDED HERE
      if __name__ == '__main__':
          # Variable for our starting cash
          startcash = 1000000
          # Create an instance of cerebro
          cerebro = bt.Cerebro(optreturn=False)
      
          # Add our strategy
          cerebro.optstrategy(firstStrategy, period=range(12, 14), rsi_low=range(31, 33), rsi_high=range(71, 73))
      
          # DATA FEED FROM EXCHANGE
      
          symbol = str('ETH/USDT')
          timeframe = str('15m')
          exchange = str('poloniex')
          exchange_out = str(exchange)
          start_date = str('2018-3-16 00:00:00')
          end_date = str('2018-3-17 19:00:00')
      
          # Get our Exchange
          exchange = getattr(ccxt, exchange)()
          exchange.load_markets()
      
      
          def to_unix_time(timestamp):
              epoch = datetime.datetime.utcfromtimestamp(0)  # start of epoch time
              my_time = datetime.datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S")  # plugin your time object
              delta = my_time - epoch
              return delta.total_seconds() * 1000
      
          # Get data
          hist_start_date = int(to_unix_time(start_date))
          hist_end_date = int(to_unix_time(end_date))
          data = exchange.fetch_ohlcv(symbol, timeframe, since=hist_start_date, limit=hist_end_date)
          header = ['Timestamp', 'Open', 'High', 'Low', 'Close', 'Volume']
          df = pd.DataFrame(data, columns=header)
          df['Timestamp'] = pd.to_datetime(df['Timestamp'], unit='ms')
          #df = pd.DataFrame(data, columns=header).set_index('Timestamp')
      
          #Precision
          df = df.round(3)
      
      
          # Save it
          symbol_out = symbol.replace("/", "")
          filename = '{}-{}-{}.csv'.format(exchange_out, symbol_out, timeframe)
          df.to_csv(filename, index= False)
      
          #READ DATA FROM CSV FILE
          modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
          datapath = os.path.join(modpath,str(filename))
          data = dataFeed(dataname=datapath, timeframe=bt.TimeFrame.Minutes, compression=60,)
      
      
          # Add the data to Cerebro
          cerebro.adddata(data)
      
          # Set our desired cash start
          cerebro.broker.setcash(startcash)
      
          # RUN STRATEGY THROUGH CEREBRO USING INPUT DATA
          opt_runs = cerebro.run()
      
          # CREATE A LIST VARIABLE THAT CONTAINS RESULTS
          final_results_list = []
          for run in opt_runs:
              for strategy in run:
                  value = round(strategy.broker.get_value(), 2)
                  PnL = round(value - startcash, 2)
                  period = strategy.params.period
                  rsi_low = strategy.params.rsi_low
                  rsi_high = strategy.params.rsi_high
                  final_results_list.append([period, rsi_low, rsi_high, PnL])
      
          # Sort Results List
          by_period = sorted(final_results_list, key=lambda x: x[0])
          by_PnL = sorted(final_results_list, key=lambda x: x[3], reverse=True)
      
          # Print results
          print('Results: Ordered by Profit:')
          for result in by_PnL:
              print('Period: {}, rsi_low: {}, rsi_high: {}, PnL: {}'.format(result[0], result[1], result[2], result[3]))
      
      

      Any ideas? Also if anybody reading this can tell me how to use the data frame without going via csv then that would also be great!

      B 1 Reply Last reply Reply Quote 0
      • B
        backtrader administrators @j45p41 last edited by

        @j45p41 said in Optomisation giving different results:

        data = exchange.fetch_ohlcv(symbol, timeframe, since=hist_start_date, limit=hist_end_date)
        

        Save it once to a file and use it always, rather than pulling data, because data can be back-adjusted.

        @j45p41 said in Optomisation giving different results:

        Also if anybody reading this can tell me how to use the data frame without going via csv then that would also be great!

        Use PandasData

        • Docs - PandasData
        • Docs - DataFeed Reference
        1 Reply Last reply Reply Quote 2
        • J
          j45p41 last edited by

          Thank you that seemed to have worked!

          1 Reply Last reply Reply Quote 0
          • 1 / 1
          • First post
            Last post
          Copyright © 2016, 2017, 2018 NodeBB Forums | Contributors
          $(document).ready(function () { app.coldLoad(); }); }