Code below, but quick walkthrough of it. Right now I'm just testing building the universe, later I'll be adjusting the long/short trades, but I have an issue where 1 symbol in the universe is not traded. I used this code as my base and have been modifying it.
I've got a unverse built with 4 underlytings: DIA, IWM, QQQ, and SPY, that are pulled from a csv file. These underlyings are parsed from the columns of a pandas Dataframe so I can adjust which underlyings are traded by adding a column for it. These are then added to the self.current_universe variable and returned by selector(). During debug logging I can see all 4 underlyings are added to self.current_universe, but when OnData() is processing SPY is nevertraded, so the portfolio is split between DIA, IWM, and QQQ.
Any thoughts about how to determine or debug why SPY is ignored?
Also, what is the best way to liquidate all holdings at the close of trading?
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm import QCAlgorithm
from QuantConnect.Data.UniverseSelection import *
from datetime import datetime
import decimal as d
import pandas as pd
class DropboxUniverseSelectionAlgorithm(QCAlgorithm):
def Initialize(self):
self.Debug("Execution Flow: Entering Initialize")
self.SetStartDate(2012,12,4)
self.SetEndDate(2017,10,13)
self.backtestSymbolsPerDay = None
self.current_universe = []
self.UniverseSettings.Resolution = Resolution.Daily;
self.AddUniverse("mxyzptlk", self.selector)
#self.Debug("Initializing, universe = " + ', '.join(self.current_universe))
def selector(self, data):
self.Debug("Execution Flow: Entering Selector")
##Fetch the csv file from dropbox and convert it to a pandas dataframe
# handle live mode file format
if self.LiveMode:
self.Debug("Execution Flow: Entering Selector::LivLiveMode")
# fetch the file from dropbox
url = ""
df = pd.read_csv(url, header = None)
# if we have a file for today, return symbols
if not df.empty:
self.current_universe = df.iloc[0,:].tolist()
# no symbol today, leave universe unchanged
return self.current_universe
# backtest - first cache the entire file
if self.backtestSymbolsPerDay is None:
self.Debug("Execution Flow: Entering Selector::backtestSymbolsPerDay")
url = "<REDACTED>"
#Create DataFrame from CSV
self.backtestSymbolsPerDay = pd.read_csv(url, header=[0,1], index_col=0)
index = str(data.strftime("%Y/%m/%d"))
if index in self.backtestSymbolsPerDay.index:
self.Debug("Execution Flow: selector::indexing")
self.current_universe = []
for item in self.backtestSymbolsPerDay.loc[index,:].dropna().index.tolist():
self.current_universe.append(item[0])
self.Debug("Selector, current_universe = " + str(self.current_universe))
return self.current_universe
def OnData(self, slice):
self.Debug("Execution Flow: Entering OnData")
if slice.Bars.Count == 0: return
if self.changes == None: return
# start fresh
self.Debug("Execution Flow: OnData::Liquidating")
self.Liquidate()
percentage = 1 / d.Decimal(slice.Bars.Count)
self.Debug("OnData/for(TradeBar), set holdings: slice.Bars.Keys = " + str(slice.Bars.Keys))
for tradeBar in slice.Bars.Values:
self.SetHoldings(tradeBar.Symbol, percentage)
self.Debug("tradeBar.Symbol = " + str(tradeBar.Symbol) + " @ \npercentage = " +str(percentage))
# reset changes
self.changes = None
def OnSecuritiesChanged(self, changes):
self.Debug("Execution Flow: Entering OnSecuritiesChanged")
self.changes = changes
2012-12-04 00:00:00 : Launching analysis for 3e0de60cbaa318a4e77bb7899d70a926 with LEAN Engine v2.4.0.1.2319
2012-12-04 00:00:00 : Execution Flow: Entering Initialize
2012-12-04 00:00:00 : Execution Flow: Entering Selector
2012-12-04 00:00:00 : Execution Flow: Entering Selector::backtestSymbolsPerDay
2012-12-04 00:00:00 : Execution Flow: selector::indexing
2012-12-04 00:00:00 : Selector, current_universe = ['DIA', 'IWM', 'QQQ', 'SPY']
2012-12-04 00:00:00 : Execution Flow: Entering OnSecuritiesChanged
2012-12-04 00:00:00 : Execution Flow: Entering OnData
2012-12-04 00:00:00 : Execution Flow: OnData::Liquidating
2012-12-04 00:00:00 : OnData/for(TradeBar), set holdings: slice.Bars.Keys = System.Collections.Generic.Dictionary`2+KeyCollection[QuantConnect.Symbol,QuantConnect.Data.Market.TradeBar]
2012-12-04 00:00:00 : Converted OrderID: 1 into a MarketOnOpen order.
2012-12-04 00:00:00 : tradeBar.Symbol = IWM RV0PWMLXVHPH @ percentage = 0.3333333333333333333333333333
2012-12-04 00:00:00 : Converted OrderID: 2 into a MarketOnOpen order.
2012-12-04 00:00:00 : tradeBar.Symbol = QQQ RIWIV7K5Z9LX @ percentage = 0.3333333333333333333333333333
2012-12-04 00:00:00 : Converted OrderID: 3 into a MarketOnOpen order.
2012-12-04 00:00:00 : tradeBar.Symbol = DIA R7KVSI4AAX5X @ percentage = 0.3333333333333333333333333333
2012-12-05 00:00:00 : Execution Flow: Entering Selector
2012-12-05 00:00:00 : Execution Flow: selector::indexing
2012-12-05 00:00:00 : Selector, current_universe = ['DIA', 'IWM', 'QQQ', 'SPY']
2012-12-05 00:00:00 : Execution Flow: Entering OnData