Overall Statistics |
Total Orders 430 Average Win 2.67% Average Loss -1.55% Compounding Annual Return -28.829% Drawdown 32.200% Expectancy -0.216 Start Equity 100000 End Equity 75828.95 Net Profit -24.171% Sharpe Ratio -1.165 Sortino Ratio -1.25 Probabilistic Sharpe Ratio 1.729% Loss Rate 71% Win Rate 29% Profit-Loss Ratio 1.72 Alpha -0.185 Beta -0.437 Annual Standard Deviation 0.212 Annual Variance 0.045 Information Ratio -1.526 Tracking Error 0.255 Treynor Ratio 0.565 Total Fees $587.05 Estimated Strategy Capacity $1000.00 Lowest Capacity Asset V 32LNYIJSPF3BA|V U12VRGLO8PR9 Portfolio Turnover 1.27% |
#region imports from AlgorithmImports import * #endregion LOOKBACK = 20 RES = Resolution.HOUR class YouTubeSeries(QCAlgorithm): def initialize(self): self.set_start_date(2024, 1, 1) self.set_cash(100000) self.universe_settings.asynchronous = True self.universe_settings.data_normalization_mode = DataNormalizationMode.RAW self.universe_settings.resolution = RES universe = self.add_universe(self._select_coarse) self.add_universe_options(universe, self._option_filter_function) self.Indics = {} self.dte = 15 self.uni_size = 10 self.AddRiskManagement(MaximumUnrealizedProfitPercentPerSecurity(1.00)) self.AddRiskManagement(MaximumDrawdownPercentPerSecurity(0.50)) def _select_coarse(self, coarse: List[CoarseFundamental]) -> List[Symbol]: selected = [c for c in coarse if c.has_fundamental_data] sorted_by_dollar_volume = sorted(selected, key=lambda c: c.dollar_volume, reverse=True) symbols = [c.symbol for c in sorted_by_dollar_volume[:self.uni_size]] return symbols def _option_filter_function(self, universe: OptionFilterUniverse) -> OptionFilterUniverse: return universe.IncludeWeeklys().Strikes(5, 5).Expiration(timedelta(self.dte), timedelta(self.dte)) def on_data(self, data: Slice): option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.OPTION] if option_invested: if self.Time + timedelta(5) > option_invested[0].ID.Date: self.Liquidate(option_invested[0], "Too close to expiration") equity_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.EQUITY] if equity_invested: self.Liquidate(equity_invested[0], tag="Equity in here") for _, chain in data.option_chains.items(): symbol = chain.underlying.symbol spot = chain.underlying.price exp = sorted(chain, key = lambda x: x.Expiry, reverse=False) if len(exp) == 0: continue expiry = exp[0].Expiry calls = [i for i in chain if i.Expiry == expiry and i.Right == OptionRight.CALL] call_contracts = sorted(calls, key = lambda x: abs(x.Strike - spot)) if len(call_contracts) == 0: continue call_con = call_contracts[0] if call_con.ask_price > 10.00: continue puts = [i for i in chain if i.Expiry == expiry and i.Right == OptionRight.PUT] put_contracts = sorted(puts, key = lambda x: abs(x.Strike - spot)) if len(put_contracts) == 0: continue put_con = put_contracts[0] if put_con.ask_price > 10.00: continue if not (data.contains_key(symbol) and data[symbol] is not None): continue if not symbol in self.Indics: continue bar = data.bars.get(symbol) if bar: self.Indics[symbol].st.update(bar) self.Indics[symbol].stch.update(bar) if not self.Indics[symbol].st.is_ready or not self.Indics[symbol].stch.is_ready: continue if not self.portfolio[call_con.symbol].Invested or not self.portfolio[put_con.symbol].Invested: c = self.securities[symbol].close st = self.Indics[symbol].st.current.value stch = self.Indics[symbol].stch.current.value if stch > 70 and st < c: self.market_order(call_con.symbol, 1) elif stch < 30 and st > c: self.market_order(put_con.symbol, 1) def on_securities_changed(self, changes: SecurityChanges) -> None: for security in changes.added_securities: if security.type == SecurityType.EQUITY: self.Indics[security.symbol] = Indics() trade_bars = self.history[TradeBar](security.symbol, LOOKBACK+1, RES) for trade_bar in trade_bars: self.Indics[security.symbol].st.update(trade_bar) self.Indics[security.symbol].stch.update(trade_bar) for security in changes.removed_securities: if security.type == SecurityType.EQUITY: indic = self.Indics.pop(security.symbol, None) class Indics: def __init__(self): self.st = SuperTrend(LOOKBACK, 2, MovingAverageType.Wilders) self.stch = Stochastic(LOOKBACK, 10, 20)