Overall Statistics Total Trades9Average Win64.79%Average Loss-38.59%Compounding Annual Return351.420%Drawdown58.800%Expectancy0.339Net Profit132.792%Sharpe Ratio9.307Probabilistic Sharpe Ratio69.794%Loss Rate50%Win Rate50%Profit-Loss Ratio1.68Alpha16.985Beta-3.459Annual Standard Deviation1.78Annual Variance3.167Information Ratio7.658Tracking Error2.147Treynor Ratio-4.789Total Fees\$15.75
from datetime import timedelta
from itertools import combinations
import pandas as pd

def Initialize(self):
self.SetStartDate(2020, 1, 1)
self.SetCash(10000)

self.symbol = option.Symbol

option.SetFilter(-5, 5, timedelta(1), timedelta(90))

self.SetBenchmark(self.spy)

def OnData(self, data):
if self.Portfolio.Invested or \
not data.OptionChains.ContainsKey(self.symbol) or \
not data.ContainsKey(self.spy):
return

for symbol, chain in data.OptionChains.items():
contracts = [contract for contract in chain]

if len(contracts) == 0:
return

underlying_price = data[self.spy].Close

# Get all put contracts
all_puts = [contract for contract in contracts if contract.Right == OptionRight.Put]

# Get all unique expiries
expires = set([contract.Expiry for contract in all_puts])

rankings_df = pd.DataFrame()
for expiry in expires:
puts = [contract for contract in all_puts if contract.Expiry == expiry]
if len(puts) == 0:
continue

for option_combinations in combinations(puts, 2):
sell_put = option_combinations[1]

# We ignore the contract multiplier here
max_loss = net_cost
max_profit = strike_width - net_cost

# Calculate factors
inverted_profit_loss_ratio = max_loss / max_profit if max_profit != 0 else float('inf')
break_even_distance = underlying_price - buy_put.Strike + net_cost
days_to_expiry = (expiry - self.Time).days

# Save factor results
row = pd.DataFrame({'inverted_profit_loss_ratio' : [inverted_profit_loss_ratio],
'break_even_distance' : [break_even_distance],
'days_to_expiry' : [days_to_expiry]},
index=[option_combinations])
rankings_df = rankings_df.append(row)

if not rankings_df.empty:
# Rank put contracts by factors
selected_contracts = rankings_df.rank().sum(axis=1).idxmin()

self.Sell(sell_symbol, quantity)