Overall Statistics Total Orders4Average Win0.77%Average Loss0%Compounding Annual Return-52.972%Drawdown7.500%Expectancy-0.5Start Equity100000End Equity94442Net Profit-5.558%Sharpe Ratio-3.576Sortino Ratio-2.468Probabilistic Sharpe Ratio0.053%Loss Rate50%Win Rate50%Profit-Loss Ratio0Alpha-0.391Beta-0.397Annual Standard Deviation0.119Annual Variance0.014Information Ratio-3.491Tracking Error0.146Treynor Ratio1.071Total Fees$2.00Estimated Strategy Capacity$250000.00Lowest Capacity AssetGOOCV WJVVXYW5VKH2|GOOCV VP83T1ZUHROLPortfolio Turnover3.02%
# region imports
from AlgorithmImports import *
# endregion

class ShortStrangleAlgorithm(QCAlgorithm):

def initialize(self) -> None:
self.set_start_date(2017, 4, 1)
self.set_end_date(2017, 4, 30)
self.set_cash(100000)

self.symbol = option.symbol
option.set_filter(-5, 5, 0, 30)

def on_data(self, slice: Slice) -> None:
if self.portfolio.invested:
return

# Get the OptionChain
chain = slice.option_chains.get(self.symbol)
if not chain:
return

# Find options with the nearest expiry
expiry = max([x.expiry for x in chain])
contracts = [contract for contract in chain if contract.expiry == expiry]

# Order the OTM calls by strike to find the nearest to ATM
call_contracts = sorted([contract for contract in contracts
if contract.right == OptionRight.CALL and
contract.strike > chain.underlying.price],
key=lambda x: x.strike)
if not call_contracts:
return

# Order the OTM puts by strike to find the nearest to ATM
put_contracts = sorted([contract for contract in contracts
if contract.right == OptionRight.PUT and
contract.strike < chain.underlying.price],
key=lambda x: x.strike, reverse=True)
if not put_contracts:
return

call_strike = call_contracts[0].strike
put_strike = put_contracts[0].strike

short_strangle = OptionStrategies.short_strangle(self.symbol, call_strike, put_strike, expiry)
self.buy(short_strangle, 1)