Navigation

    Backtrader Community

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

    j45p41

    @j45p41

    0
    Reputation
    725
    Profile views
    27
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    j45p41 Unfollow Follow

    Latest posts made by j45p41

    • RE: Optimize Stop-Trail order values

      @backtrader So obvious (when you know how) got it. Removed the globals and try except and got it to work! Thank you sir!

      posted in Indicators/Strategies/Analyzers
      J
      j45p41
    • RE: Bokeh Integration - Interactive Webbrowser Plotting

      Many thanks! got it working now - great work.

      posted in General Discussion
      J
      j45p41
    • RE: Bokeh Integration - Interactive Webbrowser Plotting

      Hi,

      thanks for the hard work here.

      when installing I get the error:

      byte-compiling build\bdist.win-amd64\egg\backtrader_plotting\bokeh\bokeh.py to bokeh.cpython-35.pyc
        File "build\bdist.win-amd64\egg\backtrader_plotting\bokeh\bokeh.py", line 41
          self.figures: List[Figure] = []
                      ^
      SyntaxError: invalid syntax
      
      
      

      Any ideas what I am doing wrong pls?

      posted in General Discussion
      J
      j45p41
    • Optimize Stop-Trail order values

      Hi,

      after posting "Create orders from CSV file" and getting quick and helpful feedabck. I have started using backtrader again and thanks to the great documentation I have now gotten to the stage where I can push in my own orders. I am now trying to:

      Optimize against stop order entry price and trailing stop distance.

      I have :

      1. declared parameters to be optimized
      2. referenced them under self.params.x
      3. added the “Strategy” hook stop method
      4. called the cerebro.optstategy function

      However I keep getting the same value back from the broker for all variances of the optimization parameters.

      Here is my code:

      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.feeds as btfeed
      import pandas as pd
      
      class PlotScheme(object):
          def __init__(self):
      
              # Default plotstyle for the OHLC bars which (line -> line on close)
              # Other options: 'bar' and 'candle'
              self.style = 'line'
      
      
      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)
          )
      
      # Create a Stratey
      class TestStrategy(bt.Strategy):
          params = (
              ('trail', 10),
              ('distance', 3),)
      
          def log(self, txt, dt=None):
              ''' Logging function fot this strategy'''
              dt = dt or self.datas[0].datetime.date(0)
              print('%s, %s' % (dt.isoformat(), txt))
      
          def __init__(self):
              # Keep a reference to the "close" line in the data[0] dataseries
              self.dataopen = self.datas[0].open
              self.datahigh = self.datas[0].high
              self.datalow = self.datas[0].low
              self.dataclose = self.datas[0].close
              self.datavolume = self.datas[0].volume
      
              # To keep track of pending orders and buy price/commission
              self.order = None
              self.buyprice = None
              self.buycomm = None
      
          def notify_order(self, order):
              if order.status in [order.Submitted, order.Accepted]:
                  # Buy/Sell order submitted/accepted to/by broker - Nothing to do
                  # print('Submitted/Accepted: ', str(self.data.datetime.time(0)))
      
                  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, Price: %.2f, Cost: %.2f, Comm %.2f' %
                          (order.executed.price,
                           order.executed.value,
                           order.executed.comm))
                      print(str(self.data.datetime.time(0)))
      
                      self.buyprice = order.executed.price
                      self.buycomm = order.executed.comm
                  else:  # Sell
                      self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                               (order.executed.price,
                                order.executed.value,
                                order.executed.comm))
                      print(str(self.data.datetime.time(0)))
      
                  self.bar_executed = len(self)
      
              elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                  self.log('Order Canceled/Margin/Rejected')
      
              self.order = None
      
          def notify_trade(self, trade):
              if not trade.isclosed:
                  return
      
              self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                       (trade.pnl, trade.pnlcomm))
      
          def next(self):
              global i,dt
      
              # Get datetime
              dt = self.datas[0].datetime.datetime()
      
              # Check if we are in the market
              try:
                  # if not self.position:
                  if orders['DATE'][i] == dt.strftime('%Y-%m-%d %H:%M:%S'):
                      if orders['DIRECTION'][i] == 'BUY':
                          self.log('OPEN BUY ORDER, %.2f' % self.dataclose[0])
                          self.order = self.buy(exectype=bt.Order.StopTrail, price=float(self.dataclose[0] + self.params.distance), trailamount=self.params.trail, valid=bt.Order.DAY)
                      elif orders['DIRECTION'][i] == 'SELL':
                          self.log('OPEN SELL ORDER, %.2f' % self.dataclose[0])
                          self.order = self.sell(exectype=bt.Order.StopTrail, price=float(self.dataclose[0] - self.params.distance), trailamount=self.params.trail, valid=bt.Order.DAY)
                      i = i + 1
      
                  if dt.strftime('%H:%M') == '21:00': self.close()
      
              except:
                  pass
      
          def stop(self):
              self.log('(Start distance %2d, Trail distance %2d) Ending Value %.2f' %
                       (self.params.distance, self.params.trail, self.broker.getvalue()))
      
      
      if __name__ == '__main__':
          # Create a cerebro entity
          cerebro = bt.Cerebro()
          i = 0
          state = False
      
          # Add a strategy
          # cerebro.addstrategy(TestStrategy)
      
          strats = cerebro.optstrategy(TestStrategy,distance=range(3,8), trail=range(3,8))
      
          datapath = os.path.join('backtrader/deepanalysis/US500/US50015m_bid_chart_data_with_vol.csv')
      
          # Create a Data Feed
          data = dataFeed(dataname=datapath, timeframe=bt.TimeFrame.Minutes, compression=15)
      
          # Read Orders
      
          orders = pd.read_csv('backtrader/deepanalysis/US500/US500_orders_20180601_to_20180815_Norm_priority.csv')
      
          # Add the Data Feed to Cerebro
          cerebro.adddata(data)
      
          # Set our desired cash start
          cerebro.broker.setcash(5000.0)
      
          # Add a FixedSize sizer according to the stake
          cerebro.addsizer(bt.sizers.FixedSize, stake=1)
      
          # Set the commission
          cerebro.broker.setcommission(commission=0.0)
      
          # Print out the starting conditions
          print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
      
          # Run over everything
          cerebro.run()
      
          # Print out the final result
          print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
      
      

      Here is the output that i get:

      C:\Users\jaspa\AppData\Local\conda\conda\envs\backtrader\python.exe C:/Users/jaspa/PycharmProjects/backtrader/US500_backtest_1.py
      Starting Portfolio Value: 5000.00
      2018-08-15, (Start distance  3, Trail distance  6) Ending Value 5000.00
      2018-08-15, (Start distance  3, Trail distance  7) Ending Value 5000.00
      2018-08-15, (Start distance  6, Trail distance  7) Ending Value 5000.00
      2018-08-15, (Start distance  4, Trail distance  6) Ending Value 5000.00
      2018-08-15, (Start distance  3, Trail distance  3) Ending Value 5000.00
      2018-08-15, (Start distance  3, Trail distance  4) Ending Value 5000.00
      2018-08-15, (Start distance  4, Trail distance  3) Ending Value 5000.00
      2018-08-15, (Start distance  5, Trail distance  5) Ending Value 5000.00
      2018-08-15, (Start distance  4, Trail distance  5) Ending Value 5000.00
      2018-08-15, (Start distance  5, Trail distance  6) Ending Value 5000.00
      2018-08-15, (Start distance  4, Trail distance  4) Ending Value 5000.00
      2018-08-15, (Start distance  3, Trail distance  5) Ending Value 5000.00
      2018-08-15, (Start distance  6, Trail distance  4) Ending Value 5000.00
      2018-08-15, (Start distance  7, Trail distance  4) Ending Value 5000.00
      2018-08-15, (Start distance  5, Trail distance  4) Ending Value 5000.00
      2018-08-15, (Start distance  5, Trail distance  3) Ending Value 5000.00
      2018-08-15, (Start distance  7, Trail distance  6) Ending Value 5000.00
      2018-08-15, (Start distance  6, Trail distance  6) Ending Value 5000.00
      2018-08-15, (Start distance  4, Trail distance  7) Ending Value 5000.00
      2018-08-15, (Start distance  5, Trail distance  7) Ending Value 5000.00
      2018-08-15, (Start distance  6, Trail distance  3) Ending Value 5000.00
      2018-08-15, (Start distance  7, Trail distance  5) Ending Value 5000.00
      2018-08-15, (Start distance  7, Trail distance  7) Ending Value 5000.00
      2018-08-15, (Start distance  6, Trail distance  5) Ending Value 5000.00
      2018-08-15, (Start distance  7, Trail distance  3) Ending Value 5000.00
      Final Portfolio Value: 5000.00
      
      Process finished with exit code 0
      
      
      

      Here is the output I get when I run the strategy with the default parameter values:

      C:\Users\jaspa\AppData\Local\conda\conda\envs\backtrader\python.exe C:/Users/jaspa/PycharmProjects/backtrader/US500_backtest_1.py
      Starting Portfolio Value: 5000.00
      2018-06-05, OPEN BUY ORDER, 2748.13
      2018-06-05, BUY EXECUTED, Price: 2749.75, Cost: 2749.75, Comm 0.00
      19:45:00
      2018-06-05, SELL EXECUTED, Price: 2751.51, Cost: 2749.75, Comm 0.00
      21:15:00
      2018-06-05, OPERATION PROFIT, GROSS 1.76, NET 1.76
      2018-06-06, OPEN SELL ORDER, 2755.69
      2018-06-07, OPEN BUY ORDER, 2775.99
      2018-06-07, BUY EXECUTED, Price: 2771.76, Cost: 2771.76, Comm 0.00
      20:30:00
      2018-06-07, SELL EXECUTED, Price: 2771.60, Cost: 2771.76, Comm 0.00
      21:15:00
      2018-06-07, OPERATION PROFIT, GROSS -0.16, NET -0.16
      2018-06-08, OPEN SELL ORDER, 2765.90
      2018-06-12, OPEN SELL ORDER, 2784.50
      2018-06-13, OPEN SELL ORDER, 2788.59
      2018-06-13, SELL EXECUTED, Price: 2780.88, Cost: -2780.88, Comm 0.00
      19:00:00
      2018-06-13, BUY EXECUTED, Price: 2773.30, Cost: -2780.88, Comm 0.00
      21:15:00
      2018-06-13, OPERATION PROFIT, GROSS 7.58, NET 7.58
      2018-06-14, OPEN BUY ORDER, 2783.62
      2018-06-15, OPEN BUY ORDER, 2769.40
      2018-06-15, BUY EXECUTED, Price: 2776.40, Cost: 2776.40, Comm 0.00
      19:15:00
      2018-06-15, SELL EXECUTED, Price: 2779.87, Cost: 2776.40, Comm 0.00
      21:15:00
      2018-06-15, OPERATION PROFIT, GROSS 3.47, NET 3.47
      2018-06-18, OPEN SELL ORDER, 2761.90
      2018-06-19, OPEN SELL ORDER, 2752.10
      2018-06-20, OPEN BUY ORDER, 2770.13
      2018-06-21, OPEN BUY ORDER, 2762.47
      2018-06-21, BUY EXECUTED, Price: 2760.22, Cost: 2760.22, Comm 0.00
      16:45:00
      2018-06-21, SELL EXECUTED, Price: 2749.00, Cost: 2760.22, Comm 0.00
      21:15:00
      2018-06-21, OPERATION PROFIT, GROSS -11.22, NET -11.22
      2018-06-25, OPEN SELL ORDER, 2733.98
      2018-06-25, SELL EXECUTED, Price: 2720.98, Cost: -2720.98, Comm 0.00
      15:00:00
      2018-06-25, BUY EXECUTED, Price: 2719.10, Cost: -2720.98, Comm 0.00
      21:15:00
      2018-06-25, OPERATION PROFIT, GROSS 1.88, NET 1.88
      2018-06-26, OPEN BUY ORDER, 2724.19
      2018-06-26, BUY EXECUTED, Price: 2730.26, Cost: 2730.26, Comm 0.00
      18:00:00
      2018-06-26, SELL EXECUTED, Price: 2725.91, Cost: 2730.26, Comm 0.00
      21:15:00
      2018-06-26, OPERATION PROFIT, GROSS -4.35, NET -4.35
      2018-06-27, OPEN SELL ORDER, 2730.00
      2018-06-27, SELL EXECUTED, Price: 2734.02, Cost: -2734.02, Comm 0.00
      16:00:00
      2018-06-27, BUY EXECUTED, Price: 2702.05, Cost: -2734.02, Comm 0.00
      21:15:00
      2018-06-27, OPERATION PROFIT, GROSS 31.97, NET 31.97
      2018-06-28, OPEN BUY ORDER, 2699.73
      2018-06-28, BUY EXECUTED, Price: 2707.06, Cost: 2707.06, Comm 0.00
      16:00:00
      2018-06-28, SELL EXECUTED, Price: 2717.05, Cost: 2707.06, Comm 0.00
      21:15:00
      2018-06-28, OPERATION PROFIT, GROSS 9.99, NET 9.99
      2018-06-29, OPEN BUY ORDER, 2735.20
      2018-06-29, BUY EXECUTED, Price: 2743.16, Cost: 2743.16, Comm 0.00
      16:00:00
      2018-06-29, SELL EXECUTED, Price: 2720.23, Cost: 2743.16, Comm 0.00
      21:15:00
      2018-06-29, OPERATION PROFIT, GROSS -22.93, NET -22.93
      2018-07-30, OPEN BUY ORDER, 2812.63
      2018-07-31, OPEN BUY ORDER, 2813.06
      2018-07-31, BUY EXECUTED, Price: 2819.25, Cost: 2819.25, Comm 0.00
      16:45:00
      2018-07-31, SELL EXECUTED, Price: 2822.88, Cost: 2819.25, Comm 0.00
      21:15:00
      2018-07-31, OPERATION PROFIT, GROSS 3.63, NET 3.63
      2018-08-01, OPEN SELL ORDER, 2819.48
      2018-08-01, SELL EXECUTED, Price: 2814.76, Cost: -2814.76, Comm 0.00
      16:45:00
      2018-08-01, BUY EXECUTED, Price: 2809.82, Cost: -2814.76, Comm 0.00
      21:15:00
      2018-08-01, OPERATION PROFIT, GROSS 4.94, NET 4.94
      2018-08-02, OPEN SELL ORDER, 2799.40
      2018-08-03, OPEN BUY ORDER, 2830.09
      2018-08-03, BUY EXECUTED, Price: 2838.84, Cost: 2838.84, Comm 0.00
      20:00:00
      2018-08-03, SELL EXECUTED, Price: 2838.85, Cost: 2838.84, Comm 0.00
      21:15:00
      2018-08-03, OPERATION PROFIT, GROSS 0.01, NET 0.01
      2018-08-06, OPEN SELL ORDER, 2837.96
      2018-08-07, OPEN SELL ORDER, 2858.17
      2018-08-08, OPEN BUY ORDER, 2855.45
      2018-08-09, OPEN SELL ORDER, 2856.91
      2018-08-09, SELL EXECUTED, Price: 2851.92, Cost: -2851.92, Comm 0.00
      20:45:00
      2018-08-09, BUY EXECUTED, Price: 2851.81, Cost: -2851.92, Comm 0.00
      21:15:00
      2018-08-09, OPERATION PROFIT, GROSS 0.11, NET 0.11
      2018-08-10, OPEN SELL ORDER, 2838.98
      2018-08-10, SELL EXECUTED, Price: 2829.47, Cost: -2829.47, Comm 0.00
      18:45:00
      2018-08-10, BUY EXECUTED, Price: 2835.86, Cost: -2829.47, Comm 0.00
      21:15:00
      2018-08-10, OPERATION PROFIT, GROSS -6.39, NET -6.39
      2018-08-13, OPEN BUY ORDER, 2837.68
      2018-08-13, BUY EXECUTED, Price: 2831.50, Cost: 2831.50, Comm 0.00
      19:15:00
      2018-08-13, SELL EXECUTED, Price: 2824.10, Cost: 2831.50, Comm 0.00
      21:15:00
      2018-08-13, OPERATION PROFIT, GROSS -7.40, NET -7.40
      2018-08-14, OPEN BUY ORDER, 2831.96
      2018-08-14, BUY EXECUTED, Price: 2840.96, Cost: 2840.96, Comm 0.00
      15:45:00
      2018-08-14, SELL EXECUTED, Price: 2839.56, Cost: 2840.96, Comm 0.00
      21:15:00
      2018-08-14, OPERATION PROFIT, GROSS -1.40, NET -1.40
      2018-08-15, OPEN SELL ORDER, 2822.43
      2018-08-15, SELL EXECUTED, Price: 2809.43, Cost: -2809.43, Comm 0.00
      15:00:00
      2018-08-15, (Start distance  3, Trail distance 10) Ending Value 5010.83
      Final Portfolio Value: 5010.83
      
      Process finished with exit code 0
      
      

      I'm sure it is probably something obvious but we all have to start somewhere :) All help greatly appreciated!

      posted in Indicators/Strategies/Analyzers
      J
      j45p41
    • RE: Create orders from CSV file

      @backtrader great! And thank you. Can’t wait to get stuck into this in the morning!

      posted in Indicators/Strategies/Analyzers
      J
      j45p41
    • Create orders from CSV file

      Hi,

      I have an external strategy that has already created my orders which have date/time stamps and order sizes.

      I would like to:

      1. import these orders and test against OHLC data that I have in CSV files
      2. use backtrader to optimise with different stop and limit values
      3. if possible test with trailing stops
      4. if possible implement a mechanism that has a "trailing start" - where I monitor the status of the last closing bar and decide whether or not execute the order in this CSV file.

      could somebody kindly tell me which of the above is possible with backtrader, and if possible, advise on how to implement?

      posted in Indicators/Strategies/Analyzers
      J
      j45p41
    • RE: Furtures data with missing days - how to handle

      @j45p41 Hi guys, with the additional info provided can you help me understand why my code is not processing trades? - thanks.

      posted in Indicators/Strategies/Analyzers
      J
      j45p41
    • RE: Furtures data with missing days - how to handle

      My apologies - i thought there was a problem due to discontinues dates.

      here is my code in which I have disabled my analysers as they end up giving me a keyerror. When disabled I get a graph that does not execute trades.

      import datetime
      import time
      import os.path
      import sys
      import backtrader as bt
      import backtrader.feeds as btfeed
      import ccxt
      import csv
      import io
      import pandas as pd
      from collections import OrderedDict
      from multiprocessing import Pool, cpu_count
      import math
      import os
      
      
      
      # DECLARE MODE FOR PROGRAM - OPTOMISATION OR STRATEGY
      opt_mode = False
      DEBUG = False
      
      # LOG OUTPUT TO FILE
      class Logger(object):
          def __init__(self, filename="Default.log"):
              self.terminal = sys.stdout
              self.log = open(filename, "a")
      
          def write(self, message):
              self.terminal.write(message)
              self.log.write(message)
      
          def flush(self):
              pass
      
      # CSV INPUT FILE FORMAT CONFIGURATION
      class dataFeed(btfeed.GenericCSVData):
          params = (
              ('dtformat', '%Y%m%d'),
              ('datetime', 0),
              ('open', 1),
              ('high', 2),
              ('low', 3),
              ('close', 4),
              ('volume', 5),
              ('openinterest', 6)
          )
      class OrderObserver(bt.observer.Observer):
          lines = ('created', 'expired',)
      
          plotinfo = dict(plot=True, subplot=True, plotlinelabels=True)
      
          plotlines = dict(
              created=dict(marker='*', markersize=8.0, color='lime', fillstyle='full'),
              expired=dict(marker='s', markersize=8.0, color='red', fillstyle='full')
          )
      
          def next(self):
              for order in self._owner._orderspending:
                  if order.data is not self.data:
                      continue
      
                  if not order.isbuy():
                      continue
      
                  # Only interested in "buy" orders, because the sell orders
                  # in the strategy are Market orders and will be immediately
                  # executed
      
                  if order.status in [bt.Order.Accepted, bt.Order.Submitted]:
                      self.lines.created[0] = order.created.price
      
                  elif order.status in [bt.Order.Expired]:
                      self.lines.expired[0] = order.created.price
      
      # MAIN STRATEGY DEFINITION - DEFINE VALUES HERE FOR NON-OPTOMISATION MODE
      class firstStrategy(bt.Strategy):
          params = (
              ("period", 28),
              ("rsi_low", 30),
              ("rsi_high", 70),
          )
      
          #TRADE LOGGING FUNCTION
          def log(self, txt, dt=None):
              ''' Logging function fot this strategy'''
              if not opt_mode:
                  dt = dt or self.datas[0].datetime.datetime(0)
                  print('%s, %s' % (dt.isoformat(), txt))
      
          def __init__(self):
              self.startcash = self.broker.getvalue()
              self.rsi = bt.indicators.RSI_SMA(self.data.close, period=self.params.period, safediv=True)
      
      
          #TRADE LOGGING FUNCTION
          def notify_trade(self, trade):
              if not trade.isclosed and not opt_mode:
                  return
      
              self.log('TRADE INFO, PRICE  %.2f, GROSS %.2f, NET %.2f' %
                       (trade.price, trade.pnl, trade.pnlcomm))
      
          def next(self):
              if not self.position:
                  if self.rsi < self.params.rsi_low:
                      self.buy(size=10)
              else:
                  if self.rsi > self.params.rsi_high:
                      self.sell(size=10)
              if opt_mode and DEBUG:
                  print('period: {}, rsi low: {}, rsi high {}'.format(self.params.period,self.params.rsi_low,self.params.rsi_high))
      
      # if opt_mode == False:
      #     def printTradeAnalysis(analyzer):
      #         '''
      #         Function to print the Technical Analysis results in a nice format.
      #         '''
      #         #Get the results we are interested in
      #         total_open = analyzer.total.open
      #         total_closed = analyzer.total.closed
      #         total_won = analyzer.won.total
      #         total_lost = analyzer.lost.total
      #         win_streak = analyzer.streak.won.longest
      #         lose_streak = analyzer.streak.lost.longest
      #         pnl_net = round(analyzer.pnl.net.total,2)
      #         strike_rate = round((total_won / total_closed) * 100,2)
      #         #Designate the rows
      #         h1 = ['Total Open', 'Total Closed', 'Total Won', 'Total Lost']
      #         h2 = ['Strike Rate','Win Streak', 'Losing Streak', 'PnL Net']
      #         r1 = [total_open, total_closed,total_won,total_lost]
      #         r2 = [strike_rate, win_streak, lose_streak, pnl_net]
      #         #Check which set of headers is the longest.
      #         if len(h1) > len(h2):
      #             header_length = len(h1)
      #         else:
      #             header_length = len(h2)
      #         #Print the rows
      #         print_list = [h1,r1,h2,r2]
      #         row_format ="{:<15}" * (header_length + 1)
      #         print("Trade Analysis Results:")
      #         for row in print_list:
      #             print(row_format.format('',*row))
      #
      #     def printSQN(analyzer):
      #         sqn = round(analyzer.sqn,2)
      #         print('SQN: {}'.format(sqn))
      
      # INPUT CONDITIONS TO FEED INTO CEREBRO IS ADDED HERE
      if __name__ == '__main__':
          sys.stdout = Logger("strat_evaluator.log")
      
      
          #periods = pd.DataFrame(columns=['FROM','TO'],index=[1,2,3,4,5,6,7,8,9,10,11,12])
          periods = pd.DataFrame(columns=['FROM','TO'],index=[1])
          periods.loc[1] = ('1990-1-01','2017-12-31')
          #periods.loc[2] = ('2017-02-01','2017-03-01')
          #periods.loc[3] = ('2017-03-01','2017-04-01')
          #periods.loc[4] = ('2017-04-01','2017-05-01')
          #periods.loc[5] = ('2017-05-01','2017-06-01')
          #periods.loc[6] = ('2017-06-01','2017-07-01')
          #periods.loc[7] = ('2017-07-01','2017-08-01')
          #periods.loc[8] = ('2017-08-01','2017-09-01')
          #periods.loc[9] = ('2017-09-01','2017-10-01')
          #periods.loc[10] = ('2017-10-01','2017-11-01')
          #periods.loc[11] = ('2017-11-01','2017-12-01')
          #periods.loc[12] = ('2017-12-01','2017-12-31')
      
          for index, row in periods.iterrows():
      
      
              # Variable for our starting cash
              startcash = 10000
              # Create an instance of cerebro
              cerebro = bt.Cerebro(optreturn=False)
      
              # Timing the whole operation
              time_at_start = time.time()
      
              if opt_mode:
                  # ADD STRATEGY OPTIMISATION
                  #cerebro.optstrategy(firstStrategy, period=range(11, 20), rsi_low=range(10, 50), rsi_high=range(51, 85))
                  cerebro.optstrategy(firstStrategy, period=range(13, 14), rsi_low=range(20, 21), rsi_high=range(40, 41))
                  cerebro.addanalyzer(bt.analyzers.SharpeRatio)
              else:
                  #ADD STRATEGY
                  cerebro.addstrategy(firstStrategy)
      
              #format dates for datafeed object
              fy,fm,fd = periods['FROM'][index].split('-')
              ty,tm,td = periods['TO'][index].split('-')
      
      
      #READ DATA FROM CSV FILE
      
              filename = 'tickerData/F_BO.txt'
              modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
              datapath = os.path.join(modpath,str(filename))
              data = dataFeed(dataname=datapath, timeframe=bt.TimeFrame.Days,
                              fromdate=datetime.datetime(int(fy),int(fm),int(fd)),
                              todate=datetime.datetime(int(ty),int(tm),int(td)),)
      
              # Add the data to Cerebro
              cerebro.adddata(data)
      
              # Set our desired cash start
              cerebro.broker.setcash(startcash)
      
              if not opt_mode:
                  # Add the analyzers we are interested in
                  cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name="ta")
                  cerebro.addanalyzer(bt.analyzers.SQN, _name="sqn")
      
      
              #WRITER TEST
              #cerebro.addwriter(bt.WriterFile, csv=True, rounding=2)
      
              # RUN STRATEGY THROUGH CEREBRO USING INPUT DATA
              # Timing the operation
              time_at_end = time.time()
              time_elapsed = round(time_at_end - time_at_start,2)
              print('Time elapsed: {} seconds'.format(time_elapsed))
              print ('Running Cerebro')
              if not opt_mode: opt_runs = cerebro.run(tradehistory=False)
              else: opt_runs = cerebro.run(tradehistory=False, runonce = False, Exactbars=True)
      
              firstStrat = opt_runs[0]
      
              if opt_mode:
                  # 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 IN OPTIMISATION AND FILTER TOP 3
                  result_number = 0
                  print('Results: Ordered by Profit:')
                  for result in by_PnL:
                      if result_number < 3:
                          print('Asset: {} Start: {}, End: {}, Period: {}, rsi_low: {}, rsi_high: {}, PnL: {}'.format(filename, periods['FROM'][index], periods['TO'][index], result[0], result[1], result[2], result[3]))
                          result_number = result_number + 1
      
              # Timing the operation
              time_at_end = time.time()
              time_elapsed = round(time_at_end - time_at_start,2)
      
      
              print('Time elapsed: {} seconds'.format(time_elapsed))
              if opt_mode == False:
                  # print the analyzers
                  # printTradeAnalysis(firstStrat.analyzers.ta.get_analysis())
                  # printSQN(firstStrat.analyzers.sqn.get_analysis())
      
                  #Get final portfolio Value
                  portvalue = cerebro.broker.getvalue()
      
                  #Print out the final result
                  print('Final Portfolio Value: ${}'.format(portvalue))
                  cerebro.plot(style='candlestick')
      
              #cerebro.plot(style='candlestick')
      
      

      for completeness here is the data that I am using

      DATE, OPEN, HIGH, LOW, CLOSE, VOL, OI, P, R, RINFO
      19900102,11520.0000,11520.0000,11316.0000,11322.0000,19779,38563,0,0,0.0000
      19900103,11322.0000,11460.0000,11298.0000,11442.0000,16270,39377,0,0,0.0000
      19900104,11472.0000,11520.0000,11340.0000,11346.0000,12743,39220,0,0,0.0000
      19900105,11298.0000,11466.0000,11286.0000,11418.0000,11808,39932,0,0,0.0000
      19900108,11448.0000,11808.0000,11442.0000,11784.0000,20844,40091,0,0,0.0000
      19900109,11730.0000,11820.0000,11682.0000,11778.0000,19457,39502,0,0,0.0000
      19900110,11760.0000,11778.0000,11598.0000,11724.0000,16266,39703,0,0,0.0000
      19900111,11712.0000,11790.0000,11706.0000,11754.0000,13699,39704,0,0,0.0000
      19900112,11826.0000,11844.0000,11634.0000,11640.0000,12677,38444,0,0,0.0000
      19900115,11598.0000,11688.0000,11580.0000,11652.0000,6067,38307,0,0,0.0000
      19900116,11610.0000,11640.0000,11490.0000,11496.0000,13691,37511,0,0,0.0000
      19900117,11484.0000,11616.0000,11484.0000,11502.0000,12378,38223,0,0,0.0000
      19900118,11508.0000,11580.0000,11496.0000,11538.0000,8570,37584,0,0,0.0000
      19900119,11562.0000,11568.0000,11400.0000,11406.0000,14732,36865,0,0,0.0000
      19900122,11400.0000,11448.0000,11316.0000,11358.0000,15163,36837,0,0,0.0000
      19900123,11382.0000,11508.0000,11376.0000,11466.0000,13141,36918,0,0,0.0000
      19900124,11472.0000,11514.0000,11436.0000,11448.0000,10550,36551,0,0,0.0000
      19900125,11472.0000,11478.0000,11340.0000,11340.0000,14579,35655,0,0,0.0000
      19900126,11340.0000,11430.0000,11328.0000,11418.0000,7547,34389,0,0,0.0000
      19900129,11430.0000,11544.0000,11370.0000,11538.0000,11285,34198,0,0,0.0000
      19900130,11544.0000,11574.0000,11442.0000,11460.0000,12167,33318,0,0,0.0000
      19900131,11460.0000,11544.0000,11430.0000,11502.0000,10708,32328,0,0,0.0000
      19900201,11520.0000,11700.0000,11502.0000,11532.0000,17957,32443,0,0,0.0000
      19900202,11544.0000,11580.0000,11508.0000,11568.0000,14151,31419,0,0,0.0000
      19900205,11568.0000,11634.0000,11460.0000,11478.0000,14241,30695,0,0,0.0000
      
      posted in Indicators/Strategies/Analyzers
      J
      j45p41
    • Furtures data with missing days - how to handle

      Hi,

      I am trying to read in futures data in the following fomat:

      DATE, OPEN, HIGH, LOW, CLOSE, VOL, OI, P, R, RINFO
      19900531,104687.5000,104850.0000,104387.5000,104525.0000,18592,32108,0,0,0.0000
      19900601,104750.0000,105512.5000,104612.5000,104762.5000,26697,27205,0,0,0.0000
      19900604,104250.0000,104562.5000,103937.5000,104437.5000,15315,25228,0,0,0.0000
      19900605,104575.0000,105250.0000,104425.0000,105137.5000,18054,25452,0,0,0.0000
      19900606,105187.5000,105437.5000,105112.5000,105300.0000,10104,24872,0,0,0.0000
      19900607,105250.0000,105450.0000,105137.5000,105425.0000,9931,24237,199009,199009,0.0000
      19900608,103562.5000,103562.5000,103125.0000,103437.5000,12791,9134,0,0,-1600.0000
      

      I intend to trim the data so that it does not include the last three columns.

      However when I run using this data, due to it not being continuous days cerebro does not process trades correctly - the graphs is plotted but the trades do not execute.

      I suspect there is a setting somewhere which will allow this data to be handled.

      I have read: https://www.backtrader.com/blog/posts/2016-08-31-rolling-over-futures/rolling-futures-over.html

      but can't figure out how to handle this data - any suggestions pls?

      posted in Indicators/Strategies/Analyzers
      J
      j45p41
    • RE: Strategy Library

      @backtrader Thank you for your answer and I am sure a library will be coming together soon. I will certainly contribute as I get further into my backtrader journey :)

      posted in Indicators/Strategies/Analyzers
      J
      j45p41