| 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)