Backtrader Community

    • 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/

    How to implement this strategy?

    General Code/Help
    1
    1
    19
    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.
    • anarchy89
      anarchy89 last edited by

      I previously was using the following code for my strategy.

      It was buy at open and readjust the portfolio the next day and I used daily data.

      My strategy has changed

      1. I buy at the beginning of the trading day during the first tick at open. Either a buy long or sell short or a mix of positions.

      2. I close either at 3:30pm, or at a take profit level called TPL of which I set everyday for different stocks, or at a stop loss which is different for each stock. All the above data is provided via dictionaries, either at % or absolute numbers.

      3. and I am currently using minute level data.

      How can I change my code here to accommodate my new strategy and the minute level data?

      This is my old code.

      import datetime
      import backtrader as bt
      
      
      class Strategy(bt.Strategy):
      
          params = (
              ("buffer", 0.05),
              ("threshold", 0.025),
          )
      
          def log(self, txt, dt=None):
              """ Logging function fot this strategy"""
              dt = dt or self.data.datetime[0]
              if isinstance(dt, float):
                  dt = bt.num2date(dt)
              print("%s, %s" % (dt.date(), txt))
      
          def print_signal(self):
              self.log(
                  f"o {self.datas[0].open[0]:7.2f} "
                  f"h {self.datas[0].high[0]:7.2f} "
                  f"l {self.datas[0].low[0]:7.2f} "
                  f"c {self.datas[0].close[0]:7.2f} "
                  f"v {self.datas[0].volume[0]:7.0f} "
              )
      
          def notify_order(self, order):
              """ Triggered upon changes to orders. """
              # Suppress notification if it is just a submitted order.
              if order.status == order.Submitted:
                  return
      
              # Print out the date, security name, order number and status.
              type = "Buy" if order.isbuy() else "Sell"
              self.log(
                  f"{order.data._name:<6} Order: {order.ref:3d} "
                  f"Type: {type:<5}\tStatus"
                  f" {order.getstatusname():<8} \t"
                  f"Size: {order.created.size:9.4f} Price: {order.created.price:9.4f} "
                  f"Position: {self.getposition(order.data).size:5.2f}"
              )
              if order.status == order.Margin:
                  return
      
              # Check if an order has been completed
              if order.status in [order.Completed]:
                  self.log(
                      f"{order.data._name:<6} {('BUY' if order.isbuy() else 'SELL'):<5} "
                      # f"EXECUTED for: {dn} "
                      f"Price: {order.executed.price:6.2f} "
                      f"Cost: {order.executed.value:6.2f} "
                      f"Comm: {order.executed.comm:4.2f} "
                      f"Size: {order.created.size:9.4f} "
                  )
      
          def notify_trade(self, trade):
              """Provides notification of closed trades."""
              if trade.isclosed:
                  self.log(
                      "{} Closed: PnL Gross {}, Net {},".format(
                          trade.data._name,
                          round(trade.pnl, 2),
                          round(trade.pnlcomm, 1),
                      )
                  )
      
          def __init__(self):
              for d in self.datas:
                  d.target = {
                      datetime.datetime.strptime(date, "%d-%b-%y").date(): allocation
                      for date, allocation in d.target.items()
                  }
      
          def next(self):
              date = self.data.datetime.date()
              track_trades = dict()
              total_value = self.broker.get_value() * (1 - self.p.buffer)
      
              for d in self.datas:
                  if date not in d.target:
                      if self.getposition(d):
                          self.close(d)
                      continue
                  target_allocation = d.target[date]
                  track_trades[d] = dict()
                  value = self.broker.get_value(datas=[d])
                  current_allocation = value / total_value
                  net_allocation = target_allocation - current_allocation
                  units_to_trade = (
                      (net_allocation) * total_value / d.close[0]
                  )
                  track_trades[d]["units"] = units_to_trade
      
                  # Can check to make sure there is enough distance away from ideal to trade.
                  track_trades[d]["threshold"] = abs(net_allocation) > self.p.threshold
      
              rebalance = False
              for values in track_trades.values():
                  if values["threshold"]:
                      rebalance = True
      
              if not rebalance:
                  return
      
              # Sell shares first
              for d, value in track_trades.items():
                  if value["units"] < 0:
                      self.sell(d, size=value["units"])
      
              # Buy shares second
              for d, value in track_trades.items():
                  if value["units"] > 0:
                      self.buy(d, size=value["units"])
      
      
      if __name__ == "__main__":
      
          cerebro = bt.Cerebro()
      
          allocations = [
              ("AAPL", "4-Jan-21", 0.300),
              ("TSM", "4-Jan-21", 0.200),
              ("IBM", "4-Jan-21", 0.300),
              ("KO", "4-Jan-21", 0.2000),
              ("AMD", "4-Jan-21", 0.1000),
              ("DELL", "5-Jan-21", 0.200),
              ("TSM", "5-Jan-21", 0.20),
              ("IBM", "5-Jan-21", 0.1),
              ("KO", "5-Jan-21", 0.1),
              ("NKE", "5-Jan-21", 0.15),
              ("TSLA", "5-Jan-21", 0.10),
              ("CSCO", "5-Jan-21", 0.050),
              ("JPM", "5-Jan-21", 0.1),
              ("AMD", "6-Jan-21", 0.25),
              ("BA", "6-Jan-21", 0.25),
              ("ORCL", "6-Jan-21", 0.50),
              ("AAPL", "7-Jan-21", 0.5000),
              ("KO", "7-Jan-21", 0.5000),
          ]
          ticker_names = list(set([alls[0] for alls in allocations]))
          targets = {ticker: {} for ticker in ticker_names}
          for all in allocations:
              targets[all[0]].update({all[1]: all[2]})
      
          for ticker, target in targets.items():
              data = bt.feeds.YahooFinanceData(
                  dataname=ticker,
                  timeframe=bt.TimeFrame.Days,
                  fromdate=datetime.datetime(2020, 12, 21),
                  todate=datetime.datetime(2021, 1, 8),
                  reverse=False,
              )
              data.target = target
              cerebro.adddata(data, name=ticker)
      
          cerebro.addstrategy(Strategy)
          cerebro.broker.setcash(1000000)
      
          # Execute
          cerebro.run()
      

      This is the new minute level data I have. Each company has it's own one.

      datetime                open	high	low	close	vol	
      2022-04-28 20:00:00	159.057356	159.146814	158.938077	159.047416	21258
      2022-04-28 19:59:00	159.156754	159.156754	159.057356	159.087175	8309
      2022-04-28 19:58:00	158.987777	159.186573	158.987777	159.146814	29998
      2022-04-28 19:57:00	158.948017	159.007656	158.948017	158.987777	25346
      2022-04-28 19:56:00	158.948017	158.977837	158.938077	158.948017	9495
      ...	...	...	...	...	...
      2022-03-30 04:05:00	176.670756	176.670756	176.630997	176.630997	1024
      2022-03-30 04:04:00	177.068350	177.068350	177.068350	177.068350	1112
      2022-03-30 04:03:00	177.088229	177.088229	177.088229	177.088229	714
      2022-03-30 04:02:00	177.068350	177.177688	177.068350	177.177688	402
      2022-03-30 04:01:00	177.426184	177.426184	177.028590	177.127989	3146
      

      This is the dataframe of my allocations for each day

          allocations = [
              ("AAPL", "4-Jan-21", 0.300),
              ("TSM", "4-Jan-21", 0.200),
              ("IBM", "4-Jan-21", 0.300),
              ("KO", "4-Jan-21", 0.2000),
              ("AMD", "4-Jan-21", 0.1000),
              ("DELL", "5-Jan-21", 0.200),
              ("TSM", "5-Jan-21", 0.20),
              ("IBM", "5-Jan-21", 0.1),
              ("KO", "5-Jan-21", 0.1),
              ("NKE", "5-Jan-21", 0.15),
              ("TSLA", "5-Jan-21", 0.10),
              ("CSCO", "5-Jan-21", 0.050),
              ("JPM", "5-Jan-21", 0.1),
              ("AMD", "6-Jan-21", 0.25),
              ("BA", "6-Jan-21", 0.25),
              ("ORCL", "6-Jan-21", 0.50),
              ("AAPL", "7-Jan-21", 0.5000),
              ("KO", "7-Jan-21", 0.5000),
          ]
      

      These are my take profit and stop loss levels.

          takeprofit= [
              ("AAPL", "4-Jan-21", 0.0700),
              ("TSM", "4-Jan-21", 0.02200),
      ........
      .........
          ]
      
          stoploss= [
              ("AAPL", "4-Jan-21", 0.100),
              ("TSM", "4-Jan-21", 0.0700),
      ........
      .........
          ]
      

      How can I modify the code to accommodate the new strategy and data?

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