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/

    Problem with using ATR multiplier as stoploss and printing CASH.

    General Code/Help
    2
    7
    296
    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.
    • G
      Gleetche last edited by

      Hello, I am new to backtrader. I have several questions, i will post them down below the original code. This is what I wanna do:

      1. Only take long positions.
      2. Use donchian channel's 20 day high as open
      3. Use 4 multipler ATR (14 day period) as stoploss/to exit long position.
      4. Risk

      Here is the original code:

      import backtrader as bt
      import datetime
      import math
      
      class DonchianChannels(bt.Indicator):
          alias = ('DCH', 'DonchianChannel',)
          lines = ('dcm', 'dch', 'dcl',)  # dc middle, dc high, dc low
          params = dict(
              period=   20,
              lookback= -1,  # (-1) = doesnt current bar
          )
          plotinfo = dict(subplot=False)  # plot along with dataa
          plotlines = dict(
              dch=dict(color="black"),  # use same color as prev line (dcm)
              #dcl=dict(_samecolor=False),  # 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)
      
      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
      
      class TestStrategy(bt.Strategy):
      
          params = dict(
              pfast=20,
              pslow=50,
          )
          def __init__(self):
              # Keep a reference to the "close" line in the data[0] dataseries
              self.dataclose = self.datas[0].close
              #DC
              self.dc = DonchianChannels()
              # To keep track of pending orders and buy price/commission
              self.order = None
              self.buyprice = None
              self.buycomm = None
              # Simple Moving Average
              sma1 = bt.ind.SMA(period=self.p.pfast)  # fast moving average
              sma2 = bt.ind.SMA(period=self.p.pslow)  # slow moving average
              self.crossover = bt.ind.CrossOver(sma1, sma2)  # crossover signal
              #ATR
              pureatr = bt.ind.ATR(period = 14)
              self.my_atr = pureatr
      
          # LOG
          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))
      
          # EXECUTED ORDER NOTIFICATIONS
          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)
                  self.log("Balance :%.2f" % (cerebro.broker.getvalue()))
      
              elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                  self.log("Order Cancled/Margin/Rejected")
      
              self.order = None
      
          #Exit Operation Logs
          def notify_trade(self, trade):
              if not trade.isclosed:
                  return
      
              self.log("[OPERATION PROFIT] GROSS: %.2f NET: %.2f, BALANCE: %.2f" %
                       (trade.pnl, trade.pnlcomm,cerebro.broker.getvalue()))
              print()
      
          def next(self):
              # Simply log the closing price of the series from the reference
              self.log('Close, %.2f' % self.dataclose[0])
      
              #Check if an order is pending.. if yes, cant send a 2nd order.
              if self.order:
                  return
      
              #LONG CONDITION
              if not self.position:
                  if self.data[0] > self.dc.dch[0]:
                      self.log('BUY CREATE, %.2f' % self.dataclose[0])
                      self.order = self.buy()
              elif (self.dataclose[1]) > self.dataclose[0]:  # in the market & cross to the downside
                  self.log("LONG CLOSED {}".format(self.dataclose[0]))
                  self.close()  # close long position
      
      
      #CEREBRO
      cerebro = bt.Cerebro()
      data = bt.feeds.YahooFinanceCSVData(
          dataname="oracle.csv",
          fromdate=datetime.datetime(2000,1,1),
          todate=datetime.datetime(2000,12,29),
          reverse=False)
      cerebro.adddata(data)
      cerebro.broker.set_cash(100000)
      cerebro.broker.setcommission(0.01)
      cerebro.addstrategy(TestStrategy)
      cerebro.addsizer(MaxRiskSizer, risk=0.5)
      
      print("Starting Portfolio :%.2f" % cerebro.broker.getvalue())
      print()
      cerebro.run()
      print()
      print("Final Portfolio Value:%.2f" % cerebro.broker.getvalue())
      cerebro.plot(style="candlestick",barup='green', bardown='red')
      

      1. I am trying to make the system print out its 'Balance/Cash' after
      "2000-03-24, BUY EXECUTED,Price: 38.61, Cost: 49922.73, Comm 499.23"

      so i put "self.log("Balance :%.2f" % (cerebro.broker.getvalue()))" after the buy/sell executed code, but the it printed out :

      Starting Portfolio :100000.00
      2000-03-23, BUY CREATE, 38.64
      2000-03-24, BUY EXECUTED,Price: 38.61, Cost: 49922.73, Comm 499.23
      2000-03-24, Balance :99604.21

      The starting portfolio is 100,000. Why is the balance after buy executed 99604?
      100,000 - 99604.21 = 395.79. Where did 395.79 come from? the Commission issued is 499.23.

      2. I am trying to use ATR as my stoploss / exit long position. Can anyone make ATR into trailing stoploss. and I tried using multipler in the ATR, but it doesn't work

      #ATR
              pureatr = bt.ind.ATR(period = 14)
              self.my_atr = pureatr
      

      then
      into
      CLOSE LONG POSITION when current close crosses/touches previous day's close - 4*ATR
      I modified the elif..... from
      elif (self.dataclose[1]) > self.dataclose[0]:
      to
      elif (self.dataclose[0]) > self.dataclose[1]-(pureatr*4)):
      (but it doesnt work)

      #LONG CONDITION
                       if not self.position:
                           if self.data[0] > self.dc.dch[0]:
                               self.log('BUY CREATE, %.2f' % self.dataclose[0])
                               self.order = self.buy()
                       elif (self.dataclose[0]) > self.dataclose[1]-(pureatr*4)):  
                           self.log("LONG CLOSED {}".format(self.dataclose[0]))
                           self.close()  # close long position
      
      "C:\Users\2200214\PycharmProjects\Trade\venv\Scripts\python.exe C:/Users/2200214/PycharmProjects/Trade/Trader.py
        File "C:/Users/2200214/PycharmProjects/Trade/Trader.py", line 123
          elif (self.dataclose[0]) > self.dataclose[1] - (pureatr * 4)):  # in the market & cross to the downside
          ^
      SyntaxError: invalid syntax
      
      Process finished with exit code 1"
      

      3. Is there anything wrong with my code? if theres anything you can think of improving it please help me

      A 1 Reply Last reply Reply Quote 0
      • A
        ab_trader @Gleetche last edited by

        @Gleetche said in Problem with using ATR multiplier as stoploss and printing CASH.:

        Where did 395.79 come from?

        Evidently, it comes as an output from the code you written. If you expected something else, than please elaborate what did you expect.

        @Gleetche said in Problem with using ATR multiplier as stoploss and printing CASH.:

        Is there anything wrong with my code?

        Since you are asking, than probably yes. Usually if everything goes well, questions are not raised on this forum. But it is quite hard to understand what is the code which potentially has an error, you may want to repost and make it more clear for other members.

        • If my answer helped, hit reputation up arrow at lower right corner of the post.
        • Python Debugging With Pdb
        • New to python and bt - check this out
        G 1 Reply Last reply Reply Quote 2
        • G
          Gleetche @ab_trader last edited by

          @ab_trader

          1 Balance Printing
          Starting Portfolio :100000.00
          2000-03-23, BUY CREATE, 38.64
          2000-03-24, BUY EXECUTED,Price: 38.61, Cost: 49922.73, Comm 499.23
          2000-03-24, Balance :99604.21

          The starting portfolio is 100,000.
          Then I made it print the balance after the "BUY EXECUTED,Price: 38.61, Cost: 49922.73, Comm 499.23"
          The balance prints 99604.21

          Like I said, I am quite new and im trying to experiment with the tutorial. I am expecting either of these to be printed

          1. Portfolio - (Cost + Comm), which is 100,000- (49922.73 +499.23) = 49578.04
          2. Portfolio - Cost, which is 100,000 - 49922.73 = 50077.27
          3. Portfolio - Cost which is 99500.77
            ( I don't really expect number 3. to be printed but its the closest with the number printed)

          But the balance prints 99604.21 , why?

          1 Reply Last reply Reply Quote 0
          • A
            ab_trader last edited by

            Documentation says the following:

            get_value(datas=None, mkt=False, lever=False)

            Returns the portfolio value of the given datas (if datas is None, then the total portfolio value will be returned (alias: getvalue)

            Evidently, that item 1 and item 2 shows the cash and cash considering no commission. Really not sure why do you expect cash to be printed with the call of cerebro.broker.getvalue(). Seems it is wrong.

            Item 3 seems equal item 2 by formula, why do you have different number?

            The number99604.21 from the original post is the value of the broker account, which includes cash and position value.

            • If my answer helped, hit reputation up arrow at lower right corner of the post.
            • Python Debugging With Pdb
            • New to python and bt - check this out
            1 Reply Last reply Reply Quote 1
            • G
              Gleetche last edited by

              @ab_trader

              Sorry it was typo.

              It should be

              1. Portfolio - (Cost + Comm), which is 100,000- (49922.73 +499.23) = 49578.04
              2. Portfolio - Cost, which is 100,000 - 49922.73 = 50077.27
              3. Portfolio - Commission 100,000 - 499.23 which is 99500.77

              "The number 99604.21 from the original post is the value of the broker account, which includes cash and position value."

              I apologize, but I still do not get it. Then can you show me the calculation on how do you get 99604.21 .

              and so,

              How do I get the number "49578.04" (CASH - (Cost + Comm)) printed out?
              The process goes like this right:

              1. Long Signal
              2. "BUY CREATE"
              3. "BUY EXECUTED"
                -->>How do I Print Cash Here (Portfolio - (Cost + Comm))<<--
              4. Long Exit Signal
              5. "LONG EXIT CREATE" (it's "Long Closed" on the original post)
              6. "SELL EXECUTED"
              1 Reply Last reply Reply Quote 0
              • A
                ab_trader last edited by

                @Gleetche said in Problem with using ATR multiplier as stoploss and printing CASH.:

                Then can you show me the calculation on how do you get 99604.21

                Should be CASH LEFT + CLOSE x NUMBER OF SHARES = 99604.21

                @Gleetche said in Problem with using ATR multiplier as stoploss and printing CASH.:

                How do I get the number "49578.04" (CASH - (Cost + Comm)) printed out?

                Docs - Broker - get_cash()

                • If my answer helped, hit reputation up arrow at lower right corner of the post.
                • Python Debugging With Pdb
                • New to python and bt - check this out
                G 1 Reply Last reply Reply Quote 1
                • G
                  Gleetche @ab_trader last edited by

                  @ab_trader

                  ohhhh, I got it now, getcash() is the thing i was looking for!
                  thanksss!

                  1 Reply Last reply Reply Quote 0
                  • 1 / 1
                  • First post
                    Last post
                  Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors