Backtrader Community

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    1. Home
    2. Julianus
    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 4
    • Posts 10
    • Best 0
    • Controversial 0
    • Groups 0

    Julianus

    @Julianus

    0
    Reputation
    330
    Profile views
    10
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    Julianus Unfollow Follow

    Latest posts made by Julianus

    • Sizer for partial units, crypto

      Hello @backtrader,

      I'm struggling with sizer settings. Based on the documentation, in my understanding, sizers in bt are set to buy whole units. I've been trying to tweak it to float units, however without success. Also searched the topics, but haven't found this.

      Could you help me how/which classes/parameters shall I modify to let my strat buy partial units?

      Many thanks for your help.

      posted in Indicators/Strategies/Analyzers
      J
      Julianus
    • RE: Notify_trade: trade.size is zero at trade closed

      @backtrader, ok.

      I'm going to deep-dive in the platform once again from the beginning, so then hopefully those questions/topics will be clearer.

      Don't you consider having a discord channel for very interactive chats?

      Thanks anyway.

      posted in Indicators/Strategies/Analyzers
      J
      Julianus
    • RE: Notify_trade: trade.size is zero at trade closed

      @backtrader, ok thanks understood.
      I asked this one as the second question in my initial post:
      "How could I easily get the given trade's quantity, price data?"

      posted in Indicators/Strategies/Analyzers
      J
      Julianus
    • RE: Notify_trade: trade.size is zero at trade closed

      @backtrader, @ab_trader, thanks for the prompt answer.
      I've cleaned the code a little, unfortunately zero still appears ('Profit' stuck there incorrectly during my tries, should've been switched like below).

      Full code:

      from collections import OrderedDict
      
      class maxRiskSizer(bt.Sizer):
          params = (('risk', 1),)
       
          def __init__(self):
              if self.p.risk > 1 or self.p.risk < 0:
                  raise ValueError('Risk parameter is not ok!')
       
          def _getsizing(self, comminfo, cash, data, isbuy):
              if isbuy == True:
                  size = (cash * self.p.risk) / data[0]
              else:
                  size = ((cash * self.p.risk) / data[0]) * -1
              return size
      
      class SmaCross(bt.Strategy):
              params = (
                  ('pfast', 15),
                  ('pslow', 100),
                  ('printlog', False),
              )
          
              def log(self, txt, dt=None):
                  ''' Logging function fot this strategy'''
                  dt = dt or self.datas[0].datetime.datetime(0)
                  print('%s, %s' % (dt.isoformat(), txt))
      
              def __init__(self):
                  self.dataclose = self.datas[0].close
                  
                  self.order = None
                  self.buyprice = None
                  self.buycomm = None
                  
                  self.sma1 = bt.ind.SimpleMovingAverage(self.data.close, period=self.params.pfast)
                  self.sma2 = bt.ind.SimpleMovingAverage(self.data.close, period=self.params.pslow)
                  self.Cross = bt.ind.CrossOver(self.sma1, self.sma2)
              
              def next(self):
                  if self.order:
                      return
                  
                  if not self.position:
                      if self.Cross and pd.notna(self.sma1[0] and self.sma2[0]):
                          self.buy()
                          
                  else:
                      if self.Cross == -1:
                          self.close()
                          
              def notify_trade(self, trade):
                  if trade.justopened:
                      print('----TRADE OPENED----')
                      print('Size: {:.3f}, value: {:.3f}'.format(trade.size, trade.value))
                  elif trade.isclosed:
                      print('----TRADE CLOSED----')
                      print('Size: {:.3f} Profit: Gross {:.3f}, Net {:.3f}'.format(trade.size, trade.pnl, trade.pnlcomm))
                  else:
                      return
                  
      
      if __name__ == '__main__':
          
          startcash = 10000
          
          cerebro = bt.Cerebro()
          
          cerebro.addstrategy(SmaCross)
      
          modpath = os.path.dirname('D:\\_projectPy\\')
          datapath = os.path.join(modpath, 'test4.csv')
      
          data = bt.feeds.GenericCSVData(
              dataname=datapath,
              timeframe=bt.TimeFrame.Minutes, compression=60,
              datetime=0,
              open = 1,
              high = 3,
              low = 4,
              close = 2,
              volume = 5,
              openinterest = -1,
              fromdate = datetime(2018, 1, 1, 1, 0, 1),
              todate = datetime(2018, 1, 20, 0, 0, 1),
              separator=',',
              dtformat=('%Y-%m-%d %H:%M:%S')
              )
      
          cerebro.adddata(data)
          
          cerebro.broker.setcash(startcash)
          
          cerebro.addsizer(maxRiskSizer, risk=1)
          
          strategies = cerebro.run(maxcpus=1)
      

      Output:

      ----TRADE OPENED----
      Size: 0.670, value: 9997.320
      ----TRADE CLOSED----
      Size: 0.000 Profit: Gross 361.163, Net 361.163
      ----TRADE OPENED----
      Size: 0.728, value: 10361.163
      ----TRADE CLOSED----
      Size: 0.000 Profit: Gross -801.999, Net -801.999
      ----TRADE OPENED----
      Size: 0.688, value: 9557.100
      ----TRADE CLOSED----
      Size: 0.000 Profit: Gross -496.562, Net -496.562
      
      posted in Indicators/Strategies/Analyzers
      J
      Julianus
    • RE: Notify_trade: trade.size is zero at trade closed

      @ab_trader, @backtrader thanks.
      What's strange is that other trade subclasses (trade.pnl, trade.pnlcomm) give the correct figure, while trade.value did not at the same call. Or these are handled differently by bt?

      posted in Indicators/Strategies/Analyzers
      J
      Julianus
    • Notify_trade: trade.size is zero at trade closed

      Hey All,

      I've added a new sizer to enable partial contracts to buy based on cash available (crypto space). Algo seems to work fine except that at closed trades the trade.size is printed as zero.
      Any thoughts on the reason of this behaviour?
      How could I easily get the given trade's quantity, price data?

      Thanks a lot

      here're the main elements:

      class maxRiskSizer(bt.Sizer):
          params = (('risk', 1),)
       
          def __init__(self):
              if self.p.risk > 1 or self.p.risk < 0:
                  raise ValueError('Risk parameter is not ok!')
       
          def _getsizing(self, comminfo, cash, data, isbuy):
              if isbuy == True:
                  size = (cash * self.p.risk) / data[0]
              else:
                  size = ((cash * self.p.risk) / data[0]) * -1
              return size
      
      class SmaCross(bt.Strategy):
      ...
              def notify_trade(self, trade):
                  if trade.justopened:
                      print('----TRADE OPENED----')
                      print('Size: {:.3f}, value: {:.3f}'.format(trade.size, trade.value))
                  elif trade.isclosed:
                      print('----TRADE CLOSED----')
                      print('Profit: {} Gross {}, Net {}'.format(trade.size, round(trade.pnl,2), round(trade.pnlcomm,2)))
                  else:
                      return
      

      This gives the following output:

      ----TRADE OPENED----
      Size: 0.670, value: 9997.320
      ----TRADE CLOSED----
      Profit: 0.0 Gross 361.16, Net 361.16
      ----TRADE OPENED----
      Size: 0.728, value: 10361.163
      ----TRADE CLOSED----
      Profit: 0.0 Gross -802.0, Net -802.0
      ----TRADE OPENED----
      Size: 0.688, value: 9557.100
      ...
      
      posted in Indicators/Strategies/Analyzers
      J
      Julianus
    • RE: SMA doesn't show correct values (vs Tradingview, manual python calculations)

      @backtrader, thanks a lot for your reply.
      After due testing, I've realized that the reason it showed different values was that the SMA calculation start date was different, so then the values.

      Apologies if something slipped through, it was very far from my intention to blame anyone, on the contrary, I'm amazed by the flexibility of the platform and the wide range of strategies I can try out.
      I'm a new one in python and backtrader and sometime a newbie question comes. Good luck with the development!

      posted in General Code/Help
      J
      Julianus
    • SMA doesn't show correct values (vs Tradingview, manual python calculations)

      Hi All,

      I'm trying to implement a simple SMA double cross strategy, but it seems that values don't match with my references (Tradingview and manual python calculations; these two matching exactly).

      my py method:

      def SMA(values, window):
          return values.rolling(window).mean()
      

      Can you advise?

      Thanks a lot in advance

      from collections import OrderedDict
      
      class SmaCross(bt.SignalStrategy):
              params = (
                  ('pfast', 15),
                  ('pslow', 100),
                  ('printlog', False),
              )
          
              def log(self, txt, dt=None):
                  ''' Logging function fot this strategy'''
                  dt = dt or self.datas[0].datetime.datetime(0)
                  print('%s, %s' % (dt.isoformat(), txt))
      
              def __init__(self):
                  self.dataclose = self.datas[0].close
                  
                  self.order = None
                  self.buyprice = None
                  self.buycomm = None
                  
                  sma1 = bt.ind.SimpleMovingAverage(self.data.close, period=self.params.pfast)
                  sma2 = bt.ind.SimpleMovingAverage(self.data.close, period=self.params.pslow)
                  self.Cross = bt.ind.CrossOver(sma1, sma2)
              
              def next(self):
                  if self.order:
                      return
                  
                  if not self.position:
                      if self.Cross:
                          self.log('BUY CREATE, %.2f' % self.dataclose[0])
                          self.buy(size = 1)
                          
                  else:
                      if self.Cross == -1:
                          self.log('SELL CREATE, %.2f' % self.dataclose[0])
                          self.sell(size = 1)
      
      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 Results:")
          for row in print_list:
              print(row_format.format('',*row))
      
      def printSQN(analyzer):
          sqn = round(analyzer.sqn,2)
          print('SQN: {}'.format(sqn))
      
      
      if __name__ == '__main__':
          
          startcash = 10000
          
          cerebro = bt.Cerebro()
          
          cerebro.addstrategy(SmaCross)
      
          # Datas are in a subfolder of the samples. Need to find where the script is
          # because it could have been called from anywhere
          modpath = os.path.dirname('D:\\Dropbox\\projectPy\\')
          datapath = os.path.join(modpath, 'test4.csv')
      
          # Create a Data Feed
          data = bt.feeds.GenericCSVData(
              dataname=datapath,
              timeframe=bt.TimeFrame.Minutes, compression=60,
              datetime=0,
              open = 1,
              high = 3,
              low = 4,
              close = 2,
              volume = 5,
              openinterest = -1,
              fromdate = datetime(2018,7,2,11,0,1),
              todate = datetime(2018,7,25,11,0,1),
              separator=',',
              dtformat=('%Y-%m-%d %H:%M:%S')
              )
      
          cerebro.adddata(data)
          
          cerebro.broker.setcash(startcash)
          
          # Add the analyzers we are interested in
          cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name="ta")
          cerebro.addanalyzer(bt.analyzers.SQN, _name="sqn")
       
          # Run over everything
          strategies = cerebro.run(maxcpus=1)
          SmaCrossStrat = strategies[0]
          
          portvalue = cerebro.broker.getvalue()
       
          #Print out the final result
          print('Final Portfolio Value: ${}\nStarting Cash: ${}'.format(portvalue, startcash))
          
          printSQN(SmaCrossStrat.analyzers.sqn.get_analysis())
          
          # print the analyzers
          printTradeAnalysis(SmaCrossStrat.analyzers.ta.get_analysis())
          #for x in SmaCrossStrat.analyzers:
          #    x.print()
          
          #Finally plot the end results
          cerebro.plot(style='candlestick',barup='green',bardown='red', iplot = False)  
      

      Output:

      2018-07-02T12:00:00, BUY CREATE, 6331.03
      2018-07-07T22:00:00, SELL CREATE, 6530.70
      2018-07-08T01:00:00, BUY CREATE, 6761.80
      2018-07-10T11:00:00, SELL CREATE, 6443.80
      2018-07-15T09:00:00, BUY CREATE, 6278.90
      2018-07-21T11:00:00, SELL CREATE, 7326.00
      2018-07-22T03:00:00, BUY CREATE, 7478.20
      Final Portfolio Value: $11198.3
      Starting Cash: $10000
      SQN: 0.95
      Trade Results:
                     Total Open     Total Closed   Total Won      Total Lost     
                     1              3              2              2              
                     Strike Rate    Win Streak     Losing Streak  PnL Net        
                     66.67          1              1              928.6          
      

      My reference data (both fine with Tradingview and python manual check):
      Close SMA15 SMA100
      Date
      2018-07-02 10:00:00 6341.700000 6334.681390 6196.541828
      2018-07-02 11:00:00 6324.900000 6335.248056 6198.605828
      2018-07-02 12:00:00 6331.026474 6335.763155 6200.873093
      2018-07-02 13:00:00 6341.200000 6335.035098 6203.105093
      2018-07-02 14:00:00 6342.969553 6333.233069 6205.342788
      2018-07-07 20:00:00 6554.000000 6573.993333 6569.899519
      2018-07-07 21:00:00 6541.900000 6570.040000 6569.482519
      2018-07-07 22:00:00 6530.700000 6565.680000 6568.942519
      2018-07-07 23:00:00 6531.700000 6562.273333 6568.460519
      2018-07-08 00:00:00 6579.300000 6561.266667 6568.515519
      2018-07-08 02:00:00 6748.046810 6584.629787 6571.408987
      2018-07-08 03:00:00 6743.100000 6594.629787 6572.729987
      2018-07-08 04:00:00 6747.100000 6605.536454 6575.331987
      2018-07-10 09:00:00 6602.600000 6664.180000 6646.618688
      2018-07-10 10:00:00 6590.900000 6657.053333 6647.275688
      2018-07-10 11:00:00 6443.800000 6639.906667 6646.673688
      2018-07-10 12:00:00 6470.100000 6623.660000 6646.710688
      2018-07-10 13:00:00 6359.200000 6601.000000 6645.463688

      posted in General Code/Help sma incorrect double cross
      J
      Julianus
    • RE: optstrategy same results in Jupyter

      @backtrader thanks a lot, working as needed now.

      posted in General Code/Help
      J
      Julianus
    • optstrategy same results in Jupyter

      Hey all,

      First of all congrats for backtrader for the platform, it seems awesome. Although I'm just starting to use it, ended up in a problem during strategy optimization. With stop(self) works fine, but when I want to get the results based on the objects list, it circulates with the same figures.
      Here's the code:

      import backtrader as bt
      from datetime import datetime
      
      class firstStrategy(bt.Strategy):
          params = (
              ('period',21),
              )
       
          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 < 30:
                      self.buy(size=1)
              else:
                  if self.rsi > 65:
                      self.sell(size=1)
       
          def stop(self):
              pnl = round(self.broker.getvalue() - self.startcash,2)
              print('RSI Period: {} Final PnL: {}'.format(
                  self.params.period, pnl))        
                 
      if __name__ == '__main__':
          startcash = 10000
          cerebro = bt.Cerebro(optreturn=False)
      
          cerebro.optstrategy(firstStrategy, period=range(20,25))
      
          modpath = os.path.dirname('D:\\Dropbox\\hye\\')
          datapath = os.path.join(modpath, 'test4.csv')
          
          data = bt.feeds.GenericCSVData(
              dataname=datapath,
              timeframe=bt.TimeFrame.Minutes, compression=60,
              datetime=0,
              open = 1,
              high = 3,
              low = 4,
              close = 2,
              volume = 5,
              openinterest = -1,
              fromdate = datetime(2018,5,2,11,0,1),
              todate = datetime(2018,5,20,11,0,1),
              separator=',',
              dtformat=('%Y-%m-%d %H:%M:%S')
              )
          
          cerebro.adddata(data)
          cerebro.broker.setcash(startcash)
      
          opt_runs = cerebro.run(maxcpus=1)   
             
          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
                  final_results_list.append([period,PnL])
                  
          by_period = sorted(final_results_list, key=lambda x: x[0])
          by_PnL = sorted(final_results_list, key=lambda x: x[1], reverse=True)
       
          print('\nResults: Ordered by period:')
          for result in by_period:
              print('Period: {}, PnL: {}'.format(result[0], result[1]))
          print('Results: Ordered by Profit:')
          for result in by_PnL:
              print('Period: {}, PnL: {}'.format(result[0], result[1]))
      

      This gives out:

      RSI Period: 20 Final PnL: -628.52
      RSI Period: 21 Final PnL: -658.0
      RSI Period: 22 Final PnL: -718.4
      RSI Period: 23 Final PnL: -601.3
      RSI Period: 24 Final PnL: -502.5
      
      Results: Ordered by period:
      Period: 20, PnL: -502.5
      Period: 21, PnL: -502.5
      Period: 22, PnL: -502.5
      Period: 23, PnL: -502.5
      Period: 24, PnL: -502.5
      Results: Ordered by Profit:
      Period: 20, PnL: -502.5
      Period: 21, PnL: -502.5
      Period: 22, PnL: -502.5
      Period: 23, PnL: -502.5
      Period: 24, PnL: -502.5
      

      Thanks a lot for your help.

      posted in General Code/Help opstrategy jupyter same results
      J
      Julianus