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)