Overall Statistics |
Total Trades 19 Average Win 1.08% Average Loss -3.73% Compounding Annual Return 2.297% Drawdown 11.100% Expectancy 0.146 Net Profit 4.652% Sharpe Ratio 0.269 Probabilistic Sharpe Ratio 10.154% Loss Rate 11% Win Rate 89% Profit-Loss Ratio 0.29 Alpha -0.005 Beta 0.305 Annual Standard Deviation 0.067 Annual Variance 0.005 Information Ratio -0.576 Tracking Error 0.102 Treynor Ratio 0.059 Total Fees $47.50 Estimated Strategy Capacity $54000.00 Lowest Capacity Asset SPY 3174CDSVN3D5Y|SPY R735QTJ8XC9X |
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. # Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from AlgorithmImports import * class TrailingStopRiskManagementModel(RiskManagementModel): '''Provides an implementation of IRiskManagementModel that limits the maximum possible loss measured from the highest unrealized profit''' def __init__(self, maximumDrawdownPercent = 0.05): '''Initializes a new instance of the TrailingStopRiskManagementModel class Args: maximumDrawdownPercent: The maximum percentage drawdown allowed for algorithm portfolio compared with the highest unrealized profit, defaults to 5% drawdown''' self.maximumDrawdownPercent = abs(maximumDrawdownPercent) self.trailing = dict() def ManageRisk(self, algorithm, targets): '''Manages the algorithm's risk at each time step Args: algorithm: The algorithm instance targets: The current portfolio targets to be assessed for risk''' riskAdjustedTargets = list() for kvp in algorithm.Securities: symbol = kvp.Key security = kvp.Value # Remove if not invested if not security.Invested: self.trailing.pop(symbol, None) continue profitPercent = security.Holdings.UnrealizedProfitPercent # Add newly invested securities value = self.trailing.get(symbol) if value == None: newValue = profitPercent if profitPercent > 0 else 0 self.trailing[symbol] = newValue continue # Check for new high and update if value < profitPercent: self.trailing[symbol] = profitPercent continue # If unrealized profit percent deviates from local max for more than affordable percentage if profitPercent < value - self.maximumDrawdownPercent: # liquidate riskAdjustedTargets.append(PortfolioTarget(symbol, 0)) return riskAdjustedTargets
import TrailingStopRiskManagementModel as mr class UpgradedRedOrangeParrot(QCAlgorithm): def Initialize(self): self.SetStartDate(2017, 10, 1) # Set Start Date self.SetEndDate(2019, 10, 1) # Set Start Date self.SetCash(100000) # Set Strategy Cash self.equity = self.AddEquity("SPY", Resolution.Minute) self.equity.SetDataNormalizationMode(DataNormalizationMode.Raw) self.symbol = self.equity.Symbol self.vix = self.AddData(CBOE, "VIX").Symbol self.rank = 0 self.contract = str() self.contractsAdded = set() self.LatestAskPrice=1 self.DaysBeforeExp = 2 self.DTE = 45 self.OTM = 0.10 self.lookbackIV = 252 self.IVlvl = 0.25 self.percentage=0.5 self.security = self.Securities["SPY"] # self.SetRiskManagement(TrailingStopRiskManagementModel()) self.Schedule.On(self.DateRules.EveryDay(self.symbol), \ self.TimeRules.AfterMarketOpen(self.symbol, 30), \ self.Plotting) self.Schedule.On(self.DateRules.EveryDay(self.symbol),\ self.TimeRules.AfterMarketOpen(self.symbol, 30), \ self.VIXRank) def VIXRank(self): history = self.History(CBOE, self.vix, self.lookbackIV, Resolution.Daily) self.rank = ((self.Securities[self.vix].Price - min(history[:-1]["low"])) / (max(history[:-1]["high"]) - min(history[:-1]["low"])) ) def OnData(self, data): '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. Arguments: data: Slice object keyed by symbol containing the stock data ''' if self.IsWarmingUp: return # if not self.Portfolio[self.symbol].invested: # self.SetHoldings(self.symbol, self.percentage) profitPercent = self.security.Holdings.UnrealizedProfitPercent if self.rank > self.IVlvl: self.SellPut(data) #Only do this if profitable, management code needed if self.contract: if profitPercent >= 0.25 or profitPercent <= -2: self.contract.Liquidate if (self.contract.ID.Date - self.Time) <= timedelta(self.DaysBeforeExp): self.Liquidate(self.contract) self.Log("Closed: too close to expiration") self.contract = str() def SellPut(self, data): if self.contract == str(): self.contract = self.OptionsFilter(data) return elif not self.Portfolio[self.contract].Invested and data.ContainsKey(self.contract): # qty = self.Portfolio.TotalPortfolioValue / self.LatestAskPRice # qty = int(self.percentage * quantity / 100) bp = str(self.Portfolio.GetBuyingPower(self.symbol)) # self.Log("Starting BP: " + bp) # self.Debug("Selling puts: " + str(10) + "@" + str(self.contract.ID.StrikePrice)) self.Sell(self.contract, 10) bp = str(self.Portfolio.GetBuyingPower(self.symbol)) # self.Debug("Ending BP: " + bp) def OptionsFilter(self, data): contracts = self.OptionChainProvider.GetOptionContractList(self.symbol, data.Time) self.underlyingPrice = self.Securities[self.symbol].Price otm_puts = [i for i in contracts if i.ID.OptionRight== OptionRight.Put and self.underlyingPrice - i.ID.StrikePrice > self.OTM * self.underlyingPrice and self.DTE - 8 < (i.ID.Date - data.Time).days < self.DTE + 8] if len(otm_puts) > 0: contract = sorted(sorted(otm_puts, key = lambda x: abs((x.ID.Date - self.Time).days - self.DTE)), key = lambda x: self.underlyingPrice - x.ID.StrikePrice)[0] if contract not in self.contractsAdded: self.contractsAdded.add(contract) self.AddOptionContract(contract, Resolution.Minute) return contract else: return str() def Plotting(self): self.Plot("Vol Chart", "Rank", self.rank) self.Plot("Vol Chart", "lvl", self.IVlvl) self.Plot("Data Chart", self.symbol, self.Securities[self.symbol].Close) option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type == SecurityType.Option] if option_invested: self.Plot("Data Chart", "Strike", option_invested[0].ID.StrikePrice)