Overall Statistics |
Total Orders 5013 Average Win 0.00% Average Loss 0.00% Compounding Annual Return 357.347% Drawdown 5.000% Expectancy -0.061 Start Equity 2000000 End Equity 2146748.56 Net Profit 7.337% Sharpe Ratio 3.081 Sortino Ratio 3.963 Probabilistic Sharpe Ratio 61.494% Loss Rate 69% Win Rate 31% Profit-Loss Ratio 2.00 Alpha 1.569 Beta -1.461 Annual Standard Deviation 0.283 Annual Variance 0.08 Information Ratio 0.929 Tracking Error 0.426 Treynor Ratio -0.598 Total Fees $7056.42 Estimated Strategy Capacity $140000.00 Lowest Capacity Asset QQQ XUERCY408MW6|QQQ RIWIV7K5Z9LX Portfolio Turnover 980.69% |
from AlgorithmImports import * import pandas as pd import numpy as np class FormalAsparagusFrog(QCAlgorithm): def Initialize(self): self.SetStartDate(2021, 12, 1) self.SetEndDate(2021, 12, 17) self.SetCash(2000000) equity = self.AddEquity('QQQ', Resolution.Minute) option = self.AddOption('QQQ', Resolution.Minute) self.symbol = option.Symbol self.stock = equity.Symbol option.SetFilter(-30, 30, 0, 500) self.trade = True self.contract = None self.size = 203 self.sign = 1 # Buying OTM calls self.highest_pnl = 0 # Track the highest PnL def OnData(self, slice: Slice) -> None: if self.trade: chain = slice.OptionChains.get(self.symbol) if chain: # Select OTM calls (strike price higher than the underlying price) contract_list = [x for x in chain if x.Expiry == DateTime(2021, 12, 17) and x.Right == 0 and x.Strike > x.UnderlyingLastPrice] self.otm_call_strike = sorted(contract_list, key=lambda x: x.Strike)[0].Strike self.contract = [contract for contract in contract_list if contract.Strike == self.otm_call_strike][0] # Calculate historical volatility daily_returns = self.History(self.stock, 25, Resolution.Daily)['close'].pct_change()[1:] volatility = daily_returns.std() * 252**0.5 # Annualized volatility self.Log(volatility) self.Log(self.contract.ImpliedVolatility) # Trading decision based on volatility comparison if volatility > self.contract.ImpliedVolatility: self.sign = 1 # Buy OTM call else: self.sign = -1 # Sell OTM call # Check margin availability before placing trade margin_remaining = self.Portfolio.MarginRemaining required_margin = self.contract.LastPrice * self.size if margin_remaining > required_margin: self.trade = False self.size = self.size * self.sign self.MarketOrder(self.contract.Symbol, self.size) self.MarketOrder(self.stock, -100 * self.size * self.contract.Greeks.Delta) # Hedge by shorting stock self.Debug(f"Delta: {self.contract.Greeks.Delta}") self.previous = self.contract.Greeks.Delta else: chain = slice.OptionChains.get(self.symbol) if chain: contract_list = [x for x in chain if x.Expiry == DateTime(2021, 12, 17) and x.Right == 0 and x.Strike > x.UnderlyingLastPrice] self.otm_call_strike = sorted(contract_list, key=lambda x: x.Strike)[0].Strike self.contract = [contract for contract in contract_list if contract.Strike == self.otm_call_strike][0] self.MarketOrder(self.stock, -100 * self.size * (self.contract.Greeks.Delta - self.previous)) self.previous = self.contract.Greeks.Delta # Track highest PnL current_pnl = self.Portfolio.TotalProfit if current_pnl > self.highest_pnl: self.highest_pnl = current_pnl self.Debug(f"New highest PnL: {self.highest_pnl}")