| Overall Statistics |
|
Total Orders 272 Average Win 0.08% Average Loss -0.07% Compounding Annual Return -16.193% Drawdown 5.800% Expectancy -0.483 Start Equity 1000000 End Equity 952000 Net Profit -4.800% Sharpe Ratio -5.839 Sortino Ratio -6.585 Probabilistic Sharpe Ratio 0.151% Loss Rate 74% Win Rate 26% Profit-Loss Ratio 1.01 Alpha -0.181 Beta -0.05 Annual Standard Deviation 0.029 Annual Variance 0.001 Information Ratio 0.321 Tracking Error 0.133 Treynor Ratio 3.429 Total Fees $0.00 Estimated Strategy Capacity $43000.00 Lowest Capacity Asset SPXW 32P827391JGBY|SPX 31 Portfolio Turnover 2.75% |
# region imports
from AlgorithmImports import *
# endregion
class OneDTEIndexOptionUniverseAlgorithm(QCAlgorithm):
def initialize(self):
self.set_start_date(2024, 12, 1)
self.set_cash(1_000_000)
self.set_security_initializer(BrokerageModelSecurityInitializer(self.brokerage_model, FuncSecuritySeeder(self.get_last_known_prices)))
self._spy = self.add_equity('SPY')
self._spy.roc = self.roc(self._spy.symbol, 1, Resolution.DAILY)
self._index = self.add_index('SPX')
self._index.canonical = Symbol.create_canonical_option(self._index.symbol, "SPXW", Market.USA, "?SPXW")
# Create a member to track when the algorithm should trade.
date_rule = self.date_rules.every_day(self._index.symbol)
self.schedule.on(date_rule, self.time_rules.before_market_close(self._index.symbol, 14), self._trade)
self.schedule.on(date_rule, self.time_rules.before_market_close(self._index.symbol, 1), self.liquidate)
self.add_risk_management(TrailingStopRiskManagementModel(0.05))
def _trade(self):
self.log(f"{self.time} - Trade")
close = self._index.price
# Get the 1DTE Options.
chain = self.option_chain(self._index.canonical, flatten=True).data_frame
expiry = chain[chain.expiry > self.time].expiry.min()
chain = chain[chain.expiry == expiry]
# Select ATM contracts.
strike_below = chain[chain.strike <= close].strike.max()
strike_above = chain[chain.strike >= close].strike.min()
contracts_below = list(chain[chain.strike == strike_below].index)
contracts_above = list(chain[chain.strike == strike_above].index)
# Add the contracts.
for symbol in contracts_below + contracts_above:
self.add_option_contract(symbol)
# Select call/put.
if contracts_above[0].id.option_right == OptionRight.CALL:
call = contracts_above[0]
put = contracts_above[1]
else:
call = contracts_above[1]
put = contracts_above[0]
# Place entry trades.
self.plot('ROC', 'Value', self._spy.roc.current.value)
if self._spy.roc.current.value > 0: # Price drifts upward => Sell call, Buy put
self.buy(call, 5)
self.sell(put, 5)
else: # Price drifts downward => Sell put, Buy call
self.buy(put, 5)
self.sell(call, 5)