Overall Statistics |
Total Orders 21 Average Win 1.44% Average Loss 0% Compounding Annual Return 20.529% Drawdown 3.400% Expectancy 0 Start Equity 1000000 End Equity 1205697.18 Net Profit 20.570% Sharpe Ratio 3.343 Sortino Ratio 2.115 Probabilistic Sharpe Ratio 97.494% Loss Rate 0% Win Rate 100% Profit-Loss Ratio 0 Alpha 0.078 Beta 0.208 Annual Standard Deviation 0.04 Annual Variance 0.002 Information Ratio -1.176 Tracking Error 0.115 Treynor Ratio 0.642 Total Fees $271.05 Estimated Strategy Capacity $510000.00 Lowest Capacity Asset SPY 31NL3I227KPVQ|SPY R735QTJ8XC9X Portfolio Turnover 0.04% |
# region imports from AlgorithmImports import * # endregion class WheelStrategyAlgorithm(QCAlgorithm): def initialize(self): self.set_start_date(2020, 6, 1) self.set_end_date(2021, 6, 1) self.set_cash(1_000_000) self.set_security_initializer(BrokerageModelSecurityInitializer(self.brokerage_model, FuncSecuritySeeder(self.get_last_known_prices))) self._equity = self.add_equity("SPY", data_normalization_mode=DataNormalizationMode.Raw) self._otm_threshold = 0.05 # 5% daily_interest_rate = (1.04) ** (1 / 365) - 1 # 4% annual interest rate. self.schedule.on(self.date_rules.every_day(), self.time_rules.midnight, lambda: self.portfolio.cash_book["USD"].add_amount(self.portfolio.cash_book["USD"].amount * daily_interest_rate)) def _get_target_contract(self, right, target_price): contract_symbols = self.option_chain_provider.get_option_contract_list(self._equity.symbol, self.time) expiry = min([s.id.date for s in contract_symbols if s.id.date.date() > self.time.date() + timedelta(30)]) filtered_symbols = [ s for s in contract_symbols if (s.id.date == expiry and s.id.option_right == right and (s.id.strike_price <= target_price if right == OptionRight.PUT else s.id.strike_price >= target_price)) ] symbol = sorted(filtered_symbols, key=lambda s: s.id.strike_price, reverse=right == OptionRight.PUT)[0] self.add_option_contract(symbol) return symbol def on_data(self, data): if not self.portfolio.invested and self.is_market_open(self._equity.symbol): symbol = self._get_target_contract(OptionRight.PUT, self._equity.price * (1-self._otm_threshold)) self.set_holdings(symbol, -0.2) elif [self._equity.symbol] == [symbol for symbol, holding in self.portfolio.items() if holding.invested]: symbol = self._get_target_contract(OptionRight.CALL, self._equity.price * (1+self._otm_threshold)) self.market_order(symbol, -self._equity.holdings.quantity / 100)