Overall Statistics
import numpy as np
from pprint import pprint
import pandas as pd
from datetime import timedelta, date, datetime

### <summary>
### Basic template algorithm simply initializes the date range and cash. This is a skeleton
### framework you can use for designing an algorithm.
### </summary>
class BasicTemplateAlgorithm(QCAlgorithm):
    '''Basic template algorithm simply initializes the date range and cash'''

    def Initialize(self):
        '''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''

        self.SetStartDate(2016,10,1)  #Set Start Date
        self.SetEndDate(2016,11,8)    #Set End Date
        self.SetCash(25000)           #Set Strategy Cash
        # Find more symbols here: http://quantconnect.com/data
        self.AddUniverse(self.CoarseSelectionFunction)
        self.should_trade = True

        # option.SetFilter(-2, 2, TimeSpan.FromDays(30), TimeSpan.FromDays(180));
        self.AddEquity("SPY")
        self.Schedule.On(self.DateRules.Every([DayOfWeek.Thursday]), self.TimeRules.BeforeMarketClose("SPY", 45), Action(self.Activate))
    
    def CoarseSelectionFunction(self, coarse):
        '''Take the top 5 by dollar volume using coarse'''
        # sort descending by daily dollar volume
        sortedByDollarVolume = sorted(coarse, \
            key=lambda x: x.DollarVolume, reverse=True) 
    
        # we need to return only the symbol objects
        return [ x.Symbol for x in sortedByDollarVolume[:5] ]
    
    def OnSecuritiesChanged (self, changes):
        for x in changes.AddedSecurities:
            if x.Symbol.SecurityType != SecurityType.Equity: continue
            option = self.AddOption(x.Symbol.Value, Resolution.Minute)
            option.SetFilter(-1, +1, timedelta(6), timedelta(15))
    
        for x in changes.RemovedSecurities:
            self.RemoveSecurity(x.Symbol)
            for symbol in self.Securities.Keys:
                if symbol.SecurityType == SecurityType.Option and symbol.Underlying == x.Symbol:
                    self.RemoveSecurity(symbol)
        
    def GetOptionTrades(self, data):
        '''figure out which trades to make, and trade size as well'''
        trades_to_make = []
        return trades_to_make
        
    def Activate(self):
        '''Make Options Trades'''
        self.should_trade = True

    def OnData(self,slice):
        if self.should_trade == False:
            return
        for security in self.ActiveSecurities.Keys:
            self.Log(f'Security in Universe: {security.Value}')
        self.Log("Doing it")
        
        # spyTickList = slice["SPY"]
        # self.Log(str(spyTickList))
        
        k = 0
        for i in slice.OptionChains:
            k += 1
            self.Log(str(k))
            optionchain = i.Value 
            # print out the undelying price
            self.Log("underlying price:" + str(optionchain.Underlying.Price))
            
            # create a data frame to show the filtered contracts
            # type(call 0, put 1)
            df = pd.DataFrame([[x.Right,float(x.Strike),x.Expiry,float(x.BidPrice), float(x.AskPrice)] for x in optionchain],
                              index=[x.Symbol.Value for x in optionchain],
                              columns=['type', 'strike', 'expiry', 'ask price', 'bid price'])
            
            #day lag
            date_format = "%Y-%m-%d"
            # day_lag = ( df.sort('expiry', ascending=True).iloc[0]['expiry'] - date.today() ).days
            
            #get history
            # hist = self.History( ["SPY"], 10, Resolution.Daily )
            # self.Log(str(hist.loc[ "SPY" ].close))
            
            #get interesting contracts
            contracts = df.loc[ df['strike'] > optionchain.Underlying.Price ].iloc[:2]
            
            # self.Log(str(contracts))

            # we sort the contracts to find at the money (ATM) contract with farthest expiration
            contracts = sorted(sorted(optionchain, key = lambda x: abs(optionchain.Underlying.Price - x.Strike)),key = lambda x: x.Expiry, reverse=True)
            # buy the option with farthest expiration and sell it when the exchange closes
            if len(contracts) == 0: continue
            symbol = contracts[0].Symbol   
            #self.MarketOrder(symbol, 1)
            #self.MarketOnCloseOrder(symbol, -1)
            
        self.should_trade = False