Overall Statistics
Total Trades
1
Average Win
0%
Average Loss
0%
Compounding Annual Return
109.635%
Drawdown
0.300%
Expectancy
0
Net Profit
0.203%
Sharpe Ratio
11.225
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0.023
Annual Variance
0.001
Information Ratio
0
Tracking Error
0
Treynor Ratio
0
Total Fees
$2.00
from datetime import datetime,timedelta
import pandas as pd
import numpy as np
import sys     

class  MomentumAlgorithm(QCAlgorithm):
    
    def Initialize(self):
        self.VERBOSEMODE = True
        self.VERBOSEMODE2 = False          
        self.SetStartDate(2019,5,10)
        self.SetEndDate(2019,5,12)
        self.SetCash(100000)
        self.benchmark = "SPY" 
        self.SetRiskManagement(TrailingStopRiskManagementModel(0.0172))
        self.symbols = ["SPY","TLT","GLD"]
        self.lastSymbol = None
        self.contract = None

        self.spy = self.AddEquity("SPY",Resolution.Minute)
        self.spy.SetDataNormalizationMode(DataNormalizationMode.Raw)  
        self.spy.SetDataNormalizationMode(DataNormalizationMode.Raw)  
        self.tlt = self.AddEquity("TLT",Resolution.Minute)
        self.protectedPositions = {'SPY': False  , 'TLT': False , 'GLD': False}
        self.myOptions={}
        self.pauseOneMinute = True
        
        for symbol in self.Securities.Keys:
            self.Securities[symbol].FeeModel = ConstantFeeModel(2.00)
            self.Securities[symbol].SetDataNormalizationMode(DataNormalizationMode.Raw)  
            self.myOptions[symbol] = self.AddOption(symbol.Value,Resolution.Minute)
            #limit options strikes to 10 strikes away  with 6 day minimum
            self.myOptions[symbol].SetFilter(-10, +10, timedelta(0), timedelta(30))

    def OnData(self, slice):
      try:
            #if self.VERBOSEMODE2:self.Log("Time: {}" . format(slice.Time) )
            if slice is None:
                if self.VERBOSEMODE2:self.Log("no slice " )
                return    
            optionchain = slice.OptionChains            
            for element  in slice:
                symbol = element.Key
                symbolStr = symbol.Value
                #make sure only act on invested symbol
                if self.pauseOneMinute:
                    if symbolStr in  self.protectedPositions and  self.protectedPositions[symbolStr] == False:  
                            self.MarketOrder(symbol,100)
                            self.PrepCall(symbol)
                            self.pauseOneMinute = False
                else:
                   if len(symbol.ToString()) > 3 : #workaround for ensuging not already an option
                        #self.MarketOrder(self.contract, 1,asynchronous = False)
                        self.SetHoldings(self.conrtract, 0.1)
                        self.pauseOneMinute = True

      except:
            if self.VERBOSEMODE:self.Log('An unknown error occurred trying OnData' +  str(sys.exc_info()[0]) )
                                    
    def calcNumberOptionsContractsNeeded(self,symbol):

        symbolStr = symbol.Value
        current = float(self.Securities[symbolStr].Price)
        quantity = float(self.Portfolio[symbolStr].Quantity)  
        optionContractCount = round(current * quantity / 100)
        if self.VERBOSEMODE: self.Log("contract count for symbol {} current {} quantity {} is {} " . format(symbolStr,current, quantity, optionContractCount))
        return optionContractCount
                    
    def PrepCall(self,symbol):
        if len(symbol.ToString()) > 3 : #workaround for ensuging not already an option
            return
        symbolStr = symbol.Value
        contracts = self.OptionChainProvider.GetOptionContractList(symbol, self.Time.date()) # must be of type Symbol
        if len(contracts) == 0: return
        min_expiry = 0
        max_expiry = 14
        
        filtered_contracts = [i for i in contracts if min_expiry <= (i.ID.Date.date() - self.Time.date()).days <= max_expiry]
        call = [x for x in filtered_contracts if x.ID.OptionRight == 0] 
        
        if len(call) == 0: return
        # sorted the contracts according to their expiration dates and choose the ATM options
        self.contract = sorted(sorted(call, key = lambda x: abs(self.Securities[symbolStr].Price - x.ID.StrikePrice)), 
                                        key = lambda x: x.ID.Date, reverse=True)[0]
      
        self.AddOptionContract(self.contract, Resolution.Minute)
        optionContractCount = self.calcNumberOptionsContractsNeeded(symbol)
        if optionContractCount == 0:
            return
        optionContractCount = 1
        #option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and  x.Value.Type==SecurityType.Option]
        orderId =  self.MarketOrder(self.contract, optionContractCount,asynchronous = False)
        self.protectedPositions[symbolStr] = True

            
        if self.VERBOSEMODE: self.Log(  "bought 1 call contract of {} {} " . format(symbolStr,self.contract ))