Overall Statistics |
Total Trades 15 Average Win 50.53% Average Loss -10.43% Compounding Annual Return 15.555% Drawdown 32.500% Expectancy 4.008 Net Profit 759.832% Sharpe Ratio 0.638 Probabilistic Sharpe Ratio 6.463% Loss Rate 14% Win Rate 86% Profit-Loss Ratio 4.84 Alpha 0 Beta 0 Annual Standard Deviation 0.169 Annual Variance 0.029 Information Ratio 0.714 Tracking Error 0.169 Treynor Ratio 0 Total Fees $19.67 Estimated Strategy Capacity $43000000.00 Lowest Capacity Asset ISRG RVIFYB6Z92LH Portfolio Turnover 0.14% |
#region import from AlgorithmImports import * #endregion from Alphas.MacdAlphaModel import MacdAlphaModel class WellDressedYellowGreenFish(QCAlgorithm): def Initialize(self): self.SetStartDate(2009, 1, 1) # Set Start Date #self.SetEndDate(2023, 6, 2) self.SetCash(10000) # Set Strategy Cash self.AddUniverse(self.CoarseSelectionFunction) self.UniverseSettings.Resolution = Resolution.Daily self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Cash) self.averages = { } self.SetWarmUp(400) self.n = 0 def CoarseSelectionFunction(self, universe): selected = [] universe = sorted(universe, key=lambda c: c.DollarVolume, reverse=True) universe = [c for c in universe if c.Price > 100][:89] for coarse in universe: symbol = coarse.Symbol if symbol not in self.averages: # 1. Call history to get an array of 200 days of history data history = self.History(symbol, 189, Resolution.Daily) #2. Adjust SelectionData to pass in the history result self.averages[symbol] = SelectionData(history) self.averages[symbol].update(self.Time, coarse.AdjustedPrice) if self.averages[symbol].is_ready() and self.averages[symbol].fast > self.averages[symbol].mid > self.averages[symbol].slow: selected.append(symbol) return selected[:2] def OnData(self, data): for symbol, symbol_data in self.averages.items(): tolerance = 0.0101 tolerance3 = 0.87 tolerance4 = 11.53 tolerance5 = 50.38 tolerance6 = 52.18 tolerance7 = 56.31 if not data.ContainsKey(symbol) or not data.Bars.ContainsKey(symbol): continue holdings = self.Portfolio[symbol].Quantity if self.Portfolio.ContainsKey(symbol) else 0 signalDeltaPercent = (symbol_data.macd.Current.Value - symbol_data.macd.Signal.Current.Value)/symbol_data.macd.Fast.Current.Value if holdings <= 0 and signalDeltaPercent > tolerance: # 0.01% if self.n == 2: return # longterm says buy as well if symbol_data.macd.Histogram.Current.Value > 0: if symbol_data.mfi.Current.Value > tolerance5: if symbol_data.trading >= symbol_data.bb.LowerBand: self.SetHoldings(symbol, 0.45) self.n += 1 elif symbol_data.mfi.Current.Value > tolerance6: if symbol_data.trading >= symbol_data.bb.MiddleBand: self.SetHoldings(symbol, 0.45) self.n += 1 elif symbol_data.rc.LowerChannel < symbol_data.trading and symbol_data.rc.LinearRegression > symbol_data.trading: if symbol_data.trading > symbol_data.bb.LowerBand and symbol_data.trading < symbol_data.bb.MiddleBand: self.SetHoldings(symbol, 0.25) self.n += 0.5 elif holdings >= 0 and signalDeltaPercent < -0.0021: if symbol_data.mfi.Current.Value >= symbol_data.mfi.Previous.Value: if symbol_data.mfi.Current.Value <= tolerance5: if symbol_data.trading >= symbol_data.bb.MiddleBand and symbol_data.trading <= symbol_data.bb.UpperBand: self.Liquidate(symbol) self.n -= 1 elif symbol_data.trading >= symbol_data.bb.LowerBand and symbol_data.trading <= symbol_data.bb.MiddleBand: if symbol_data.trading > symbol_data.rc.LowerChannel: self.Liquidate(symbol) self.n -= 1 elif symbol_data.trading <= symbol_data.bb.LowerBand: self.Liquidate(symbol) self.n -= 1 elif tolerance5 < symbol_data.mfi.Current.Value <= tolerance6: if symbol_data.trading >= symbol_data.rc.LowerChannel and symbol_data.trading <= symbol_data.rc.LinearRegression: if symbol_data.trading >= symbol_data.bb.MiddleBand and symbol_data.trading <= symbol_data.bb.UpperBand: self.MarketOrder(symbol, -((self.Portfolio[symbol].Quantity)/2)) self.n -= 0.5 elif symbol_data.trading >= symbol_data.bb.UpperBand: self.Liquidate(symbol) self.n -= 1 elif tolerance6 < symbol_data.mfi.Current.Value < tolerance7: if symbol_data.trading > symbol_data.bb.MiddleBand and symbol_data.trading < symbol_data.bb.UpperBand: self.MarketOrder(symbol, -((self.Portfolio[symbol].Quantity)/2)) self.n -= 0.5 elif symbol_data.mfi.Current.Value >= tolerance7: if symbol_data.trading > symbol_data.rc.UpperChannel: if symbol_data.trading > symbol_data.bb.UpperBand: self.Liquidate(symbol) self.n -= 1 elif symbol_data.mfi.Current.Value <= symbol_data.mfi.Previous.Value: if symbol_data.mfi.Current.Value >= tolerance7: if symbol_data.trading > symbol_data.rc.UpperChannel: self.Liquidate(symbol) self.n -= 1 elif symbol_data.trading > symbol_data.bb.UpperBand: self.Liquidate(symbol) self.n -= 1 elif symbol_data.trading > symbol_data.rc.LinearRegression and symbol_data.trading < symbol_data.rc.UpperChannel: self.Liquidate(symbol) self.n -= 1 elif tolerance6 < symbol_data.mfi.Current.Value <= tolerance7: if symbol_data.trading >= symbol_data.rc.LinearRegression and symbol_data.trading <= symbol_data.rc.UpperChannel: self.MarketOrder(symbol, -((self.Portfolio[symbol].Quantity)/2)) self.n -= 0.5 elif symbol_data.trading <= symbol_data.bb.UpperBand and symbol_data.trading >= symbol_data.bb.MiddleBand: self.MarketOrder(symbol, -((self.Portfolio[symbol].Quantity)/2)) self.n -= 0.5 elif tolerance5 < symbol_data.mfi.Current.Value <= tolerance6: if symbol_data.trading >= symbol_data.bb.UpperBand: self.Liquidate(symbol) self.n -= 1 elif symbol_data.trading <= symbol_data.bb.UpperBand and symbol_data.trading >= symbol_data.bb.MiddleBand: self.Liquidate(symbol) self.n -= 1 elif symbol_data.mfi.Current.Value <= tolerance5: if symbol_data.trading > symbol_data.bb.LowerBand: self.Liquidate(symbol) self.n -= 1 class SelectionData(): #3. Update the constructor to accept a history array def __init__(self, history): self.slow = ExponentialMovingAverage(335)#optimised Fib self.mid = ExponentialMovingAverage(233)#optimised Fib self.fast = ExponentialMovingAverage(136) self.macd = MovingAverageConvergenceDivergence(144, 377, 233, MovingAverageType.Exponential) self.mfi = RelativeStrengthIndex(145, MovingAverageType.Simple) self.bb = BollingerBands(55, 0.6) self.trading = WilderMovingAverage(14) self.rc = RegressionChannel(200, 1.0) #4. Loop over the history data and update the indicators for bar in history.itertuples(): self.slow.Update(bar.Index[1], bar.close) self.mid.Update(bar.Index[1], bar.close) self.fast.Update(bar.Index[1], bar.close) self.trading.Update(bar.Index[1], bar.close) self.macd.Update(bar.Index[1], bar.close) self.mfi.Update(bar.Index[1], bar.close) self.bb.Update(bar.Index[1], bar.close) self.rc.Update(bar.Index[1], bar.close) def is_ready(self): return self.slow.IsReady and self.mid.IsReady and self.fast.IsReady and self.trading.IsReady and self.bb.UpperBand.IsReady and self.bb.MiddleBand.IsReady and self.bb.LowerBand.IsReady return self.rc.UpperChannel.IsReady and self.rc.LowerChannel.IsReady and self.rc.LinearRegression.IsReady def update(self, time, price): self.fast.Update(time, price) self.trading.Update(time, price) self.mid.Update(time, price) self.slow.Update(time, price) self.macd.Update(time, price) self.rc.Update(time, price) self.mfi.Update(time, price)