Overall Statistics
Total Orders
367
Average Win
0.21%
Average Loss
-0.19%
Compounding Annual Return
0.272%
Drawdown
1.500%
Expectancy
0.430
Start Equity
500000
End Equity
506837
Net Profit
1.367%
Sharpe Ratio
-4.086
Sortino Ratio
-5.392
Probabilistic Sharpe Ratio
1.752%
Loss Rate
32%
Win Rate
68%
Profit-Loss Ratio
1.09
Alpha
-0.034
Beta
0.001
Annual Standard Deviation
0.008
Annual Variance
0
Information Ratio
-0.752
Tracking Error
0.142
Treynor Ratio
-39.246
Total Fees
$211.00
Estimated Strategy Capacity
$1000.00
Lowest Capacity Asset
SPY 32X5I9TKKAAIU|SPY R735QTJ8XC9X
Portfolio Turnover
0.56%
Drawdown Recovery
797
#region imports
from AlgorithmImports import *
#endregion
# https://quantpedia.com/Screener/Details/20


class VolatilityRiskPremiumStrategy(QCAlgorithm): 

    def initialize(self):
        self.set_start_date(self.end_date - timedelta(5*365))
        self.set_cash(500_000)
        self.settings.seed_initial_prices = True
        self._underlying = self.add_equity('SPY', data_normalization_mode=DataNormalizationMode.RAW)

    def on_data(self, slice: Slice) -> None:
        # When assigned, liquidate the underlying position.
        if self._underlying.invested:
            self.liquidate(self._underlying)
            return
        # When we're still holding Option contracts, do nothing.
        if self.portfolio.invested: 
            return

        # Get the OptionChain.
        chain = self.option_chain(self._underlying.symbol)
        
        # Get the nearest expiration date that's at least 30 days away.
        min_expiry = self.time + timedelta(30)
        expiry = min([c.expiry for c in chain if c.expiry >= min_expiry and c.right == OptionRight.PUT])
        
        # Select the put Option contracts at that expiry.
        puts = [c for c in chain if c.expiry == expiry and c.right == OptionRight.PUT]
        if not puts: 
            return

        # Select 15% OTM put.
        otm_put = sorted(puts, key=lambda p: abs(p.strike - 0.85*self._underlying.price))[0]
        self.add_option_contract(otm_put.symbol)

        # Select the ATM strike price from the remaining contracts.
        atm_strikes = sorted([p.strike for p in puts], key=lambda x: abs(x - self._underlying.price))[0]        
        for contract in chain:
            if contract.strike == atm_strikes and contract.expiry == expiry:
                self.add_option_contract(contract.symbol)

        # Place orders.
        self.buy(OptionStrategies.straddle(otm_put.symbol.canonical, atm_strikes, expiry), 1)
        self.sell(otm_put.symbol, 1)