Backtrader Community

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

    Jonny8

    @Jonny8

    8
    Reputation
    35
    Profile views
    45
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    Jonny8 Unfollow Follow

    Best posts made by Jonny8

    • RE: How do I install this?

      @Gleetche
      Hi Gleetche,

      I think this is a rather general question but I try to help you out here.
      I myself also had no clue how to do that, but
      the description to install it seems to be for linux. So if you have linux then follow the install notes.
      I strongly assume you use windows, hence I googled "make install on windows" and got this:
      https://stackoverflow.com/questions/32127524/how-to-install-and-use-make-in-windows

      Before that you have to clone the github files to you pc.

      Best
      John

      posted in General Code/Help
      J
      Jonny8
    • RE: Genetic Algorithm using multiple cpu threads

      @Wayne-Filkins-0

      Hi,

      as far as I know backtrader uses automatically all CPUs.
      https://www.backtrader.com/blog/posts/2015-07-23-multicore-optimization/multicore-optimization/

      If you are using Jupyter, then this limits the CPU usage.
      Otherwise the package you are using might be limiting its multicore capabilities (i.e. optunity is as far as I know doing that)

      posted in General Discussion
      J
      Jonny8
    • RE: How do I print (ATR)

      Hi Gleetche,

      I guess your code would help to answer your question.

      Best

      posted in General Code/Help
      J
      Jonny8
    • RE: How do I print (ATR)

      @Gleetche said in How do I print (ATR):

      def next(self):
          # Simply log the closing price of the series from the reference
          self.log('Close: %.2f , ATR: $.2f' % (self.dataclose[0],self.my_atr))
      

      I think replacing the $ after "ATR:" with a % should do the trick.

      Best

      posted in General Code/Help
      J
      Jonny8
    • RE: Why doesn't my 'buy' trigger?

      is there enough cash?

      def log(self, arg):
              print('{} {}'.format(self.datetime.date(), arg))
              
          # This section is for logging of orders in greater detail to figure out whether the strategy is actually having no problem with orders
          def notify_order(self, order):
              if order.status in [order.Accepted]:
                  # Buy/Sell order submitted/accepted to/by broker - Nothing to do
                  return
              if order.status in [order.Submitted]:
                  if order.isbuy():
                  
                      dt, dn = self.datetime.date(), order.data._name
                      print('Buy {} {} {} Price {:.2f} Value {:.2f} Size {} Cash {:.2f}'.format(
                              order.getstatusname(), dt, dn, order.created.price, order.created.size * order.created.price , order.created.size, self.broker.getcash()))
                  if order.issell():
                      dt, dn = self.datetime.date(), order.data._name
                      print('Sell {} {} {} Price {:.2f} Value {:.2f} Size {}'.format(
                              order.getstatusname(), dt, dn, order.created.price, order.created.size * order.created.price, order.created.size))
      
                  # Buy/Sell order submitted/accepted to/by broker - Nothing to do
                  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():
                      dt, dn = self.datetime.date(), order.data._name
                      print('Buy {} {} Price {:.2f} Value {:.2f} Size {}'.format(
                          dt, dn, order.executed.price, order.executed.value, order.executed.size))
      
                  if order.issell():# Sell
                      dt, dn = self.datetime.date(), order.data._name
                      print('Sell {} {} Price {:.2f} Value {:.2f} Size {}'.format(
                          dt, dn, order.executed.price, order.executed.value, order.executed.size))
      
      
              elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                  self.log('Order Canceled/Margin/Rejected')
      

      Code to have a closer look at the orders.

      posted in General Code/Help
      J
      Jonny8
    • RE: Trouble interpreting TradeAnalyzer results.

      @earlcharles1
      Might this help?
      https://community.backtrader.com/topic/670/it-s-here-a-beta-you-can-use-right-now-essential-trade-statistics-all-in-one-place

      posted in General Code/Help
      J
      Jonny8
    • RE: Used Timer only works (partially) with _getminperstatus() ?

      Still stuck...
      I gave up the avenue I tried witht he HoldAllStrategy of the previous post.

      instead I tried to understand when and therefore where I have to filter out the stocks going to next().

      Strategy

      class Sur(bt.Strategy):
          params = dict(
                  selcperc=0.10,  # percentage of stocks to select from the universe
                  rperiod=1,  # period for the returns calculation, default 1 period
                  vperiod=55,  # lookback period for volatility - default 36 periods
                  mperiod=195,  # lookback period for momentum - default 90 periods
                  momentum=Momentum, # parametrize the momentum and its period
                  reserve=globalparams["reserve"],  # 5% reserve capital
                  monthdays=[1],
                  monthcarry=True,
                  when=bt.timer.SESSION_START,
                  benchmarkstop=False, # If true, no stocks will be bought and no rebalancing will be done if benchmark is below SMAperiod
                  SMAperiod=200,
                  benchmark_bond=True, # Sell all Stocks and buy Bonds
                  jump_momentum=True, # If true, after a time of jump_one (30 days x jump_one) in every month, all the money will be directed to the best performing stock. Rule for that:
                                      # In Excel, this is a 0.6 x month return of fund with best past 3 month return plus 0.4 x return of fund with best return, month to date.
                  jump_one=0.6,
                  printlog=True,
              )
      
          def __init__(self):
              self.bench = self.data0
              self.bond = self.data1
              self.stocks = self.datas[2:]
              # calculate 1st the amount of stocks that will be selected
              self.selnum = int(len(self.stocks) * self.p.selcperc)
      
              # allocation perc per stock
              # reserve kept to make sure orders are not rejected due to
              # margin. Prices are calculated when known (close), but orders can only
              # be executed next day (opening price). Price can gap upwards
              self.perctarget = (1.0 - self.p.reserve) / self.selnum
              
              # This is the set up of the timer that makes the strategy being executed at the given time
              self.add_timer(
                  when=self.p.when,
                  monthdays=self.p.monthdays,
                  monthcarry=self.p.monthcarry
              )
              
              self.stocks_len = []
              
              jump = True
      
              # returns, volatilities and momentums
              rs = [bt.ind.PctChange(d, period=self.p.rperiod) for d in self.stocks]
              vs = [bt.ind.StdDev(ret, period=self.p.vperiod) for ret in rs]
              #ms = [bt.ind.ROC(d, period=self.p.mperiod) for d in self.datas]
              ms = [self.p.momentum(d, period=self.p.mperiod) for d in self.stocks]
              
              self.bench_sma = bt.ind.SMA(self.data0, period=self.p.SMAperiod)
              
              # simple rank formula: (momentum * net payout) / volatility
              # the highest ranked: low vol, large momentum, large payout
              self.ranks = {d: m / v for d, v, m in zip(self.stocks, vs, ms)}
              #TODO: does it perform better without the volatility?
      
              self.bench_filter = self.bench < self.bench_sma
      
      
          def log(self, arg):
              if self.p.printlog:
                  print('{} {}'.format(self.datetime.date(), arg))
              
      
          # This is the function using the timer to execute the rebalance 
          def notify_timer(self, timer, when, *args, **kwargs):
              print('strategy notify_timer with tid {}, when {} _getminperstatus {}'.
                    format(timer.p.tid, when, int(self._getminperstatus())))
              print("timer")
              if self._getminperstatus() < 0:
                  self.rebalance()
          
          def nextstart(self):
              self.ranks_filter = self.ranks
              print("nextstart")
              self.next()
              
          def prenext(self):
              self.stocks_len = [d for d in self.stocks if len(d)]
              self.ranks_filter = dict(zip(self.stocks_len, [self.ranks[k] for k in self.stocks_len]))        
              self.next()
              
          def next(self):
              print("next")
              pass # must be filled with a pass
      
          
          # Actual order giving by a ranking takes place here
          def rebalance(self):
              print("rebalance")
              #if jump == True:
              # Enter Jump Code here    
              
              # sort data and current rank
              ranks = sorted(
                  self.ranks_filter.items(),  # get the (d, rank), pair
                  key=lambda x: x[1][0],  # use rank (elem 1) and current time "0"
                  reverse=True,  # highest ranked 1st ... please
              )
              
              # put top ranked in dict with data as key to test for presence
              rtop = dict(ranks[:self.selnum])
      
              # For logging purposes of stocks leaving the portfolio
              rbot = dict(ranks[self.selnum:])
      
              # prepare quick lookup list of stocks currently holding a position
              posdata = [d for d, pos in self.getpositions().items() if pos]
              
      
              if self.p.benchmarkstop:
                  for d in (d for d in posdata):
                      if "Bond" == d._name and self.bench_filter:
                          return
                      else:
                          if "Bond" == d._name and not self.bench_filter:
                              self.order_target_percent("Bond", target=0.0)
                              self.log('Leave {} due to end of down period'.format(d._name))
                              return
              
              # Triple Momentum: If Benchmark index is below SMA, nothing will be bought or rebalanced
              if self.p.benchmarkstop:
                  if self.bench_filter:
                      #print('SMA {} - Bench {}'.format(self.bench_sma[0], self.bench[0]))
                      if self.p.benchmark_bond:
                          for d in posdata:
                              self.log('Leave {} due to switch to Bonds'.format(d._name))
                              self.order_target_percent(d, target=0.0)
                          self.order_target_percent("Bond", target=0.95)
                          self.log('Buy Bond')
                          bond_flag = True
                          return #Code stops here and skips rebalancing und buying
      
              # remove those no longer top ranked
              # do this first to issue sell orders and free cash
              for d in (d for d in posdata if d not in rtop):
                  self.log('Leave {} - Rank {:.2f}'.format(d._name, rbot[d][0]))
                  self.order_target_percent(d, target=0.0)
              
              # rebalance those already top ranked and still there
              for d in (d for d in posdata if d in rtop):
                  self.log('Rebal {} - Rank {:.2f}'.format(d._name, rtop[d][0]))
                  self.order_target_percent(d, target=self.perctarget)
                  del rtop[d]  # remove it, to simplify next iteration
      
              # issue a target order for the newly top ranked stocks
              # do this last, as this will generate buy orders consuming cash
              for d in rtop:
                  self.log('Enter {} - Rank {:.2f}'.format(d._name, rtop[d][0]))
                  self.order_target_percent(d, target=self.perctarget)
                  
          def stop(self):
              pnl = round(self.broker.getvalue() - globalparams["cash"],2)
              print('Final PnL: {}'.format(
                  pnl))
      

      Error Message

      strategy notify_timer with tid 0, when 2014-11-03 00:00:00 _getminperstatus 199
      timer
      next
      
      ---------------------------------------------------------------------------
      IndexError                                Traceback (most recent call last)
      <ipython-input-7-8fb965d11696> in <module>
          312 # <<<Execute starting section>>>
          313 if __name__ == '__main__':
      --> 314     run()
      
      <ipython-input-7-8fb965d11696> in run(args)
          284                         timeframe=bt.TimeFrame.NoTimeFrame)
          285 
      --> 286     results = cerebro.run(maxcpus=1)#maxcpu=1 otherwise pickling multiprocessing errors
          287 
          288 # <<<Performance analysing section section>>>
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\cerebro.py in run(self, **kwargs)
         1125             # let's skip process "spawning"
         1126             for iterstrat in iterstrats:
      -> 1127                 runstrat = self.runstrategies(iterstrat)
         1128                 self.runstrats.append(runstrat)
         1129                 if self._dooptimize:
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\cerebro.py in runstrategies(self, iterstrat, predata)
         1296                     self._runnext_old(runstrats)
         1297                 else:
      -> 1298                     self._runnext(runstrats)
         1299 
         1300             for strat in runstrats:
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\cerebro.py in _runnext(self, runstrats)
         1628                 self._check_timers(runstrats, dt0, cheat=False)
         1629                 for strat in runstrats:
      -> 1630                     strat._next()
         1631                     if self._event_stop:  # stop if requested
         1632                         return
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\strategy.py in _next(self)
          348 
          349         minperstatus = self._getminperstatus()
      --> 350         self._next_analyzers(minperstatus)
          351         self._next_observers(minperstatus)
          352 
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\strategy.py in _next_analyzers(self, minperstatus, once)
          386                 analyzer._nextstart()  # only called for the 1st value
          387             else:
      --> 388                 analyzer._prenext()
          389 
          390     def _settz(self, tz):
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\analyzer.py in _prenext(self)
          148     def _prenext(self):
          149         for child in self._children:
      --> 150             child._prenext()
          151 
          152         self.prenext()
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\analyzer.py in _prenext(self)
          150             child._prenext()
          151 
      --> 152         self.prenext()
          153 
          154     def _notify_cashvalue(self, cash, value):
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\analyzer.py in prenext(self)
          227         The default behavior for an analyzer is to invoke ``next``
          228         '''
      --> 229         self.next()
          230 
          231     def nextstart(self):
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\analyzers\positions.py in next(self)
           76 
           77     def next(self):
      ---> 78         pvals = [self.strategy.broker.get_value([d]) for d in self.datas]
           79         if self.p.cash:
           80             pvals.append(self.strategy.broker.get_cash())
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\analyzers\positions.py in <listcomp>(.0)
           76 
           77     def next(self):
      ---> 78         pvals = [self.strategy.broker.get_value([d]) for d in self.datas]
           79         if self.p.cash:
           80             pvals.append(self.strategy.broker.get_cash())
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\brokers\bbroker.py in get_value(self, datas, mkt, lever)
          413             return self._value if not lever else self._valuelever
          414 
      --> 415         return self._get_value(datas=datas, lever=lever)
          416 
          417     getvalue = get_value
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\brokers\bbroker.py in _get_value(self, datas, lever)
          437                 dvalue = comminfo.getvalue(position, data.close[0])
          438             else:
      --> 439                 dvalue = comminfo.getvaluesize(position.size, data.close[0])
          440 
          441             dunrealized = comminfo.profitandloss(position.size, position.price,
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\linebuffer.py in __getitem__(self, ago)
          161 
          162     def __getitem__(self, ago):
      --> 163         return self.array[self.idx + ago]
          164 
          165     def get(self, ago=0, size=1):
      
      IndexError: array index out of range
      
      

      So here I think the issue is something that doesn't have data gets into next.
      But since no prenext or nextstart is printed, I have no clue how to filter the inputs of next before next starts...

      posted in General Code/Help
      J
      Jonny8

    Latest posts made by Jonny8

    • Normalize Indicator over several stocks while creating it

      Hi everyone,

      I would like to normalize the momentum indicator, i.e. the values of all stocks should range between 0 and 1. I fear it is not possible to do that within the indicator since the data of all stocks is needed to normalize it, isn't it?

      https://www.backtrader.com/blog/2019-05-20-momentum-strategy/momentum-strategy/

      '''
      class Momentum(bt.Indicator):
      lines = ('trend',)
      params = (('period', 90),)

      def __init__(self):
          self.addminperiod(self.params.period)
      
      def next(self):
          returns = np.log(self.data.get(size=self.p.period))
          x = np.arange(len(returns))
          slope, _, rvalue, _, _ = linregress(x, returns)
          annualized = (1 + slope) ** 252
          self.lines.trend[0] = annualized * (rvalue ** 2)
      

      '''
      So I thought the most straight forward way would be to divide every self.lines.trend[0] by the maximum self.lines.trend[0] of all stocks. But I don't know how to access that while creating the indicator...

      Any ideas for an easy implementation?
      Thanks in advance!

      posted in Indicators/Strategies/Analyzers normalization momentum indicator
      J
      Jonny8
    • RE: Live Trading OANDA Particle Swarm Optimization

      @waudinio27

      Hi Matthias,

      have you already checked out this post?
      https://community.backtrader.com/topic/186/genetic-optimization/7?_=1613131720503

      And as usual it helps to see all of your code.

      Best

      posted in General Code/Help
      J
      Jonny8
    • RE: Buy and Sell arrows not showing in Plot

      Which observers have u tried?

      I think they are part of stdstats
      https://www.backtrader.com/docu/observers-reference/
      https://www.backtrader.com/blog/posts/2016-12-10-buysellarrows/buysellarrows/

      posted in General Discussion
      J
      Jonny8
    • RE: optstrategy

      Which error comes up?
      Pardon me if I overread it, but didn't find the error message.

      posted in General Discussion
      J
      Jonny8
    • Exchange of your strategy evaluation indicators

      Hi everyone,

      I would like to know how you evaluate which strategy works better.

      I found this forum post which is insightful:
      https://www.omnitrader.com/currentclients/omnivestforum/thread-view.asp?threadid=6067&start=1

      In the beginning I was focusing merely on profits, but since these barely make a strategy sound, I would like to know what you are using. At the moment I am stuck with sharpe.

      But i am looking into the others given in quantstrat:

      Calmar
      Skew
      Kurtosis
      Kelly Criterion
      Risk of Ruin
      Daily Value-at-Risk
      Expected Shortfall (cVaR)
      Payoff Ratio
      Profit Factor
      Common Sense Ratio
      CPC Index
      Tail Ratio
      Outlier Win Ratio
      Outlier Loss Ratio
      Recovery Factor
      Ulcer Index

      So does anyone have recommendations / experiences to share?

      posted in General Discussion strategy evaluation
      J
      Jonny8
    • RE: Why I can't search for the documentation

      @Zhuorui-CAI

      niether can i. but rigth next to it is a google search bar which is working for me.

      posted in General Discussion
      J
      Jonny8
    • RE: Own indicator: "if function" with min max is very slow

      @crunchypickle

      Good call.

      I used cProfile to do it. https://towardsdatascience.com/how-to-profile-your-code-in-python-e70c834fad89

      There is a execution difference of 20% but it does not seem to come from min max or ceil, I assume it is due to the roc calculation in the init.

      Thank you chrunchypickle!

      posted in Indicators/Strategies/Analyzers
      J
      Jonny8
    • Own indicator: "if function" with min max is very slow

      Hi everyone,

      I am having a hard time creating / adapting an indicator.
      I made it in the most slow way and I wonder whether there is a better solution.

      The idea is to have an if positive RoC the 1 else 0.

      class Momentumplus_org(bt.Indicator):
          lines = ('trend',)
          params = (('period', 190), ('rperiod', 30))
          
          def __init__(self):
              self.addminperiod(self.params.period)
              self.roc = bt.ind.ROC(self.data, period=self.p.rperiod)
      
          def next(self):
              returns = np.log(self.data.get(size=self.p.period))
              x = np.arange(len(returns))
              slope, _, rvalue, _, _ = linregress(x, returns)
              annualized = (1 + slope) ** 252
              test = math.ceil(self.roc[0])
              rate = bt.Min(1, bt.Max(0, test))
              self.lines.trend[0] = annualized * (rvalue ** 2) * rate
      

      This takes a hell of a time to get calculated. I tried to get the test and rate into the init ...

      I also tried to keep the original design:

      def momentum_func(the_array):
          r = np.log(the_array)
          slope, _, rvalue, _, _ = linregress(np.arange(len(r)), r)
          annualized = (1 + slope) ** 252
          return annualized * (rvalue ** 2)
      
      
      class Momentum(bt.ind.OperationN):
          lines = ('trend',)
          params = dict(period=50)
          func = momentum_func
      

      But I couldn't make it work with two parameters...

      Are there better ways than math.ceil / min / max?

      Thank you very much in advance!

      Best

      posted in Indicators/Strategies/Analyzers momentum indicator if function
      J
      Jonny8
    • RE: cerebro.plot() report errors

      @T-yellow
      It would help to see you code.

      posted in General Code/Help
      J
      Jonny8
    • RE: Used Timer only works (partially) with _getminperstatus() ?

      @run-out

      @.@
      with zero

      strategy notify_timer with tid 0, when 2014-11-03 00:00:00 _getminperstatus 199
      timer
      next
      
      ---------------------------------------------------------------------------
      ZeroDivisionError                         Traceback (most recent call last)
      <ipython-input-10-5014d2b5e44f> in <module>
          134 # <<<Execute starting section>>>
          135 if __name__ == '__main__':
      --> 136     run()
      
      <ipython-input-10-5014d2b5e44f> in run(args)
          106                         timeframe=bt.TimeFrame.NoTimeFrame)
          107 
      --> 108     results = cerebro.run(maxcpus=1)#maxcpu=1 otherwise pickling multiprocessing errors
          109 
          110 # <<<Performance analysing section section>>>
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\cerebro.py in run(self, **kwargs)
         1125             # let's skip process "spawning"
         1126             for iterstrat in iterstrats:
      -> 1127                 runstrat = self.runstrategies(iterstrat)
         1128                 self.runstrats.append(runstrat)
         1129                 if self._dooptimize:
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\cerebro.py in runstrategies(self, iterstrat, predata)
         1296                     self._runnext_old(runstrats)
         1297                 else:
      -> 1298                     self._runnext(runstrats)
         1299 
         1300             for strat in runstrats:
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\cerebro.py in _runnext(self, runstrats)
         1628                 self._check_timers(runstrats, dt0, cheat=False)
         1629                 for strat in runstrats:
      -> 1630                     strat._next()
         1631                     if self._event_stop:  # stop if requested
         1632                         return
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\strategy.py in _next(self)
          345 
          346     def _next(self):
      --> 347         super(Strategy, self)._next()
          348 
          349         minperstatus = self._getminperstatus()
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\lineiterator.py in _next(self)
          261 
          262         for indicator in self._lineiterators[LineIterator.IndType]:
      --> 263             indicator._next()
          264 
          265         self._notify()
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\lineiterator.py in _next(self)
          261 
          262         for indicator in self._lineiterators[LineIterator.IndType]:
      --> 263             indicator._next()
          264 
          265         self._notify()
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\linebuffer.py in _next(self)
          619         elif clock_len == self._minperiod:
          620             # only called for the 1st value
      --> 621             self.nextstart()
          622         else:
          623             self.prenext()
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\lineroot.py in nextstart(self)
          142         calling next
          143         '''
      --> 144         self.next()
          145 
          146     def next(self):
      
      c:\users\mmd\appdata\local\programs\python\python36\lib\site-packages\backtrader\linebuffer.py in next(self)
          742     def next(self):
          743         if self.bline:
      --> 744             self[0] = self.operation(self.a[0], self.b[0])
          745         elif not self.r:
          746             if not self.btime:
      
      ZeroDivisionError: float division by zero
      
      
      
      posted in General Code/Help
      J
      Jonny8