Overall Statistics Total Trades 3 Average Win 0% Average Loss 0% Compounding Annual Return -4.276% Drawdown 16.000% Expectancy 0 Net Profit -15.744% Sharpe Ratio -1.046 Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha -0.044 Beta 0.226 Annual Standard Deviation 0.038 Annual Variance 0.001 Information Ratio -1.533 Tracking Error 0.038 Treynor Ratio -0.177 Total Fees \$3.00
```import numpy as np
import decimal as d
from datetime import timedelta
import datetime
#import 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.'''

'''Initialie the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''

self.SetStartDate(2014, 1, 1)  #Set Start Date
self.SetEndDate(2017,12,1)    #Set End Date
self.SetCash(1000000)           #Set Strategy Cash
# Find more symbols here: http://quantconnect.com/data
self.osymbol = "XOM"
self.stock = equity.Symbol
self.symbol = option.Symbol
# set our strike/expiry filter for this option chain
option.SetFilter(-5, 5, timedelta(20), timedelta(35))
#direcitonal indicators
self._macdHistogram = RollingWindow[float](12)
# Creates a Rolling Window indicator to keep the 2 TradeBar
self._bbupwindow = RollingWindow[d.Decimal](12)    # For other security types, use QuoteBar
self._bbmidwindow = RollingWindow[d.Decimal](12)    # For other security types, use QuoteBar
self._bblowindow = RollingWindow[d.Decimal](12)    # For other security types, use QuoteBar

self._keltnerupwindow = RollingWindow[d.Decimal](12)    # For other security types, use QuoteBar
self._keltnermidwindow = RollingWindow[d.Decimal](12)    # For other security types, use QuoteBar
self._keltnerlowindow = RollingWindow[d.Decimal](12)    # For other security types, use QuoteBar
self._mom = RollingWindow[float](12)

self._macd = self.MACD(self.osymbol, 12, 26, 9, MovingAverageType.Exponential, Resolution.Daily)
self._bb = self.BB(self.osymbol, 20, 2,  MovingAverageType.Simple, Resolution.Daily)
self._keltner = self.KCH(self.osymbol, 20, d.Decimal(1.5), MovingAverageType.Simple, Resolution.Daily)  #its working NOW !!!
self._mom1 = self.MOM(self.osymbol, 20, Resolution.Daily)
def bullSqueeze(self, data):
a = True
for num in range(0,5):
if self._bbupwindow[num] < self._keltnerupwindow[num] and self._bblowindow[num] > self._keltnerlowindow[num]:
a = True
else:
return False
if a == True:
if self._mom[4] < self._mom[0] and self._macdHistogram[3] < self._macdHistogram[0]:
return True
def bearishSqueeze(self,data):
a = True
for num in range(0,5):
if self._bbupwindow[num] < self._keltnerupwindow[num] and self._bblowindow[num] > self._keltnerlowindow[num]:
a = True
else:
return False
if a == True:
if self._mom[4] > self._mom[0] and self._macdHistogram[3] > self._macdHistogram[0]:
return True
if self._mom[2] > self._mom[0] or self._macdHistogram[2] > self._macdHistogram[0]:
return True
if self._mom[2] < self._mom[0] or self._macdHistogram[2] < self._macdHistogram[0]:
return True
def OnData(self, slice):
#'''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.'''
#if not self.Portfolio.Invested:

if not self.Portfolio.Invested:
if self.bullSqueeze(slice) == True:
self.Log("Bullish squeeze")
optionchain = slice.OptionChains
for i in slice.OptionChains:
if i.Key != self.symbol: continue
chains = i.Value
contract_list = [x for x in chains]
# if there is no contracts in this optionchain, pass the instance
if (slice.OptionChains.Count == 0) or (len(contract_list) == 0):
return
elif self.bearishSqueeze(slice) == True:
self.Log("Bearish squeeze")
optionchain = slice.OptionChains
for i in slice.OptionChains:
if i.Key != self.symbol: continue
chains = i.Value
contract_list = [x for x in chains]
# if there is no contracts in this optionchain, pass the instance
if (slice.OptionChains.Count == 0) or (len(contract_list) == 0):
return
# if there is no securities in portfolio, trade the options
else:
option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.Option]
for a in option_invested:
if self.Securities[a].Invested:
#self.Transactions.CancelOpenOrders(a)
open_orders = self.Transactions.GetOpenOrders(a)
if len(open_orders) == 0:
if a.ID.OptionRight == OptionRight.Call:
if self.Time.date() == (self.Securities[a].Expiry.date()+timedelta(1)):
self.LimitOrder(a, -(self.quantityC), self.Securities[a].BidPrice)
#self.Transactions.CancelOpenOrders(a)
self.LimitOrder(a, -(self.quantityC), self.Securities[a].BidPrice)
#self.Transactions.CancelOpenOrders(a)
elif a.ID.OptionRight == OptionRight.Put:
if self.Time.date() == (self.Securities[a].Expiry.date()+timedelta(1)):
self.LimitOrder(a, -(self.quantityP), self.Securities[a].BidPrice)
# self.Transactions.CancelOpenOrders(a)
self.LimitOrder(a, -(self.quantityP), self.Securities[a].BidPrice)
#self.Transactions.CancelOpenOrders(a)
#if self.Portfolio.Invested:

def OnOrderEvent(self, orderEvent):
self.Log("order event")
self.Log(str(orderEvent))

for i in optionchain:
if i.Key != self.symbol: continue
chain = i.Value
# sorted the optionchain by expiration date and choose the furthest date
expiry = sorted(chain,key = lambda x: x.Expiry, reverse=True)[0].Expiry
# filter the call options from the contracts expires on that date
call = [i for i in chain if i.Expiry == expiry and i.Right == 0]
# sorted the contracts according to their strike prices
call_contracts = sorted(call,key = lambda x: x.Strike)
if len(call_contracts) == 0: continue
self.call = call_contracts[0]
self.quantityC = self.CalculateOrderQuantity(self.call.Symbol, .05)

for i in optionchain: