Overall Statistics |
Total Trades 779 Average Win 3.95% Average Loss -2.60% Compounding Annual Return 98.169% Drawdown 54.200% Expectancy 0.361 Net Profit 3120.832% Sharpe Ratio 1.669 Probabilistic Sharpe Ratio 74.604% Loss Rate 46% Win Rate 54% Profit-Loss Ratio 1.52 Alpha 0.549 Beta 1.314 Annual Standard Deviation 0.471 Annual Variance 0.222 Information Ratio 1.487 Tracking Error 0.407 Treynor Ratio 0.599 Total Fees $111240.46 Estimated Strategy Capacity $240000000.00 Lowest Capacity Asset TQQQ UK280CGTCB51 |
class PriceActionTQQQ(QCAlgorithm): def Initialize(self): self.SetStartDate(2017, 1, 1) self.SetCash(100000) self.TQQQ = self.AddEquity("TQQQ", Resolution.Daily).Symbol self.SetBenchmark("QQQ") self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage) self.SetExecution(ImmediateExecutionModel()) self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel()) symbol = [Symbol.Create(self.TQQQ, SecurityType.Equity, Market.USA)] self.AddUniverseSelection(ManualUniverseSelectionModel(symbol)) self.AddAlpha(PriceActionTQQQAlphaModel(self, self.TQQQ, 0.05)) class PriceActionTQQQAlphaModel(AlphaModel): def __init__(self, algorithm, tkr, maximumDrawdown): self.period = timedelta(days=1) self.symbol = tkr self.symbolData = SymbolData(algorithm) #Set our max drawdown self.maximumDrawdown = -abs(maximumDrawdown) self.trailingHighs = dict() def Update(self, algorithm, data): insights = [] #This only gets returned if we have drawdowns appended. This only gets one update pr day, as we have set the resolution to daily drawdowns = [] #Iterrate over the securities """ for kvp in algorithm.Securities: #Set the value security = kvp.Value #If are flat, we will continue if not security.Invested: continue #Set the unrealized profit/loss pnl = security.Holdings.UnrealizedProfitPercent #If max drawdown is bigger than pnl, we send a flat insights if pnl < self.maximumDrawdown: drawdowns.append(Insight(security.Symbol, self.period, InsightType.Price, InsightDirection.Flat, 1, None)) if len(drawdowns) != 0: return drawdowns """ HO = 0.0 OL = 0.0 if self.symbolData.Updated: Open = self.symbolData.open High = self.symbolData.high Low = self.symbolData.low Close = self.symbolData.close HO = High - Open OL = Open - Low HC = High - Close CL = Close - Low if Close > Open: if HO > OL: insights.append(Insight(self.symbol, self.period, InsightType.Price, InsightDirection.Up, 1, None)) if Close < Open: if HO < OL: insights.append(Insight(self.symbol, self.period, InsightType.Price, InsightDirection.Up, 1, None)) if HO > OL: insights.append(Insight(self.symbol, self.period, InsightType.Price, InsightDirection.Down, 1, None)) if HO == OL: insights.append(Insight(self.symbol, self.period, InsightType.Price, InsightDirection.Up, 1, None)) if Close == Open: if HO < OL: insights.append(Insight(self.symbol, self.period, InsightType.Price, InsightDirection.Up, 1, None)) if HO > OL: insights.append(Insight(self.symbol, self.period, InsightType.Price, InsightDirection.Down, 1, None)) if HO == OL: insights.append(Insight(self.symbol, self.period, InsightType.Price, InsightDirection.Flat, 1, None)) self.symbolData.Updated = False for kvp in algorithm.Securities: symbol = kvp.Key security = kvp.Value if not security.Invested: self.trailingHighs.pop(symbol, None) continue if symbol not in self.trailingHighs: self.trailingHighs[symbol] = security.Holdings.AveragePrice continue if self.trailingHighs[symbol] < security.High: self.trailingHighs[symbol] = security.High continue # Check for securities past the drawdown limit securityHigh = self.trailingHighs[symbol] drawdown = (security.Low / securityHigh) - 1 if drawdown < self.maximumDrawdown: # liquidate insights.append(Insight(self.symbol, self.period, InsightType.Price, InsightDirection.Flat, 1, None)) return insights def OnSecuritiesChanged(self, algorithm, changes): self.changes = changes class SymbolData: def __init__(self, algorithm): algorithm.Consolidate("TQQQ", Resolution.Daily, self.DailyBarHandler) self.open = 0 self.close = 0 self.high = 0 self.low = 0 self.Updated = False def DailyBarHandler(self, consolidated): self.open = consolidated.Open self.close = consolidated.Close self.high = consolidated.High self.low = consolidated.Low self.Updated = True