Overall Statistics |
Total Trades 440 Average Win 1.78% Average Loss -1.37% Compounding Annual Return -99.699% Drawdown 64.500% Expectancy -0.214 Net Profit -51.900% Sharpe Ratio -1.284 Probabilistic Sharpe Ratio 0.172% Loss Rate 66% Win Rate 34% Profit-Loss Ratio 1.30 Alpha -0.439 Beta -0.305 Annual Standard Deviation 0.769 Annual Variance 0.592 Information Ratio -3.448 Tracking Error 0.809 Treynor Ratio 3.24 Total Fees $1100.00 |
from clr import AddReference AddReference("System") AddReference("QuantConnect.Algorithm") AddReference("QuantConnect.Common") from System import * from QuantConnect import * from QuantConnect.Data import * from QuantConnect.Algorithm import * from QuantConnect.Securities.Option import OptionPriceModels import numpy as np from datetime import timedelta ### <summary> ### Demonstration of the Option Chain Provider -- a much faster mechanism for manually specifying the option contracts you'd like to recieve ### data for and manually subscribing to them. ### </summary> ### <meta name="tag" content="strategy example" /> ### <meta name="tag" content="options" /> ### <meta name="tag" content="using data" /> ### <meta name="tag" content="selecting options" /> ### <meta name="tag" content="manual selection" /> class OptionChainProviderAlgorithm(QCAlgorithm): trailing_stop_pct = .93 highestPrice_call = 0 highestPrice_put = 0 trailing_stop_price_call = 0 trailing_stop_price_put = 0 def Initialize(self): self.SetStartDate(2020, 4, 21) self.SetCash(20000) # add the underlying asset self.equity = self.AddEquity("SPY R735QTJ8XC9X", Resolution.Minute) self.syl = "SPY" self.spy = "SPY" self.equity.SetDataNormalizationMode(DataNormalizationMode.Raw) # create a XX-period exponential moving average self.fast = self.EMA("SPY", 30, Resolution.Minute) # create a XX-period exponential moving average since this is minute, may have to multiply by 2 if want 2 min chart #self.slow = self.EMA("SPY", 50, Resolution.Minute) slow_ema_lookback = 100 self.slow = self.EMA("SPY", slow_ema_lookback, Resolution.Minute); self.SetWarmUp(slow_ema_lookback) # initialize the option contract with empty string self.contract_put = str() self.contract_call = str () self.contractsAdded = set() self.underlyingsymbol = self.AddEquity(self.syl, Resolution.Minute).Symbol def OnData(self, data): if self.IsWarmingUp: return if data.Time.hour < 10 or (data.Time.hour == 15 and data.Time.minute >= 30) or data.Time.hour > 15: return if not self.Portfolio.Invested: fast = self.fast.Current.Value slow = self.slow.Current.Value call_entry = (fast >= slow) and (fast <= self.equity.Price <= (fast + 0.03)) put_entry = (fast <= slow) and (fast >= self.equity.Price >= (fast - 0.03)) if call_entry: self.contract_call = self.OptionsFilter(data, OptionRight.Call) if self.contract_call in data: self.MarketOrder(self.contract_call, +10) price = self.Securities[self.contract_call].Close self.trailing_stop_price_call = self.trailing_stop_pct * price self.highestPrice_call = price if put_entry: self.contract_put = self.OptionsFilter(data, OptionRight.Put) if self.contract_put in data: self.MarketOrder(self.contract_put, +10) price = self.Securities[self.contract_put].Close self.trailing_stop_price_put = self.trailing_stop_pct * price self.highestPrice_put = price #exit if self.Portfolio.Invested: if self.contract_call in self.Securities and self.Portfolio[self.contract_call].Invested: contract_price_call = self.Securities[self.contract_call].Close take_profit = contract_price_call >= self.trailing_stop_price_call * 1.3 stop_loss_hit = contract_price_call < self.trailing_stop_price_call if take_profit or stop_loss_hit: self.MarketOrder(self.contract_call, -10) self.trailing_stop_price_call = 0 self.highestPrice_call = 0 # Updating trailing stop loss level elif contract_price_call > self.highestPrice_call: self.highestPrice_call = contract_price_call self.trailing_stop_price_call = self.highestPrice_call * self.trailing_stop_pct if self.contract_put in self.Securities and self.Portfolio[self.contract_put].Invested: contract_price_put = self.Securities[self.contract_put].Close take_profit = contract_price_put >= self.trailing_stop_price_put * 1.3 stop_loss_hit = contract_price_put < self.trailing_stop_price_put if take_profit or stop_loss_hit: self.MarketOrder(self.contract_put, -10) self.trailing_stop_price_put = 0 self.highestPrice_put = 0 # Updating trailing stop loss level elif contract_price_put > self.highestPrice_put: self.highestPrice_put = contract_price_put self.trailing_stop_price_put = self.highestPrice_put * self.trailing_stop_pct def OptionsFilter(self, data, optionRight): ''' OptionChainProvider gets a list of option contracts for an underlying symbol at requested date. Then you can manually filter the contract list returned by GetOptionContractList. The manual filtering will be limited to the information included in the Symbol (strike, expiration, type, style) and/or prices from a History call ''' contracts = self.OptionChainProvider.GetOptionContractList(self.equity.Symbol, data.Time) self.underlyingPrice = self.Securities[self.equity.Symbol].Price otm_contracts = [i for i in contracts if i.ID.OptionRight == optionRight and i.ID.Date > data.Time] if len(otm_contracts) == 0: return str() contract = sorted(sorted(otm_contracts, key=lambda x: abs(self.underlyingPrice - x.ID.StrikePrice)), key=lambda x: x.ID.Date)[0] if contract not in self.contractsAdded: self.contractsAdded.add(contract) # use AddOptionContract() to subscribe the data for specified contract self.AddOptionContract(contract, Resolution.Minute) return contract