| Overall Statistics |
|
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio -1.283 Tracking Error 0.099 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset |
import pandas as pd
import datetime
class LogicalFluorescentOrangeButterfly(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2017, 1, 1)
self.SetEndDate(2018,5,1)
self.SetCash(1000000)
self.spy=self.AddEquity("SPY", Resolution.Minute)
self.futures_bar_resolution=15 # 15 ie consolidate 1 min bar to 15min
self.consolidator_dict={} # this is to keep track of the consolidator and hence can remove effciently
self.generate_futures_dict()
self.futures_child_to_parent_mapping_dict={}
self.last_futures_active_contract_checked=0 # will only check if a future is active once a day
self.last_spy_checked=0 # similar to above, but it is to check SPY
def OnData(self, data):
''' OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
Arguments:
data: Slice object keyed by symbol containing the stock data
'''
self.OnData_for_futures(data)
if self.Time.hour>=9:
if data.ContainsKey(self.spy.Symbol):
if self.Time.date()!=self.last_spy_checked:
self.last_spy_checked=self.Time.date()
self.Plot('Custom', 'es', str(10*data.Bars[self.spy.Symbol].Close))
self.Plot('Custom', '/es', str(self.futures_data_dict['/ES']['dataframe']['close'].iloc[-1]))
## helpers
def OnData_for_futures(self,data):
if self.Time.date()!=self.last_futures_active_contract_checked:
self.last_futures_active_contract_checked=self.Time.date()
for chain in data.FutureChains.Values:
contracts = chain.Contracts
sorted_by_oi_contracts = sorted(contracts.Values, key=lambda k: k.OpenInterest, reverse=True)
popular_contracts = sorted_by_oi_contracts[:3]
active_contract=sorted_by_oi_contracts[0]
if active_contract.Symbol!=self.futures_data_dict[str(chain.Symbol)]['active_symbol']:
last_contract_price=0
self.futures_child_to_parent_mapping_dict[str(active_contract.Symbol)]=str(chain.Symbol)
self.futures_data_dict[str(chain.Symbol)]['last_active_symbol']=self.futures_data_dict[str(chain.Symbol)]['active_symbol']
self.futures_data_dict[str(chain.Symbol)]['active_symbol']=str(active_contract.Symbol)
self.Log('active contract change for {}, from {} to {}'.format(str(chain.Symbol), self.futures_data_dict[str(chain.Symbol)]['last_active_symbol'], self.futures_data_dict[str(chain.Symbol)]['active_symbol']))
self.Log('new contract expiry is {}'.format(active_contract.Expiry))
if self.futures_data_dict[str(chain.Symbol)]['last_active_symbol']==None:
pass
else:
for tmp_contract in popular_contracts[1:]:
if str(tmp_contract.Symbol)==self.futures_data_dict[str(chain.Symbol)]['last_active_symbol']:
last_contract_price=tmp_contract.LastPrice
if last_contract_price==0: # 2017/12/31, ES front month contract has strange (nil?) data for a day
last_contract_price=self.futures_data_dict[str(chain.Symbol)]['dataframe']['close'][-1]
self.futures_data_dict[str(chain.Symbol)]['new_old_ratio']=active_contract.LastPrice / last_contract_price
self.futures_data_dict[str(chain.Symbol)]['dataframe']=self.futures_data_dict[str(chain.Symbol)]['dataframe']*self.futures_data_dict[str(chain.Symbol)]['new_old_ratio']
self.Log('attempting to delete existing symbol {}'.format(self.futures_data_dict[str(chain.Symbol)]['last_active_symbol']))
self.SubscriptionManager.RemoveConsolidator(self.futures_data_dict[str(chain.Symbol)]['last_active_symbol'], self.consolidator_dict[self.futures_data_dict[str(chain.Symbol)]['last_active_symbol']])
del self.consolidator_dict[self.futures_data_dict[str(chain.Symbol)]['last_active_symbol']]
self.consolidator_dict[self.futures_data_dict[str(chain.Symbol)]['active_symbol']] = TradeBarConsolidator(timedelta(minutes=self.futures_bar_resolution))
self.consolidator_dict[self.futures_data_dict[str(chain.Symbol)]['active_symbol']].DataConsolidated += self.Futures_OneMinuteBarHandler
self.SubscriptionManager.AddConsolidator(active_contract.Symbol, self.consolidator_dict[self.futures_data_dict[str(chain.Symbol)]['active_symbol']])
self.futures_data_dict[str(chain.Symbol)]['last_rolled_date']=self.Time.date()
def Futures_OneMinuteBarHandler(self, sender, bar):
contract_symbol = sender.Consolidated.Symbol
parent_symbol=self.futures_child_to_parent_mapping_dict[str(contract_symbol)]
self.futures_data_dict[parent_symbol]['dataframe']=pd.concat([self.futures_data_dict[parent_symbol]['dataframe'], pd.DataFrame({'open':bar.Open, 'high':bar.High, 'low':bar.Low, 'close':bar.Close}, index=[bar.EndTime])],axis=0)
def generate_futures_dict(self):
self.futures_data_dict={}
self.futures_data_dict['/ES']={'code':Futures.Indices.SP500EMini}
#self.futures_data_dict['/MID']={'code':Futures.Indices.SP400MidCapEmini}
self.futures_data_dict['/YM']={'code':Futures.Indices.Dow30EMini}
#self.futures_data_dict['/RTY']={'code':Futures.Indices.Russell2000EMini}
self.futures_data_dict['/GC']={'code':Futures.Metals.Gold}
self.futures_data_dict['/SI']={'code':Futures.Metals.Silver}
#self.futures_data_dict['/PL']={'code':Futures.Metals.Platinum}
#self.futures_data_dict['/PA']={'code':Futures.Metals.Palladium}
#self.futures_data_dict['/HG']={'code':Futures.Metals.Copper}
for future in self.futures_data_dict.keys():
self.futures_data_dict[future]['active_symbol']=None
self.futures_data_dict[future]['last_rolled_date']=self.Time.date()-datetime.timedelta(days=100)
self.futures_data_dict[future]['dataframe']=pd.DataFrame([],columns=['open','high','low','close'])
tmp = self.AddFuture(self.futures_data_dict[future]['code'], Resolution.Minute)
tmp.SetFilter(lambda universe: universe.Expiration(timedelta(0), timedelta(182)))