Backtrader Community

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

    Posts made by joeyy

    • cerebro.optstrategy slow AF on mac and really fast on Windows ?

      Hi All!

      This is such an esoteric problem and I don't suppose others have encountered it, but I figured it might be worth a shot.
      I have a strategy which I want to test across thousands and thousands of permutations via cerebro.optstrategy.
      When I run it on my macbook pro it's ridiculously slow and is able to compute about 5-6 results per minute, which basically makes it unusable.
      Then if I run the same code on a mediocre windows machine it generates hundreds of results per minute.
      Has anyone experienced anything similar ? Is there a config somewhere where I can make it more CPU intensive / add threads ?

      Thanks in advance!

      posted in General Code/Help
      J
      joeyy
    • RE: Is there a way to differentiate 2 streams of sampled data in the next function ?

      this is def. better, thanks!

      posted in General Discussion
      J
      joeyy
    • RE: indicator always runs on the shorter candle timeframe

      I figured it out. It was as simple as adding the timeframe to the indicator init as such

      self.ema = bt.ind.EMA(self.data1, period=self.p.period)
      
      posted in General Code/Help
      J
      joeyy
    • indicator always runs on the shorter candle timeframe

      hi everyone and happy holidays,

      I have a strategy that combines 2 timeframes, 1 every 5 minutes to make snappy decisions such as a stop loss and another 4 hours timeframe that runs the strategy.

      If I add an indicator, such as EMA

      self.ema = bt.ind.EMA(period=self.p.period)
              self.ema = btind.ExponentialMovingAverage(period=self.p.period)
      

      And instantiate 2 timeframes

       data_ticks_long = bt.feeds.CCXT(
              exchange='binance',
              symbol=symbol,
              timeframe=bt.TimeFrame.Minutes,
              config={'rateLimit': 1000, 'enableRateLimit': True},
              fromdate=from_date,
              compression=STRATEGY_CANDLE_SIZE_IN_MINUTES
          )
      
          data_ticks_short = bt.feeds.CCXT(
              exchange='binance',
              symbol=symbol,
              timeframe=bt.TimeFrame.Minutes,
              config={'rateLimit': 1000, 'enableRateLimit': True},
              fromdate=from_date,
              compression=STOPLOSS_CANDLE_SIZE_IN_MINUTES
          )
      

      it would build the EMA line based on the ticks in the next function. Since the shorter timeframe happens every 5 minutes my EMA will be built entirely from that timeframe.
      How do I get my indicator to be based on the longer, 4 hours, timeframe ?

      thanks!

      posted in General Code/Help
      J
      joeyy
    • RE: Is there a way to differentiate 2 streams of sampled data in the next function ?

      That makes sense, I do wish to replace my hack with something more sustainable. Perhaps the link you were looking for was this one -
      https://community.backtrader.com/topic/1329/how-to-determine-if-the-data-is-being-replayed-in-strategy

      posted in General Discussion
      J
      joeyy
    • RE: Is there a way to differentiate 2 streams of sampled data in the next function ?

      thank you ab_trader!
      your answer got me most of the way. I can split the logic in my next function based on the index of the self.datas object.
      There is one caveat though. If I want to compare the indicator's value to one of the timeframe, it will get evaluated for every tick, and might satisfy a greater than / less than condition in the wrong tick. In other words, if I have an SMA, and 2 candles: one is 5min, the other 60min, and I want to buy based on the SMA cross with the 60min candle, it will still get checked every 5min and the SMA will change in every iteration. Therefore I might be making trades without waiting for the 60min tick.

      I solved it by adding a flag that checks if the slow indicator value has changed, which stays the same for every fast tick, i.e -

      if(self.last_candle_ref_price != self.data1.lines.close[0]):
         if self.sma.lines.sma[0] < self.data1.lines.close[0]:
            <do something>
      
      self.last_candle_ref_price = self.data1.lines.close[0]
      
      posted in General Discussion
      J
      joeyy
    • RE: Is there a way to differentiate 2 streams of sampled data in the next function ?

      this doesn't work, won't tell you anything about the current tick compression

      posted in General Discussion
      J
      joeyy
    • RE: Is there a way to differentiate 2 streams of sampled data in the next function ?

      correction: the longer timeframe

      posted in General Discussion
      J
      joeyy
    • RE: Is there a way to differentiate 2 streams of sampled data in the next function ?

      thanks for the reply! unfortunately self.data.p.compression always returns the shorter timeframe

      2017-08-18 00:00:00, EMA PRICE 4357.05,  CLOSE PRICE 4286.53, TIME FRAME : 60
      2017-08-18 01:00:00, EMA PRICE 4346.73,  CLOSE PRICE 4243.59, TIME FRAME : 60
      2017-08-18 02:00:00, EMA PRICE 4339.54,  CLOSE PRICE 4267.59, TIME FRAME : 60
      2017-08-18 03:00:00, EMA PRICE 4335.25,  CLOSE PRICE 4292.39, TIME FRAME : 60
      2017-08-18 04:00:00, EMA PRICE 4330.95,  CLOSE PRICE 4287.92, TIME FRAME : 60
      2017-08-18 05:00:00, EMA PRICE 4329.37,  CLOSE PRICE 4313.56, TIME FRAME : 60
      2017-08-18 06:00:00, EMA PRICE 4324.83,  CLOSE PRICE 4279.46, TIME FRAME : 60
      2017-08-18 07:00:00, EMA PRICE 4322.60,  CLOSE PRICE 4300.25, TIME FRAME : 60
      2017-08-18 08:00:00, EMA PRICE 4318.97,  CLOSE PRICE 4282.73, TIME FRAME : 60
      2017-08-18 09:00:00, EMA PRICE 4317.62,  CLOSE PRICE 4304.15, TIME FRAME : 60
      2017-08-18 10:00:00, EMA PRICE 4321.14,  CLOSE PRICE 4356.31, TIME FRAME : 60
      2017-08-18 11:00:00, EMA PRICE 4322.88,  CLOSE PRICE 4340.31, TIME FRAME : 60
      2017-08-18 12:00:00, EMA PRICE 4323.69,  CLOSE PRICE 4331.71, TIME FRAME : 60
      2017-08-18 13:00:00, EMA PRICE 4320.90,  CLOSE PRICE 4293.09, TIME FRAME : 60
      2017-08-18 14:00:00, EMA PRICE 4315.31,  CLOSE PRICE 4259.40, TIME FRAME : 60
      2017-08-18 15:00:00, EMA PRICE 4308.18,  CLOSE PRICE 4236.89, TIME FRAME : 60
      2017-08-18 16:00:00, EMA PRICE 4302.93,  CLOSE PRICE 4250.34, TIME FRAME : 60
      2017-08-18 17:00:00, EMA PRICE 4292.96,  CLOSE PRICE 4193.35, TIME FRAME : 60
      2017-08-18 18:00:00, EMA PRICE 4277.00,  CLOSE PRICE 4117.41, TIME FRAME : 60
      2017-08-18 19:00:00, EMA PRICE 4264.21,  CLOSE PRICE 4136.28, TIME FRAME : 60
      2017-08-18 20:00:00, EMA PRICE 4242.11,  CLOSE PRICE 4021.11, TIME FRAME : 60
      2017-08-18 21:00:00, EMA PRICE 4217.89,  CLOSE PRICE 3975.69, TIME FRAME : 60
      2017-08-18 22:00:00, EMA PRICE 4208.42,  CLOSE PRICE 4113.75, TIME FRAME : 60
      2017-08-18 23:00:00, EMA PRICE 4199.33,  CLOSE PRICE 4108.37, TIME FRAME : 60
      2017-08-19 00:00:00, EMA PRICE 4196.07,  CLOSE PRICE 4163.49, TIME FRAME : 60
      2017-08-19 01:00:00, EMA PRICE 4191.75,  CLOSE PRICE 4148.53, TIME FRAME : 60
      2017-08-19 02:00:00, EMA PRICE 4188.53,  CLOSE PRICE 4156.39, TIME FRAME : 60
      
      posted in General Discussion
      J
      joeyy
    • RE: Is there a way to differentiate 2 streams of sampled data in the next function ?

      A more concrete example is having 1 SMA and needing to write logic that's different based on the compression you're viewing

      posted in General Discussion
      J
      joeyy
    • Is there a way to differentiate 2 streams of sampled data in the next function ?

      Hello All,

      Imagine you have something that looks like that:

      import backtrader as bt
      import backtrader.feeds as btfeeds
      import backtrader.indicators as btind
      
      
      class TimeFrameStrategy(bt.Strategy):
          def __init__(self):
              self.sma_small_tf = btind.SMA(self.data, period=10)
              self.sma_large_tf = btind.SMA(self.data1, period=30)
      
          def next(self):
              print("{}, sma small {:.2f},  sma large {:.2f}".format(self.data.datetime.datetime(), self.sma_small_tf[0], self.sma_large_tf[0]))
      
      def runstrat():
      
          cerebro = bt.Cerebro()
      
          cerebro.addstrategy(TimeFrameStrategy)
      
          datapath = "data/dev.csv"
          data = btfeeds.GenericCSVData(
              dataname=datapath,
              timeframe=bt.TimeFrame.Minutes,
              compression=1,
              format="%Y-%m-%d %H:%M:%S",
          )
      
          cerebro.resampledata(data, timeframe=bt.TimeFrame.Minutes, compression=5)
          cerebro.resampledata(data, timeframe=bt.TimeFrame.Minutes, compression=60)
      
          cerebro.run()
      
      if __name__ == "__main__":
          runstrat()
      

      How can one handle the data differently based on the sampled compression ?
      For instance, I might want to use the 60min for executing trades and the 5min candle for stoploss.

      Any help would be appreciated!

      posted in General Discussion
      J
      joeyy
    • RE: can't get 2 timeframes to plot in 1 graph

      I can always add this to show only the shorter timeframe graph

      data_ticks_long.plotinfo.plot=False
      

      so I guess my question is how can I get both the strategy line and buy/sell signals to show on the long timeframe graph instead ?

      posted in General Code/Help
      J
      joeyy
    • can't get 2 timeframes to plot in 1 graph

      Hi all,

      I'm trying to run a strategy that uses 1 indicator and 2 timeframes, 1 long for the strategy and 1 short for stoploss. I know backtrader already has a built in mechanism for stoploss but I want to use it for live trading too so I need to have control over what to send to the brokerage when that happens.

      I have 2 candles one for 240 minutes and another for 15 minutes.
      I can see the results plotted as 2 graphs, but I only want the longer timeframe to be plotted. More over, the buy and sell arrows should be drawn on the longer candle, which isn't the case.

      plot

      this is the relevant code

       # Create a cerebro entity
          cerebro = bt.Cerebro()
      
          # Add a strategy
          cerebro.addstrategy(EmaCross)
      
          data_ticks_long = bt.feeds.CCXT(
              exchange='binance',
              symbol='BTC/USDT',
              name='EMA 21',
              timeframe=bt.TimeFrame.Minutes,
              fromdate=FROM_DATE,
              todate=TO_DATE,
              historical='True',
              compression=STRATEGY_CANDLE_SIZE_IN_MINUTES)
      
          data_ticks_short = bt.feeds.CCXT(
              exchange='binance',
              symbol='BTC/USDT',
              name='STOP_LOSS',
              timeframe=bt.TimeFrame.Minutes,
              fromdate=FROM_DATE,
              todate=TO_DATE,
              historical='True',
              compression=STOPLOSS_CANDLE_SIZE_IN_MINUTES)
      
          # Add the Data Feed to Cerebro
          cerebro.adddata(data_ticks_short)
      
          cerebro.adddata(data_ticks_long)
      
          # Set our desired cash start
          cerebro.broker.setcash(STARTING_BALANCE)
      
          # Add a FixedSize sizer according to the stake
          cerebro.addsizer(bt.sizers.PercentSizer,percents=95)
      
          # Set the commission
          cerebro.broker.setcommission(commission=COMMISION)
      
          # 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())
      
          # Plot the result
          # cerebro.plot(style='candlestick', barup='green', bardown='red')
          cerebro.plot()
      

      I tried using plotinfo.sameaxis = True or plotinfo.plotmaster but it throws a
      KeyError: <backtrader.feeds.ccxt.CCXT object at 0x7fe9e2959250>

      Any help would be really appreciated!

      posted in General Code/Help
      J
      joeyy
    • RE: notify_order shows wrong calculations

      Perfect! so the BUY/SELL show the underlying single unit asset price whereas the PROFIT is the delta times the stake size (minus commission). It adds up. Thank you Rajanprabu!

      posted in General Code/Help
      J
      joeyy
    • RE: notify_order shows wrong calculations

      As you can see from the first line, 7079.00 (buy) - 7468.99 (sell) - 71.50 (commission) = -461.49 (not -5117.39)

      posted in General Code/Help
      J
      joeyy
    • notify_order shows wrong calculations

      Hi All,

      I'm running some backtesting and have noticed over multiple examples that my notify_order don't match the trades. Not sure where it's coming from.

      STARTING_BALANCE = 100000.0
      FROM_DATE = datetime(2017, 11, 1)
      TO_DATE = datetime(2020, 11, 25)
      COMMISION = 0.00075
      
        def notify_order(self, order):
              # 1. If order is submitted/accepted, do nothing
              if order.status in [order.Submitted, order.Accepted]:
                  return
              # 2. If order is buy/sell executed, report price executed
              if order.status in [order.Completed]:
                  if order.isbuy():
                      self.log('BUY EXECUTED, Price: {0:8.2f}, Size: {1:8.2f} Cost: {2:8.2f}, Comm: {3:8.2f}'.format(
                          order.executed.price,
                          order.executed.size,
                          order.executed.value,
                          order.executed.comm))
      
                      self.buyprice = order.executed.price
                      self.buycomm = order.executed.comm
                  else:
                      self.log('SELL EXECUTED, {0:8.2f}, Size: {1:8.2f} Cost: {2:8.2f}, Comm{3:8.2f}'.format(
                          order.executed.price,
                          order.executed.size,
                          order.executed.value,
                          order.executed.comm))
      
                  self.bar_executed = len(self)  # when was trade executed
              # 3. If order is canceled/margin/rejected, report order canceled
              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
      
              self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                       (trade.pnl, trade.pnlcomm))
      
      

      This is the beginning of my output:

      2017-11-08, BUY EXECUTED, Price:  7468.99, Size:    12.76 Cost: 95339.67, Comm:    71.50
      2017-11-10, SELL EXECUTED,  7079.00, Size:   -12.76 Cost: 95339.67, Comm   67.77
      2017-11-10, OPERATION PROFIT, GROSS -4978.12, NET -5117.39
      2017-11-15, BUY EXECUTED, Price:  7248.98, Size:    12.44 Cost: 90187.99, Comm:    67.64
      2017-12-20, SELL EXECUTED, 17295.20, Size:   -12.44 Cost: 90187.99, Comm  161.38
      2017-12-20, OPERATION PROFIT, GROSS 124989.78, NET 124760.76
      2017-12-26, BUY EXECUTED, Price: 15649.99, Size:    13.33 Cost: 208674.39, Comm:   156.51
      2017-12-28, SELL EXECUTED, 14045.94, Size:   -13.33 Cost: 208674.39, Comm  140.46
      2017-12-28, OPERATION PROFIT, GROSS -21388.14, NET -21685.11
      2018-01-03, BUY EXECUTED, Price: 15170.00, Size:    12.40 Cost: 188060.34, Comm:   141.05
      2018-01-09, SELL EXECUTED, 14902.54, Size:   -12.40 Cost: 188060.34, Comm  138.56
      2018-01-09, OPERATION PROFIT, GROSS -3315.66, NET -3595.27
      2018-01-20, BUY EXECUTED, Price: 12539.08, Size:    14.73 Cost: 184645.28, Comm:   138.48
      2018-01-21, SELL EXECUTED, 11420.99, Size:   -14.73 Cost: 184645.28, Comm  126.14
      2018-01-21, OPERATION PROFIT, GROSS -16464.53, NET -16729.15
      2018-01-28, BUY EXECUTED, Price: 11499.98, Size:    14.69 Cost: 168884.02, Comm:   126.66
      2018-01-29, SELL EXECUTED, 11383.91, Size:   -14.69 Cost: 168884.02, Comm  125.38
      2018-01-29, OPERATION PROFIT, GROSS -1704.56, NET -1956.60
      2018-02-10, BUY EXECUTED, Price:  8683.93, Size:    19.22 Cost: 166893.56, Comm:   125.17
      2018-02-23, SELL EXECUTED,  9815.55, Size:   -19.22 Cost: 166893.56, Comm  141.48
      2018-02-23, OPERATION PROFIT, GROSS 21748.23, NET 21481.58
      2018-02-27, BUY EXECUTED, Price: 10321.00, Size:    18.14 Cost: 187246.44, Comm:   140.43
      2018-03-07, SELL EXECUTED, 10716.48, Size:   -18.14 Cost: 187246.44, Comm  145.82
      2018-03-07, OPERATION PROFIT, GROSS 7174.91, NET 6888.66
      2018-03-20, BUY EXECUTED, Price:  8595.01, Size:    22.54 Cost: 193732.62, Comm:   145.30
      2018-03-25, SELL EXECUTED,  8468.85, Size:   -22.54 Cost: 193732.62, Comm  143.17
      2018-03-25, OPERATION PROFIT, GROSS -2843.66, NET -3132.13
      2018-04-03, BUY EXECUTED, Price:  7370.01, Size:    25.90 Cost: 190869.57, Comm:   143.15
      2018-04-05, SELL EXECUTED,  6796.10, Size:   -25.90 Cost: 190869.57, Comm  132.00
      2018-04-05, OPERATION PROFIT, GROSS -14863.20, NET -15138.36
      2018-04-09, BUY EXECUTED, Price:  7011.04, Size:    25.15 Cost: 176313.10, Comm:   132.23
      2018-04-10, SELL EXECUTED,  6781.55, Size:   -25.15 Cost: 176313.10, Comm  127.91
      2018-04-10, OPERATION PROFIT, GROSS -5771.20, NET -6031.34```
      
      As you can see from the first line, 7079.00 (buy) - 7468.99 (sell) - 71.50 (commission) = -461.49 (not -5117.39)
      
      thanks in advance!
      posted in General Code/Help
      J
      joeyy
    • RE: Prevent live trading during "warm up" period

      i think I got it, I can do something like this

      def notify_data(self, data, status, *args, **kwargs):
          print('*' * 5, 'DATA NOTIF:', data._getstatusname(status))
          if status == data.LIVE:
              self.datastatus = 1
          else:
              self.datastatus = 0
      

      and then use it in your next example.
      awesome, thanks!

      posted in General Code/Help
      J
      joeyy
    • RE: Prevent live trading during "warm up" period

      thanks for the quick reply. I'm indeed looking for a flag that will tell me if it's a live, delayed or simulated trade.
      Unfortunately self.datastatus doesn't seem to work

       def next(self):
              print(self.datastatus)
      

      I'm getting a

      AttributeError: 'Lines_LineSeries_LineIterator_DataAccessor_Strateg' object has no attribute 'datastatus'
      
      posted in General Code/Help
      J
      joeyy
    • Prevent live trading during "warm up" period

      Hey all!
      I've setup a strategy which seem to work alright and I've run simulations using backtrader and would now like to use it for live trading too.
      The problem is that if I let it run for several candles to "warm up" the strategy, it will get buy/sell signals and try to execute trades on these historical candles. The reason being is that for instance for a 1 day candle and a 21 EMA I don't have to wait a few weeks to get a signal.
      Is there a way to run it's "warm up" period and only make trades when it makes it to the ***** DATA NOTIF: LIVE period ?

      I've run it using these two CCXT implementations, one by Dave-Vallance
      and the other by Ed Bartosh':

      from_date = datetime.utcnow() - timedelta(days=1)
      data_ticks = bt.feeds.CCXT(
              exchange='binance',
              symbol='BTC/USDT',
              timeframe=bt.TimeFrame.Minutes,
              config={'rateLimit': 1000, 'enableRateLimit': True},
              fromdate=from_date,
              compression=5
          )
      
      store = CCXTStore(exchange='binance', currency='USDT', config={
                            'rateLimit': 1000, 'enableRateLimit': True}, retries=5, debug=False)
      
          hist_start_date = datetime.utcnow() - timedelta(days=3)
          data_ticks = store.getdata(dataname='BTC/USDT',
                                     name="BTCUSDT",
                                     timeframe=bt.TimeFrame.Minutes,
                                     fromdate=hist_start_date,
                                     compression=60,
                                     ohlcv_limit=500,
                                     drop_newest=True)
      

      thanks in advance!

      posted in General Code/Help
      J
      joeyy
    • 1 / 1