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
-29.365
Tracking Error
0.052
Treynor Ratio
0
Total Fees
$0.00
from datetime import *
import math

import QuantConnect
from QuantConnect.Securities import *
from QuantConnect.Algorithm.Selection import *


class ResistanceUncoupledAutosequencers(QCAlgorithm):

    symbolsToConsider = 20
    
    optionChainRcvd = {}

    def Initialize(self):
        self.SetStartDate(2018, 1, 1)
        self.SetEndDate(2018, 1, 13)
        self.SetCash(100000)
        
        self.UniverseSettings.Resolution = Resolution.Minute
        self.UniverseSettings.FillForward = True
        self.UniverseSettings.Leverage = 10/3
        self.UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw
        self.UniverseSettings.MinimumTimeInUniverse = timedelta(minutes=1)
        
        coarseUniverse = self.AddUniverse(self.CoarseFilter)
        self.AddUniverseOptions(coarseUniverse, self.OptionFilter)

    def OptionFilter(self, optionFilterUniverse):
        return optionFilterUniverse.IncludeWeeklys().Expiration(0, 1)

    def CoarseFilter(self, coarse):
        # Need to do universe selection on Thursday in order to get the ticks for open interest on Friday at midnight.
        # So on Friday, we return Universe.Unchanged, on Thursday we do the selection, and we return an empty list
        # on all other days.
        if self.Time.weekday() == 4:
            return Universe.Unchanged
        if self.Time.weekday() != 3:
            return []

        self.optionChainRcvd = {}
        
        friday = self.Time.date() + timedelta(days = (4-self.Time.weekday()) % 7) # https://stackoverflow.com/questions/8801084/how-to-calculate-next-friday
        equities = [c for c in coarse if c.Symbol.SecurityType == SecurityType.Equity and c.HasFundamentalData and c.Price > 10]
        sortedByVolume = sorted(equities, reverse=True, key=lambda x: x.Volume)
        hasOptionsExpiringFriday = []
        for c in sortedByVolume[:20]:
            optionSymbols = self.OptionChainProvider.GetOptionContractList(c.Symbol, self.Time)
            optionsExpiringFriday = [os for os in optionSymbols if os.ID.Date.date() == friday]
            
            if len(optionsExpiringFriday) > 0:
                securityExchangeHours = self.MarketHoursDatabase.GetExchangeHours(c.Market, c.Symbol, c.Symbol.SecurityType)
                previousMarketOpen = securityExchangeHours.GetNextMarketOpen(securityExchangeHours.GetPreviousTradingDay(self.Time), False)
                # Have to start at midnight in order for openinterest data to arrive
                df = self.History(optionsExpiringFriday, previousMarketOpen.date(), previousMarketOpen+timedelta(minutes=1), Resolution.Minute)
                if "openinterest" in df:
                    totalOpenInterest = df["openinterest"].sum()
                    hasOptionsExpiringFriday.append((c.Symbol, totalOpenInterest, c.Volume, optionsExpiringFriday))

        sortedByRatio = sorted(hasOptionsExpiringFriday, reverse=True, key=lambda x: x[1]/x[2])
        self.Debug(f"sorted by ratio: {[(str(a), b, c) for (a,b,c,d) in sortedByRatio[:self.symbolsToConsider]]}")
        
        return [x[0] for x in sortedByRatio[:self.symbolsToConsider]]

    def OnData(self, slice):
        # Only care about Fridays (when options expire)
        if self.Time.weekday() != 4:
            return

        for symbol in slice.OptionChains.Keys:
            if symbol not in self.optionChainRcvd:
                self.optionChainRcvd[symbol] = self.Time
            
        if self.Time.hour == 15 and self.Time.minute == 59:
            for symbol in self.ActiveSecurities.Keys:
                if symbol.SecurityType == SecurityType.Equity:
                    gotOptionChainAt = None
                    for optionSymbol, time in self.optionChainRcvd.items():
                        if optionSymbol.HasUnderlyingSymbol(symbol):
                            gotOptionChainAt = time
                    self.Debug(f"{symbol} gotOptionChainAt={gotOptionChainAt}")