| Overall Statistics |
|
Total Trades 4 Average Win 0% Average Loss 0% Compounding Annual Return -0.501% Drawdown 0.100% Expectancy 0 Net Profit -0.057% Sharpe Ratio -3.634 Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha -0.004 Beta -0.005 Annual Standard Deviation 0.001 Annual Variance 0 Information Ratio -1.418 Tracking Error 0.057 Treynor Ratio 0.936 Total Fees $1.00 |
from datetime import timedelta
# Implementation of Iron Condor https://www.tastytrade.com/tt/shows/market-measures/episodes/backtesting-iron-condors-in-spx-06-29-2016
class BasicTemplateOptionsAlgorithm(QCAlgorithm):
contracts = 1
shortDelta = .3
longDelta = .05
def Initialize(self):
self.SetStartDate(2017, 01, 01)
self.SetEndDate(2017, 02, 01)
self.SetCash(100000)
self.symbol = "SPY"
equity = self.AddEquity(self.symbol, Resolution.Minute)
option = self.AddOption(self.symbol, Resolution.Minute)
option.SetFilter(-20, 20, timedelta(30), timedelta(60))
# use the underlying equity as the benchmark
self.SetBenchmark(equity.Symbol)
self.SetWarmUp(timedelta(10))
def OnData(self, slice):
if(self.IsWarmingUp):
return
self.TradeOptions(slice)
def TradeOptions(self, slice):
if not self.Portfolio.Invested and self.Time.hour != 0 and self.Time.minute != 0:
shortCall = None
longCall = None
shortPut = None
longPut = None
for i in slice.OptionChains:
chain = i.Value
contract_list = [x for x in chain]
# if there is no optionchain or no contracts in this optionchain, pass the instance
if (slice.OptionChains.Count == 0) or (len(contract_list) == 0):
return
# sorted optionchain by expiration date and choose the furthest date
expiry = sorted(chain, key = lambda x: x.Expiry)[-1].Expiry
# filter call and put options from the contracts
call = [i for i in chain if i.Right == 0 and i.Expiry == expiry]
put = [i for i in chain if i.Right == 1 and i.Expiry == expiry]
# sort calls by strike prices in ascending order
call_contracts = sorted(call, key = lambda x: x.Strike)
# sort puts by strike prices in descending order
put_contracts = sorted(put, key = lambda x: x.Strike, reverse=True)
if len(call_contracts) == 0 or len(put_contracts) == 0 :
continue
# loop from low strike to high
for call in call_contracts:
self.Log("call=" + str(call.Greeks.Delta))
if((shortCall is None) and (call.Greeks.Delta <= self.shortDelta)):
shortCall = call
elif((longCall is None) and (call.Greeks.Delta <= self.longDelta)):
longCall = call
break # stop for loop
# loop from high strike to low
for put in put_contracts:
self.Log("put=" + str(put.Greeks.Delta))
if((shortPut is None) and (put.Greeks.Delta >= -self.shortDelta)):
shortPut = put
elif((longPut is None) and (put.Greeks.Delta >= -self.longDelta)):
longPut = put
break # stop for loop
if((longCall is not None) and (shortCall is not None) and (longPut is not None) and (shortPut is not None)):
break
if((longCall is None) or (shortCall is None) or (longPut is None) or (shortPut is None)):
return
self.Log(str(longCall.Greeks.Delta))
self.Log(str(shortCall.Greeks.Delta))
self.Log(str(shortPut.Greeks.Delta))
self.Log(str(longPut.Greeks.Delta))
# trade the options
self.Buy(longCall.Symbol, self.contracts)
self.Sell(shortCall.Symbol, self.contracts)
self.Sell(shortPut.Symbol, self.contracts)
self.Buy(longPut.Symbol, self.contracts)