Navigation

    Backtrader Community

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

    Edward Owen

    @Edward Owen

    2
    Reputation
    6
    Profile views
    8
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    Edward Owen Unfollow Follow

    Best posts made by Edward Owen

    • RE: Using Donchian Channel to execute buy order

      ah, i shouldve put the results, sorry. I already found the fix :D

      posted in General Code/Help
      Edward Owen
      Edward Owen
    • RE: Sizer problem

      @ab_trader said in Sizer problem:

      @Edward-Owen said in Sizer problem:

      Some of the costs are negative.

      cost = size x price
      size is negative for short position, therfore cost is also negative.

      I am quite new to python and backtrader, can you point me out which code is shorting my trades, I thought that my code only goes long.

      posted in General Code/Help
      Edward Owen
      Edward Owen

    Latest posts made by Edward Owen

    • RE: Running a backtest from a single class

      i got it!

      I insert few functions to call the values from bt.cerebro to mimic cerebro.broker.getcash()
      e1f3fe8c-e177-4593-b58d-41f3851178cc-image.png

      but any other solutions are welcome!

      posted in General Code/Help
      Edward Owen
      Edward Owen
    • Running a backtest from a single class

      Hi,

      I am doing a web project using Backtrader for my class. Basically, the web page allows users to input variables such as initial cash, indicator values, risk management values, etc, and run a simple backtest with Backtrader from the web itself.

      As far as I know, to run a simple strategy you'll need to

      1. Instantiate Cerebro
      2. cerebro.broker.addstrategy(strategy)
      3. Add Data and set cash
      4. cerebro.run()

      To backtest from the web I have to run the backtest from a single class. I named the class "Simulate" and have decided to insert steps 1-4 into the class' __ init __

      class Simulate:
      
          def __init__(self, initialCash):
              self.cash = initialCash
              self.cerebro = bt.Cerebro()
              #self.TestStrategy = TestStrategy()
              self.cerebro.addstrategy(TestStrategy)
      
              data = bt.feeds.YahooFinanceCSVData(
                  dataname="datas/Misc/orcl-1995-2014.txt",
                  fromdate=datetime.datetime(2000, 1, 1),
                  todate=datetime.datetime(2000, 12, 31),
                  reverse=False)
      
              self.cerebro.adddata(data)
              self.cerebro.broker.setcash(self.cash)
              print('Starting Portfolio Value: %.2f' % self.cerebro.broker.getvalue())
              self.cerebro.run()
              print('Final Portfolio Value: %.2f' % self.cerebro.broker.getvalue())
              self.cerebro.plot(style="candlestick", barup='green', bardown='red')
      

      The bt.strategy class that I will be using is outside of the "Simulate" class.

      class Simulate: ...
      class TestStrategy(bt.Strategy): ...
      

      Let's say in this example I wanted to log the "Initial Cash" every time I place a Buy order. This "Initial Cash" is supposed to be in Simulate's __ init __

      class Simulate:
      
          def __init__(self, initialCash):
              self.cash = initialCash
      

      and to log

      1. Buy Create's Close
      2. Current Cash
      3. Initial Cash
      self.log('BUY CREATE, %.2f, Cash: %.2f, Initial Cash:%.2f' %                
      ( self.dataclose[0],self.cerebro.broker.getcash(), self.cash))
      

      How do I get the values from Simulate class to the strategy class, I've been trying to solve this for days, but just can't figure it out. Please help :c

      .
      .
      .
      Here is the full code(the strategy is an example strategy from the quickstart docs):

      
      from __future__ import (absolute_import, division, print_function,
                              unicode_literals)
      import backtrader as bt
      import datetime
      
      class Simulate:
      
          def __init__(self, initialCash):
              self.cash = initialCash
              self.cerebro = bt.Cerebro()
              #self.TestStrategy = TestStrategy()
              self.cerebro.addstrategy(TestStrategy)
      
              data = bt.feeds.YahooFinanceCSVData(
                  dataname="datas/Misc/orcl-1995-2014.txt",
                  fromdate=datetime.datetime(2000, 1, 1),
                  todate=datetime.datetime(2000, 12, 31),
                  reverse=False)
      
              self.cerebro.adddata(data)
              self.cerebro.broker.setcash(self.cash)
              print('Starting Portfolio Value: %.2f' % self.cerebro.broker.getvalue())
              self.cerebro.run()
              print('Final Portfolio Value: %.2f' % self.cerebro.broker.getvalue())
              self.cerebro.plot(style="candlestick", barup='green', bardown='red')
      
      class TestStrategy(bt.Strategy):
          def log(self, txt, dt=None):
              dt = dt or self.datas[0].datetime.date(0)
              print('%s, %s' % (dt.isoformat(), txt))
          def __init__(self):
              self.dataclose = self.datas[0].close
      
          def notify_order(self, order):
              if order.status in [order.Submitted, order.Accepted]:
                  return
              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')
              self.order = None
          def next(self):
                  self.log('Close, %.2f' % self.dataclose[0])
                  if self.dataclose[0] < self.dataclose[-1]:
                      if self.dataclose[-1] < self.dataclose[-2]:
                          self.log('BUY CREATE, %.2f, Cash: %.2f, Initial Cash:%.2f' %
                                   ( self.dataclose[0],self.cerebro.broker.getcash(),
                                     self.cash))
                          self.buy()
      
      Simulate(100000)
      
      posted in General Code/Help
      Edward Owen
      Edward Owen
    • RE: Sizer problem

      thankss!

      posted in General Code/Help
      Edward Owen
      Edward Owen
    • RE: Sizer problem

      @ab_trader said in Sizer problem:

      @Edward-Owen said in Sizer problem:

      Some of the costs are negative.

      cost = size x price
      size is negative for short position, therfore cost is also negative.

      I am quite new to python and backtrader, can you point me out which code is shorting my trades, I thought that my code only goes long.

      posted in General Code/Help
      Edward Owen
      Edward Owen
    • RE: Sizer problem

      @ab_trader okay that makes sense

      posted in General Code/Help
      Edward Owen
      Edward Owen
    • Sizer problem

      So I tried using an example sizer from Backtest-Rookies and implemented it to my own code
      https://backtest-rookies.com/2017/07/24/developing-sizers-backtrader-part-1/


      #This is the example code that they provided:

      class MaxRiskSizer(bt.Sizer):
          '''
          Returns the number of shares rounded down that can be purchased for the
          max rish tolerance
          '''
          params = (('risk', 0.03),)
      
          def __init__(self):
              if self.p.risk > 1 or self.p.risk < 0:
                  raise ValueError('The risk parameter is a percentage which must be'
                      'entered as a float. e.g. 0.5')
      
          def _getsizing(self, comminfo, cash, data, isbuy):
              if isbuy:
                  size = math.floor((cash * self.p.risk) / data[0])
              else:
                  size = math.floor((cash * self.p.risk) / data[0]) * -1
              return size
      
      cerebro.addsizer(MaxRiskSizer, risk=0.5)
      
      

      ...............................................................................................................................................................
      I set the risk at (risk = 0.5) , so it should mean I am going to use 50% of the portfolio to enter a trade right?

      #This is my code(I seperated the stategy class and main):

      1. Main:
      import backtrader as bt
      import datetime
      import math
      from Strategy import TestStrategy
      
      cerebro = bt.Cerebro()
      cerebro.broker.set_cash(100000)
      cerebro.broker.setcommission(0.01)
      data = bt.feeds.YahooFinanceCSVData(
          dataname="oracle.csv",
          fromdate=datetime.datetime(2000,3,1),
          todate=datetime.datetime(2000,4,29),
          reverse=False)
      class MaxRiskSizer(bt.Sizer):
          '''
          Returns the number of shares rounded down that can be purchased for the
          max rish tolerance
          '''
          params = (('risk', 0.03),)
      
          def __init__(self):
              if self.p.risk > 1 or self.p.risk < 0:
                  raise ValueError('The risk parameter is a percentage which must be'
                      'entered as a float. e.g. 0.5')
      
          def _getsizing(self, comminfo, cash, data, isbuy):
              if isbuy:
                  size = math.floor((cash * self.p.risk) / data[0])
              else:
                  size = math.floor((cash * self.p.risk) / data[0]) * -1
              return size
      
      cerebro.adddata(data)                   #Insert Data.
      cerebro.addstrategy(TestStrategy)
      #cerebro.addsizer(bt.sizers.FixedSize, stake=2)
      cerebro.addsizer(MaxRiskSizer, risk=0.5)
      
      
      print("Starting Portfolio :%.2f" % cerebro.broker.getvalue())
      print()
      cerebro.run()
      print("Final Portfolio Value:%.2f" % cerebro.broker.getvalue())
      cerebro.plot(style="candlestick",barup='green', bardown='red')
      
      1. Strategy class :
      import backtrader as bt
      
      class TestStrategy(bt.Strategy):
      
          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.datas[0].close
              # 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]:
                  return
      
              # Check if an order has been completed. Broker could reject 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))
      
                      self.buyprice = order.executed.price
                      self.buycomm = order.executed.comm
      
                  elif order.issell():
                      self.log("SELL 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 Cancled/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))
              print()
      
          def next(self):
              # Simply log the closing price of the series from the reference
              #self.log('Close, %.2f' % self.dataclose[0])
      
              if self.order:
                  return
      
              #If we are not in the market, we might buy.
              if not self.position:
                  if self.dataclose[0] < self.dataclose[-1]:
                      # current close less than previous close
      
                      if self.dataclose[-1] < self.dataclose[-2]:
                          # previous close less than the previous previous close
      
                          # BUY, BUY, BUY!!! (with all possible default parameters)
                          self.log('BUY CREATED, %.2f' % self.dataclose[0])
                          self.order = self.buy()
              else:
                  if len(self) >= (self.bar_executed + 5):
                      self.log("SELL CREATED {}".format(self.dataclose[0]))
                      self.order = self.sell()
      
      

      ...............................................................................................................................................................
      Starting Portfolio :100000.00

      2000-03-02, BUY CREATED, 30.47
      2000-03-03, BUY EXECUTED,Price: 31.63, Cost: 51873.20, Comm 518.73
      2000-03-10, SELL CREATED 36.3
      2000-03-13, SELL EXECUTED,Price: 34.91, Cost: 20717.65, Comm 228.66
      2000-03-20, SELL CREATED 34.75
      2000-03-21, SELL EXECUTED,Price: 34.63, Cost: 30289.80, Comm 349.76
      2000-03-21, OPERATION PROFIT, GROSS 5103.40 NET 4014.90

      2000-03-28, SELL CREATED 38.5
      2000-03-29, SELL EXECUTED,Price: 38.28, Cost: -52099.08, Comm 520.99
      2000-04-05, SELL CREATED 34.8
      2000-04-06, SELL EXECUTED,Price: 35.86, Cost: -80577.42, Comm 805.77
      2000-04-13, SELL CREATED 31.99
      2000-04-14, SELL EXECUTED,Price: 31.10, Cost: -114821.20, Comm 1148.21
      2000-04-24, SELL CREATED 32.22
      2000-04-25, SELL EXECUTED,Price: 33.30, Cost: -180785.70, Comm 1807.86
      Final Portfolio Value:75467.86
      ...............................................................................................................................................................

      Problem is:

      1. Just on the first buy, my portfolio starts at $100k but it uses $51.8k instead of amount < $50k. (Note: risk is 0.5)

      2. Some of the costs are negative. :/

      so,
      how do I fix the negative, is there something I am missing out or don't understand?

      posted in General Code/Help
      Edward Owen
      Edward Owen
    • RE: Using Donchian Channel to execute buy order

      ah, i shouldve put the results, sorry. I already found the fix :D

      posted in General Code/Help
      Edward Owen
      Edward Owen
    • Using Donchian Channel to execute buy order

      hi,

      I am new to backtrader and even python. I know I shouldn't be rushing but I just wanna get this to work. I have only watched a few tutorials on backtrading but not much.

      So I am planning to use the provided
      https://www.backtrader.com/recipes/indicators/donchian/donchian/
      and use it to execute a buy order on DC 5 day.

      Here is the code
      import backtrader as bt
      import datetime

      cerebro = bt.Cerebro()
      cerebro.broker.set_cash(1000000)
      data = bt.feeds.YahooFinanceCSVData(
      dataname="oracle.csv",
      fromdate=datetime.datetime(2000,1,1),
      todate=datetime.datetime(2000,12,31),
      reverse=False)

      cerebro.adddata(data) #Insert Data.

      class DonchianChannels(bt.Strategy):
      #DONCHIAN CHANNELS PLOTTING
      alias = ('DCH', 'DonchianChannel',)
      lines = ( 'dch', 'dcl',) # dc middle, dc high, dc low
      params = dict(
      period=5,
      lookback=-1, #look at Params Note.
      )
      plotinfo = dict(subplot=False) # plot along with data
      plotlines = dict(
      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):
          self.dataclose = self.datas[0].close
          self.order = None
          #DC
          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
          
      def next(self):
          # Simply log the closing price of the series from the reference
          self.log('Close, %.2f' % self.dataclose[0])
      
          if self.order:
              return
      
          if not self.position:
              if self.dataclose[-1] < self.l.dch:
                  # previous close less than the previous previous close
      
                  # BUY, BUY, BUY!!! (with all possible default parameters)
                  self.log('BUY CREATE, %.2f' % self.dataclose[0])
                  self.order = self.buy()
          else:
              if len(self) >= (self.bar_executed + 5):
                  self.log("SELL CREATED {}".format(self.dataclose[0]))
                  self.order = self.sell()
      

      cerebro.addstrategy(DonchianChannels)

      cerebro.addsizer(bt.sizers.FixedSize, stake=1000)
      print("Starting Portfolio :%.2f" % cerebro.broker.getvalue())
      cerebro.run()
      print("Final Portfolio Value:%.2f" % cerebro.broker.getvalue())
      cerebro.plot(style="candlestick",barup='green', bardown='red')

      posted in General Code/Help
      Edward Owen
      Edward Owen