Hi All,
I've written a couple of options algorithms now and wondering if anyone can share some best practices to make them backtest more quickly?
I've built algorithms using the option chain (I wanted the Greeks) and I've also tried just adding a specific contract (cannot use the Greeks this way because there is no pricing model).
So far my tests have focused on a single equity and those run much slower than equities. I understand there is much more data to be processed and assume that is why it is slower.
In order to get access to data like the greeks and implied volatitliy for decision purposes we have to use the Option Chain.
I'm just curious for people who have written Option algorithms, do you have any best practices you follow? Do you limit the number of equities you use in one algorithm at a given time?
Karthik Kailash
One trick I discovered while trying to make an option algo run faster was to make the OptionChainUniverse dynamic. My algo needed to look at all the contracts for many equities in the morning, but then didn't need them for the rest of the day. So my filter function passed to OptionChainUniverse via AddUniverseOptions looked something like this:
def OptionFilter(self, optionFilterUniverse): # Referencing Underlying changes the option universe to dynamic (runs filter every minute). So does calling strikes() or any of the # OptionFilterUniverseEx methods. Just leaving this in to be explicit about what we are trying to do. underlying = optionFilterUniverse.Underlying # Only return contracts Thursday afternoon and Friday morning so we don't have to process all the option trade data on Thursday # but we will still get the open interest tick at midnight if (self.Time.weekday() == 3 and self.Time - self.Time.replace(hour=0, minute=0) >= timedelta(hours=15, minutes=55)) or (self.Time.weekday() == 4 and self.Time - self.Time.replace(hour=0,minute=0) < timedelta(hours=9, minutes=35)): return optionFilterUniverse.IncludeWeeklys().Expiration(0, 1) else: # All other times return empty list (won't cause the options we are keeping around to be removed because we don't set their cache to empty) return OptionFilterUniverseEx.WhereContains(optionFilterUniverse, [])
What the comment above the last line of code is alluding to: I found that the OptionChainUniverse::CanRemoveMember() won't return False until the next day. Which means you are still subscribed to and receiving data for all the contracts you no longer care about. But, it has a check where if it thinks it hasn't receive data yet for a security, it will allow it to be removed.
// if we haven't begun receiving data for this security then it's safe to remove var lastData = security.Cache.GetData(); if (lastData == null) { return true; }
So, in conjunction with returning an empty list for the OptionFilterUniverse, we can reset the caches of everything we don't want:
class EmptySecurityCache(SecurityCache): def AddData(self, data): pass def AddDataList(self, data, dataType, containsFillForwardData): pass for symbol in self.ActiveSecurities.Keys: if symbol.SecurityType == SecurityType.Option and not self.IsSymbolInSpreads(symbol): security = self.Securities[symbol] security.Cache = EmptySecurityCache() # Cache _lastData needs to be null in order for OptionChainUniverse to allow removing the data
I'm pretty sure this works as I tracked the number of subscriptions in SubscriptionManager with/without this. But it has been some time and I stopped researching this algo so something may be wrong. Also this is exploiting implementation details not public API so I'm sure it could change behavior any time. But it is a benefit of the platform code being open source :D I also don't believe it causes other side effects but don't know for sure.
Cole S
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!