Ive been learning from the community here and would like to put this out there to help anyone else who has been having difficulties making their strategies work with futures contacts. This is a simple BB system but it shows you how to add your indicator and update through history functions and that is a great starting template for most simple systems you might be trying to implement. Best Regards, Aegeanfutures 

 

  1. import pandas as pd
  2. class BollingerBandsAlgorithm(QCAlgorithm):
  3. def Initialize(self):
  4. self.SetStartDate(2018, 1, 1) #Set Start Date
  5. self.SetEndDate(2020, 1, 1) #Set End Date
  6. self.SetCash(100000) #Set Strategy Cash
  7. self.new_day = True
  8. self.contract = None
  9. # Subscribe and set our expiry filter for the futures chain
  10. futureES = self.AddFuture(Futures.Indices.SP500EMini)
  11. futureES.SetFilter(TimeSpan.FromDays(30), TimeSpan.FromDays(720))
  12. self.bb_period = 50
  13. self.bb_dev = 4
  14. def OnData(self, slice):
  15. self.InitUpdateContract(slice)
  16. def InitUpdateContract(self, slice):
  17. # Reset daily - everyday we check whether futures need to be rolled
  18. if not self.new_day:
  19. return
  20. if self.contract != None and (self.contract.Expiry - self.Time).days >= 3: # rolling 3 days before expiry
  21. return
  22. for chain in slice.FutureChains.Values:
  23. # If we trading a contract, send to log how many days until the contract's expiry
  24. if self.contract != None:
  25. self.Log('Expiry days away {} - {}'.format((self.contract.Expiry-self.Time).days, self.contract.Expiry))
  26. # Reset any open positions based on a contract rollover.
  27. self.Log('RESET: closing all positions')
  28. self.Liquidate()
  29. # get list of contracts
  30. contracts = list(chain.Contracts.Values)
  31. chain_contracts = list(contracts) #[contract for contract in chain]
  32. # order list of contracts by expiry date: newest --> oldest
  33. chain_contracts = sorted(chain_contracts, key=lambda x: x.Expiry)
  34. # pick out contract and log contract name
  35. self.contract = chain_contracts[1]
  36. self.Log("Setting contract to: {}".format(self.contract.Symbol.Value))
  37. # Set up consolidators.
  38. one_hour = TradeBarConsolidator(TimeSpan.FromMinutes(60))
  39. one_hour.DataConsolidated += self.OnHour
  40. self.SubscriptionManager.AddConsolidator(self.contract.Symbol, one_hour)
  41. # Set up indicators
  42. self.Bolband = self.BB(self.contract.Symbol, self.bb_period, self.bb_dev, MovingAverageType.Simple, Resolution.Hour)
  43. history = self.History(self.contract.Symbol, self.bb_period*60, Resolution.Minute).reset_index(drop=False)
  44. for bar in history.itertuples():
  45. if bar.time.minute == 0 and ((self.Time-bar.time)/pd.Timedelta(minutes=1)) >= 2:
  46. self.Bolband.Update(bar.time, bar.close)
  47. self.new_day = False
  48. def OnHour(self, sender, bar):
  49. if (self.Bolband != None and self.Bolband.IsReady) :
  50. if bar.Symbol == self.contract.Symbol:
  51. price = bar.Close
  52. holdings = self.Portfolio[self.contract.Symbol].Quantity
  53. # buy if price closes below lower bollinger band
  54. if holdings <= 0 and price < self.Bolband.LowerBand.Current.Value:
  55. self.Log("BUY >> {}".format(price))
  56. self.MarketOrder(self.contract.Symbol, 1)
  57. if holdings <= 0 and price > self.Bolband.UpperBand.Current.Value:
  58. self.Log("Sell >> {}".format(price))
  59. self.MarketOrder(self.contract.Symbol, -1)
  60. # sell if price closes above the upper bollinger band
  61. if self.Portfolio[self.contract.Symbol].IsLong and price > self.Bolband.UpperBand.Current.Value:
  62. self.Log("SELL >> {}".format(price))
  63. self.Liquidate()
  64. if self.Portfolio[self.contract.Symbol].IsShort and price < self.Bolband.LowerBand.Current.Value:
  65. self.Log("Buy >> {}".format(price))
  66. self.Liquidate()
  67. self.Plot("BB", "MiddleBand", self.Bolband.MiddleBand.Current.Value)
  68. self.Plot("BB", "UpperBand", self.Bolband.UpperBand.Current.Value)
  69. self.Plot("BB", "LowerBand", self.Bolband.LowerBand.Current.Value)
  70. else:
  71. self.Log('Bollinger Bands not ready yet')
  72. def OnEndOfDay(self):
  73. self.new_day = True
+ Expand

Author

AegeanFutures

May 2022