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/

    Kernel Freeze! Can someone help to vet through my first-ever backtrader code?

    General Code/Help
    1
    1
    26
    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.
    • mama1baba
      mama1baba last edited by

      Trading Instrument : Futures
      Position sizing : 1% of total capital / Margin per lot; rounding down to nearest whole number
      Indicator(s):

      • Donchian Channel : 20 periods
      • ATR : 20 periods
      • Exp Moving Avg : 25 and 350 EMA

      Trading Plan:

      • Buy if closing Price breaks above Donchian Upper Band & 25 EMA > 350 EMA
      • Sell if closing price breaks below Donchian Lower Band & 25 EMA < 350 EMA
      • Profit Target & Stop Loss : 2 x ATR(20) of the entry price

      Code Snippets:

      import backtrader as bt
      import datetime # For datetime objects
      
      
      
      # Create a custom datafeed from csv
      class customCSV(bt.feeds.GenericCSVData):
          params = (
              ('fromdate', datetime.datetime(2000, 1, 1)),
              ('todate', datetime.datetime(2020, 8, 31)),
              ('dtformat', '%Y-%m-%d'),
              
              ('datetime', 0), #index column
              ('open', 1),
              ('high', 2),
              ('low', 3),
              ('close', 4),
              ('volume', 5),
              ('openinterest', -1), #did not import this column
              
              )
      
      class FixedPerc(bt.Sizer):
          '''This sizer simply returns a fixed size for any operation
      
          Params:
            - ``perc`` (default: ``0.20``) Perc of cash to allocate for operation
            - ``margin`` (default : 5000) Margin per lot
          '''
          params = (
              ('perc', 0.01),
              ('margin', 5000) # margin per lot
              )
          
          def _getsizing(self, comminfo, cash, data, isbuy):
              cashtouse = self.p.perc * cash
              size = cashtouse // self.p.margin
              
              return size
      
      # Donchian Channel Indicator
      class DonchianChannels(bt.Indicator):
          '''
          Params Note:
            - ``lookback`` (default: -1)
      
              If `-1`, the bars to consider will start 1 bar in the past and the
              current high/low may break through the channel.
      
              If `0`, the current prices will be considered for the Donchian
              Channel. This means that the price will **NEVER** break through the
              upper/lower channel bands.
          '''
      
          alias = ('DCH', 'DonchianChannel',)
      
          lines = ('dcm', 'dch', 'dcl',)  # dc middle, dc high, dc low
          params = dict(
              period=20,
              lookback=-1,  # consider current bar or not
          )
      
          plotinfo = dict(subplot=False)  # plot along with data
          plotlines = dict(
              dcm=dict(ls='--'),  # dashed line
              dch=dict(_samecolor=True),  # use same color as prev line (dcm)
              dcl=dict(_samecolor=True),  # use same color as prev line (dch)
          )
      
          def __init__(self):
              hi, lo = self.data.high, self.data.low
              if self.p.lookback:  # move backwards as needed
                  hi, lo = hi(self.p.lookback), lo(self.p.lookback)
      
              self.l.dch = bt.ind.Highest(hi, period=self.p.period)
              self.l.dcl = bt.ind.Lowest(lo, period=self.p.period)
              self.l.dcm = (self.l.dch + self.l.dcl) / 2.0  # avg of the above
      
      
      # Create a Strategy
      class TestStrategy(bt.Strategy):
          
          # Set the parameters
          params = (
              ('fast_ema_period', 25),
              ('slow_ema_period', 350),
              ('donchian_period', 20),
              ('ATR_period', 20),
              ('ATR_dist', 2.0)
              )
          
          def log(self, txt, dt = None):
              ''' Logging Function for 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.dataclose = self.data.close[0]
              
              # Set up the indicators
              self.emafast = bt.indicators.ExponentialMovingAverage(self.dataclose,
                  period = self.p.fast_ema_period)
              self.emaslow = bt.indicators.ExponentialMovingAverage(self.dataclose,
                  period = self.p.slow_ema_period)
              self.donchian = DonchianChannels()
              self.atr = bt.indicators.ATR(self.datas[0],
                                           period=self.p.ATR_period)
              
              # Keep track of pending order + 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 by broker. Do nothing
                  return 
              
              #Check if order has been completed
              if order.status in [Order.Completed]:
                  if order.isbuy():
                      self.log(
                          'LONG EXECUTED, Price: %.2f, Cost: %.2f, Comm: %.2f' % 
                          (order.executed.price,
                           order.executed.value,
                           order.executed.comm))
                      
                      self.buyprice = order.executed.price
                      self.buycomm = order.executed.comm
                  
                  else: # Sell
                      self.log(
                          'SHORT EXECUTED, Price: %.2f, Cost: %.2f, Comm: %.2f' % 
                          (order.executed.price,
                           order.executed.value,
                           order.executed.comm))
                      
                  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
              
              # open position PnL
              self.log('OPERATION PROFIT, Gross %.2f, Net %.2f' %
                       (trade.pnl, trade.pnlcomm))
                      
      
          def next(self):
              # Log closing price for reference
              self.log('Close, %.2f' % self.dataclose)
              
              # Check if an order is pending, if yes then we do nothing
              if self.order:
                  return
              
              # set up parameters for SL and TP
              pdist = self.atr[0] * self.p.ATR_dist
              long_stop = self.dataclose - pdist
              short_stop = self.dataclose + pdist
              long_profit = self.dataclose + pdist
              short_profit = self.dataclose - pdist
              
              # Check if we are in the market
              if not self.position: # not in the market
                  # Trade Logic
                  if self.dataclose > self.donchian.dch[0]:
                      if self.emafast[0] > self.emaslow[0]:
                          # Place BUY trade : 1% of portfolio value
                          self.log('BUY CREATE, %.2f' % self.dataclose)
                          self.order_target_percent(target = 0.01)
                          self.buy()
                          
                  
                  elif self.dataclose < self.donchian.dcl[0]:
                      if self.emafast[0] < self.emaslow[0]:
                          # Place SELL trade : 1% of portfolio value
                          self.log('SELL CREATE, %.2f' % self.dataclose)
                          self.order_target_percent(target = 0.01)
                          self.sell()
                          
      
                          
              else: # in the market
                  if self.position.size > 0: # For long positions
                      if self.dataclose < long_stop or self.dataclose > long_profit:
                          self.close()
                  elif self.position.size < 0: # For short positions
                      if self.dataclose > short_stop or self.dataclose < short_profit:
                          self.close()
                  else:
                      return
                      
      
      # Setting the Cash
      
      if __name__ == '__main__':
          
          # Create a cerebro entity
          cerebro = bt.Cerebro()
          
          # Add a strategy
          cerebro.addstrategy(TestStrategy)
          
          # Create a data feed
          data = customCSV(dataname = 'CrudeDaily.csv')
          
          # Add the data feed to cerebro
          cerebro.adddata(data)
          
          # Set our desired cash start
          cerebro.broker.setcash(500000.0)
          
          # Add a sizer according to stake
          cerebro.addsizer(FixedPerc)
      
          # Set the commission 
          cerebro.broker.setcommission(commission = 5.0, margin = 5000.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())
          
      

      Thank You for the help!

      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(); }); }