Overall Statistics |
Total Trades 127 Average Win 0.88% Average Loss -0.53% Compounding Annual Return 26.572% Drawdown 3.700% Expectancy 0.650 Net Profit 25.258% Sharpe Ratio 2.03 Sortino Ratio 2.2 Probabilistic Sharpe Ratio 97.792% Loss Rate 38% Win Rate 62% Profit-Loss Ratio 1.67 Alpha 0.083 Beta 0.351 Annual Standard Deviation 0.063 Annual Variance 0.004 Information Ratio -0.002 Tracking Error 0.087 Treynor Ratio 0.363 Total Fees $0.00 Estimated Strategy Capacity $41000000.00 Lowest Capacity Asset SPY R735QTJ8XC9X Portfolio Turnover 33.80% |
from System import * from QuantConnect import * from QuantConnect.Algorithm import * from QuantConnect.Indicators import * import tweepy, statistics from datetime import datetime, timedelta, date import numpy as np from scipy import stats from AlgorithmImports import * from sklearn.linear_model import LinearRegression, LogisticRegression from sklearn.tree import ExtraTreeRegressor, ExtraTreeClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error from sklearn import preprocessing class DualMomentumWithOutDaysAlphaModel(AlphaModel): def __init__(self, algorithm, VOLA = 126, BASE_RET = 83, resolution = Resolution.Daily, *args, **kwargs): super().__init__() self.VOLA = VOLA self.BASE_RET = BASE_RET self.resolution = Resolution.Daily # resolution self.MKT = algorithm.AddEquity('SPY', resolution).Symbol self.SLV = algorithm.AddEquity('SLV', resolution).Symbol self.GLD = algorithm.AddEquity('GLD', resolution).Symbol self.XLI = algorithm.AddEquity('XLI', resolution).Symbol self.XLU = algorithm.AddEquity('XLU', resolution).Symbol self.DBB = algorithm.AddEquity('DBB', resolution).Symbol self.UUP = algorithm.AddEquity('UUP', resolution).Symbol self.count = self.BASE_RET self.outday = 5 pairs = [self.MKT, self.SLV, self.GLD, self.XLI, self.XLU, self.DBB, self.UUP] for symbol in pairs: self.consolidator = TradeBarConsolidator(timedelta(days=1)) self.consolidator.DataConsolidated += self.consolidation_handler algorithm.SubscriptionManager.AddConsolidator(symbol, self.consolidator) self.history = np.log(algorithm.History(pairs, self.VOLA + 1, self.resolution)) #self.history = self.history['close'].unstack(level=0).dropna() self.predictionInterval = Time.Multiply(Extensions.ToTimeSpan(self.resolution), 1) resolutionString = Extensions.GetEnumString(resolution, Resolution) self.Name = f"{self.__class__.__name__}({resolutionString})" # Force alpha to only produce insights Daily at 11.10am self.set_flag = False algorithm.Schedule.On(algorithm.DateRules.EveryDay(), algorithm.TimeRules.AfterMarketOpen('SPY', 100), self.SetFlag) def SetFlag(self): self.set_flag = True def consolidation_handler(self, sender, consolidated): self.history.loc[consolidated.EndTime, consolidated.Symbol] = consolidated.Close self.history = self.history.iloc[-(self.VOLA + 1):] def Update(self, algorithm, _data): if algorithm.IsWarmingUp or not self.set_flag: return [] self.set_flag = False insights = [] # Volatility vola = self.history[self.MKT].pct_change().std() * np.sqrt(252) wait_days = int(vola * self.BASE_RET) period = int((1.0 - vola) * self.BASE_RET) r = self.history.pct_change(period).iloc[-1] exit_market = r[self.SLV] < r[self.GLD] and r[self.XLI] < r[self.XLU] and r[self.DBB] < r[self.UUP] direction = InsightDirection.Down if (exit_market): #algorithm.Plot("In vs Out", "Market", -1) direction = InsightDirection.Down self.outday = self.count elif (self.count >= wait_days + self.outday): #algorithm.Plot("In vs Out", "Market", 1) direction = InsightDirection.Up else: direciton = InsightDirection.Flat self.count += 1 insights.append(Insight.Price(self.MKT, self.predictionInterval, direction)) return insights
#region imports from AlgorithmImports import * #endregion import math class SupportResistance: # Get the S&R's for the last 2 weeks. def __init__(self, algorithm, ticker): self.Ticker = ticker self.Algorithm = algorithm self.Daily = RollingWindow[TradeBar](7) self.Min = algorithm.MIN(self.Ticker, 390, Resolution.Minute) # Range of today; breaking out of new highs/lows self.Max = algorithm.MAX(self.Ticker, 390, Resolution.Minute) algorithm.Consolidate(self.Ticker, Resolution.Daily, self.SaveDailyBars) def NextSupport(self): support = [] price = self.Algorithm.Securities[self.Ticker].Price # Rounded Price to $1 support.append( round(price) ) # Rounded Price to $10 support.append( int(math.floor(price / 10.0)) * 10 ) # Yesterday's OHLC Price support.append( self.Daily[0].Close ) support.append( self.Daily[0].Low ) # Append 7 day Low: support.append( min([bar.Low for bar in self.Daily]) ) support = sorted(support, reverse=True) return support[0] def NextResistance(self): resistance = [] price = self.Algorithm.Securities[self.Ticker].Price # Round Price Up to $1 resistance.append( math.ceil(price) ) # Rounded Price Up to $10 resistance.append( int(math.ceil(price / 10.0)) * 10 ) # Yesterday's Close, High resistance.append( self.Daily[0].Close ) resistance.append( self.Daily[0].High ) # Append 7 Day High resistance.append( max([bar.High for bar in self.Daily]) ) # Take the lowest value on the list resistance = sorted(resistance) return resistance[0] # Build a 14 day historical rolling window of underlying prices. def SaveDailyBars(self, bar): self.Daily.Add(bar) # Reset any "daily" indicators def Reset(self): self.Min.Reset() self.Max.Reset()
#region imports from AlgorithmImports import * #endregion from trade import * from levels import * from dual_momentum_with_out_days_alpha import DualMomentumWithOutDaysAlphaModel from symbol_data import SymbolData from ml_model import ML_Model class OptionsOvernightContrarian(QCAlgorithm): def Initialize(self): # Settings self.SetStartDate(2023, 1, 1) #self.SetEndDate(2020, 6, 1) self.SetCash(10000) self.SetWarmup(timedelta(10)) self.EnableAutomaticIndicatorWarmUp = True self.orderDate = None # Apply Robinhood Fees self.SetSecurityInitializer(lambda security: security.SetFeeModel(ConstantFeeModel(0))) # Select Underlying and Configure self.ticker = "SPY" # ES CME Futures.Indices.SP500EMini self.equity = self.AddEquity(self.ticker, Resolution.Minute, extendedMarketHours=True) self.equity.SetDataNormalizationMode(DataNormalizationMode.Raw) self.Data = dict() self.Data_ = dict() self.DataT = dict() self.DataHour = dict() self.DataDaily = dict() # initialize our equity data BarPeriod = timedelta(minutes=5) BarPeriod_ = timedelta(minutes=15) TTPeriod = timedelta(minutes=30) HourPeriod = timedelta(minutes=60) DailyPeriod = timedelta(minutes=60*24) RollingWindowSize = 5 for symbol in [self.ticker]: equity = self.AddEquity(symbol, Resolution.Minute) equity.SetDataNormalizationMode(DataNormalizationMode.Raw) self.Data[symbol] = SymbolData(equity, BarPeriod, RollingWindowSize * (390/5)) self.Data_[symbol] = SymbolData(equity, BarPeriod_, RollingWindowSize * (390/15)) self.DataT[symbol] = SymbolData(equity, TTPeriod, RollingWindowSize * (390/10)) self.DataHour[symbol] = SymbolData(equity, HourPeriod, RollingWindowSize) self.DataDaily[symbol] = SymbolData(equity, HourPeriod, RollingWindowSize*5) for symbol, symbolData in self.Data.items(): consolidator = TradeBarConsolidator(BarPeriod) consolidator.DataConsolidated += self.OnDataConsolidated self.SubscriptionManager.AddConsolidator(symbol, consolidator) quoteconsolidator = QuoteBarConsolidator(BarPeriod) quoteconsolidator.DataConsolidated += self.OnQuoteDataConsolidated self.SubscriptionManager.AddConsolidator(symbol, quoteconsolidator) for symbol, symbolData in self.Data_.items(): consolidator = TradeBarConsolidator(BarPeriod_) consolidator.DataConsolidated += self.OnDataConsolidated self.SubscriptionManager.AddConsolidator(symbol, consolidator) quoteconsolidator = QuoteBarConsolidator(BarPeriod_) quoteconsolidator.DataConsolidated += self.OnQuoteDataConsolidated self.SubscriptionManager.AddConsolidator(symbol, quoteconsolidator) for symbol, symbolData in self.DataT.items(): consolidator = TradeBarConsolidator(TTPeriod) consolidator.DataConsolidated += self.OnDataConsolidated self.SubscriptionManager.AddConsolidator(symbol, consolidator) quoteconsolidator = QuoteBarConsolidator(TTPeriod) quoteconsolidator.DataConsolidated += self.OnQuoteDataConsolidated self.SubscriptionManager.AddConsolidator(symbol, quoteconsolidator) for symbol, symbolData in self.DataHour.items(): consolidator = TradeBarConsolidator(HourPeriod) consolidator.DataConsolidated += self.OnDataConsolidated self.SubscriptionManager.AddConsolidator(symbol, consolidator) quoteconsolidator = QuoteBarConsolidator(HourPeriod) quoteconsolidator.DataConsolidated += self.OnQuoteDataConsolidated self.SubscriptionManager.AddConsolidator(symbol, quoteconsolidator) for symbol, symbolData in self.DataDaily.items(): consolidator = TradeBarConsolidator(DailyPeriod) consolidator.DataConsolidated += self.OnDataConsolidated self.SubscriptionManager.AddConsolidator(symbol, consolidator) quoteconsolidator = QuoteBarConsolidator(DailyPeriod) quoteconsolidator.DataConsolidated += self.OnQuoteDataConsolidated self.SubscriptionManager.AddConsolidator(symbol, quoteconsolidator) # Select Target Asset to Trade self.option = self.AddOption(self.ticker) #self.option.SetFilter(self.OptionFilterUniverse) self.option.SetFilter(-3, 10, 0, 1) # # Set TrainingMethod to be executed immediately self.Train(self.TrainingMethod) # Set TrainingMethod to be executed at 8:00 am every Sunday self.Train(self.DateRules.EveryDay(self.ticker), self.TimeRules.At(9 , 0), self.TrainingMethod) # Exit before any assignments self.Schedule.On(self.DateRules.EveryDay(self.ticker), self.TimeRules.AfterMarketOpen(self.ticker, 1), self.MarketOpen) self.Schedule.On(self.DateRules.EveryDay(self.ticker), self.TimeRules.BeforeMarketClose(self.ticker, 5), self.BeforeMarketClose) self.Schedule.On(self.DateRules.EveryDay(self.ticker), self.TimeRules.BeforeMarketClose(self.ticker, -1), self.MarketClose) # Trade Tracker self.Trade = TradeManagement(self, self.ticker, self.option.Symbol) # Support Resistance Detection: self.SupportResistance = SupportResistance(self, self.ticker) self.mean = self.EMA(self.ticker, 60, Resolution.Minute) def MarketClose(self): self.SupportResistance.Reset() def CloseTo(self, x, y, delta): return abs(x-y) < delta def OnData(self, data): # Ignore dividends, splits etc if not self.equity.Exchange.ExchangeOpen or self.IsWarmingUp: return # Manage existing positions: self.Trade.ManageOpenPositions() price = self.equity.Price support = self.SupportResistance.NextSupport() resistance = self.SupportResistance.NextResistance() mean = self.mean.Current.Value #self.Plot("SPY", "Minute", self.equity.Price) #self.Plot("Volume", "Minute", self.equity.Volume) # self.Plot('SPY', 'Support', support) # self.Plot('SPY', 'Resistance', resistance) # for symbol in self.DataHour.keys(): # symbolData = self.DataHour[symbol] # if symbolData.IsReady() and symbolData.WasJustUpdated(self.Time): # bars = symbolData.Bars # curr = bars[0] # prev = bars[1] # # self.Plot('SPY', 'Current', float(curr.Close)) # # self.Plot('SPY', 'Previous', float(prev.Close)) # self.model = ML_Model(self, self.Data, symbol, timeframe = 5) # price_obs, price_pred, duration_obs, duration_pred, direction_obs, direction_pred, p_val = self.model.BuildModel() # if (direction_obs == 1) and (p_val < 0.025): # if duration_obs > 1: # #self.SetHoldings(symbol, 0.95) # self.Long = True # if duration_obs <= 1: # #self.SetHoldings(symbol, 0.0) # self.Long = False # if (direction_obs == 0) and (p_val < 0.025): # #self.SetHoldings(symbol, 0.0) # self.Long = False for symbol in self.Data_.keys(): symbolData = self.Data_[symbol] if symbolData.IsReady() and symbolData.WasJustUpdated(self.Time): bars = symbolData.Bars curr = bars[0] prev = bars[1] # self.Plot('SPY', 'Current', float(curr.Close)) # self.Plot('SPY', 'Previous', float(prev.Close)) self.model = ML_Model(self, self.Data_, symbol, timeframe = 15) price_obs, price_pred, duration_obs, duration_pred, direction_obs, direction_pred, p_val = self.model.BuildModel() self.Plot("SPY", 'Actual_15', float(price_obs)) self.Plot("SPY", 'Pred_15', float(price_pred)) # self.Plot("SPY_Duration", 'Actual_15', float(duration_obs)) # self.Plot("SPY_Duration", 'Pred_15', float(duration_pred)) # self.Plot("SPY_Direction", 'Actual_15', float(direction_obs)) # self.Plot("SPY_Direction", 'Pred_15', float(direction_pred)) self.Plot("PVal", 'p-val', float(p_val)) # chain = data.OptionChains.get(option.Symbol) # if not chain: # return # # Find ATM call with the farthest expiry # expiry = max([x.Expiry for x in chain]) # call_contracts = sorted([x for x in chain # if x.Right == OptionRight.Call and x.Expiry == expiry], # key=lambda x: abs(chain.Underlying.Price - x.Strike)) # if not call_contracts: # return # atm_call = call_contracts[0] # naked_call = OptionStrategies.NakedCall(symbol, atm_call.Strike, expiry) if (direction_obs == 2) and (p_val < 0.025): #2 if duration_obs > 1: self.SetHoldings(symbol, 0.95) if duration_obs <= 1: self.SetHoldings(symbol, 0.0) if (direction_obs == 1) and (p_val < 0.025): self.SetHoldings(symbol, 0.00) # if (direction_obs == 1) and (p_val < 0.025): #2 # # if isn't invested # if duration_obs > 3: # self.SetHoldings(symbol, -0.95) # elif (direction_obs == 2) and (p_val < 0.025): # if duration_obs > 3: # self.SetHoldings(symbol, 0.95) # self.Plot("Quantity", 'quantity', float(self.Portfolio[symbol].Quantity)) # for symbol in self.DataHour.keys(): # symbolData = self.DataHour[symbol] # if symbolData.IsReady() and symbolData.WasJustUpdated(self.Time): # bars = symbolData.Bars # curr = bars[0] # prev = bars[1] # # self.Plot('SPY', 'Current_H', float(curr.Close)) # # self.Plot('SPY', 'Previous_H', float(prev.Close)) # self.model = ML_Model(self, self.DataHour, symbol) # data, y_pred = self.model.BuildModel() # self.Plot("SPY", 'Actual_H', float(data)) # self.Plot("SPY", 'Pred_H', float(y_pred)) # if self.CloseTo(price, support, 0.15) and (curr.Open > prev.Close):#(mean > support): # t = self.Trade.Create(OrderDirection.Buy) # self.Log(f"{self.Time} LONG: Price {price} Support {support}") # #self.Plot('SPY', 'Buy', price) # #self.Plot('SPY', 'Support', support) # if self.CloseTo(price, resistance, 0.15) and (curr.Open < prev.Close): #(mean < resistance): # t = self.Trade.Create(OrderDirection.Sell) # self.Log(f"{self.Time} SHORT: Price {price} Resistance {resistance}") #self.Plot('SPY', 'Sell', price) #self.Plot('SPY', 'Resistance', resistance) def TrainingMethod(self): self.Log(f'Start training at {self.Time}') # Use the historical data to train the machine learning model history = self.History(self.ticker, 200, Resolution.Minute) # ML code: pass def OnDataConsolidated(self, sender, bar): self.Data[bar.Symbol.Value].Bars.Add(bar) self.Data_[bar.Symbol.Value].Bars.Add(bar) self.DataT[bar.Symbol.Value].Bars.Add(bar) self.DataHour[bar.Symbol.Value].Bars.Add(bar) self.DataDaily[bar.Symbol.Value].Bars.Add(bar) def OnQuoteDataConsolidated(self, sender, quotebar: QuoteBar): self.Data[quotebar.Symbol.Value].QuoteBars.Add(quotebar) self.Data_[quotebar.Symbol.Value].QuoteBars.Add(quotebar) self.DataT[quotebar.Symbol.Value].QuoteBars.Add(quotebar) self.DataHour[quotebar.Symbol.Value].QuoteBars.Add(quotebar) self.DataDaily[quotebar.Symbol.Value].QuoteBars.Add(quotebar) # def UpdateVolumeProfileWindow(self, sender: object, updated: IndicatorDataPoint) -> None: # indicator = sender # self.Data[updated.Symbol.Value].MarketProfile['time'].Add(updated.EndTime) # self.Data[updated.Symbol.Value].MarketProfile["vp"].Add(updated.Value) # self.Data[updated.Symbol.Value].MarketProfile["vp_profilehigh"].Add(indicator.ProfileHigh) # self.Data[updated.Symbol.Value].MarketProfile["vp_profilelow"].Add(indicator.ProfileLow) # self.Data[updated.Symbol.Value].MarketProfile["vp_pocprice"].Add(indicator.POCPrice) # self.Data[updated.Symbol.Value].MarketProfile["vp_pocvolume"].Add(indicator.POCVolume) # self.Data[updated.Symbol.Value].MarketProfile["vp_valueareavolume"].Add(indicator.ValueAreaVolume) # self.Data[updated.Symbol.Value].MarketProfile["vp_valueareahigh"].Add(indicator.ValueAreaHigh) # self.Data[updated.Symbol.Value].MarketProfile["vp_valuearealow"].Add(indicator.ValueAreaLow) ################################################################################################# # SCRATCH ####################################################################################### ################################################################################################# def MarketOpen(self): pass def BeforeMarketClose(self): pass def OptionFilterUniverse(self, universe): # Select puts 2-3 strikes OOM, expiring at least 2 days out; but no more than 10 return universe.IncludeWeeklys().Strikes(-3, 3).Expiration(2, 10) def StrikeVisualization(self, contracts): strikes = f"{self.Time} - {self.equity.Price} :: [[" for x in self.contracts: strikes = strikes + f"{x.Strike}-{x.Expiry} ]] [[" self.Log(strikes) self.Log(f"{self.Time} - Contract: {self.contracts[0]} | Strike: {self.contracts[0].Strike} | Underlying: {self.equity.Price} | Delta: {self.equity.Price - self.contracts[0].Strike}")
#region imports from AlgorithmImports import * #endregion # Your New Python File import math import tweepy, statistics, json from datetime import datetime, timedelta, date import numpy as np from scipy import stats from AlgorithmImports import * from sklearn.pipeline import Pipeline from sklearn.linear_model import LinearRegression, LogisticRegression from sklearn.tree import ExtraTreeRegressor, ExtraTreeClassifier from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier from sklearn.model_selection import train_test_split, GridSearchCV, StratifiedKFold, KFold from sklearn.feature_selection import SelectKBest, f_regression, f_classif from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error, r2_score, explained_variance_score, accuracy_score from sklearn import preprocessing from sklearn.preprocessing import MinMaxScaler, StandardScaler, LabelEncoder import statistics import ta from scipy.stats import ttest_rel, ttest_ind, ttest_1samp import pickle import inspect class ML_Model: def __init__(self, algorithm, _dict, ticker, timeframe): self.Ticker = ticker self.Algorithm = algorithm self.DataBars = _dict[self.Ticker] self.timeframe = str(timeframe) + '-' + 'minute' + '_' self.regressor_model1 = pickle.loads(bytes(self.Algorithm.ObjectStore.ReadBytes(self.timeframe + 'Price_Change'))) self.regressor_model2 = pickle.loads(bytes(self.Algorithm.ObjectStore.ReadBytes(self.timeframe + 'Price_Movement_Duration'))) self.classifier_model = pickle.loads(bytes(self.Algorithm.ObjectStore.ReadBytes(self.timeframe + 'Price_Direction'))) # self.regressor1 = RandomForestRegressor(random_state = 42) # self.regressor2 = RandomForestRegressor(random_state = 42) # self.classifier = RandomForestClassifier(random_state = 42) # self.pipeline_reg = Pipeline([ # ('selector', SelectKBest(f_regression)), # ('regressor', self.regressor) # ]) # self.pipeline_clf = Pipeline([ # ('selector', SelectKBest(f_classif)), # ('classifier', classifier) # ]) # self.hyperparameters = { # 'selector__k': [2, 4, 6, 8, 'all'], # 'regressor__n_estimators' : [10, 50, 150, 200], # 'regressor__max_depth': [None, 5, 10, 15], # 'regressor__min_samples_split': [2, 5, 25] # } # self.cv = KFold(n_splits=10, shuffle = True, random_state = 42) # self.regression_grid_search = GridSearchCV(self.pipeline_reg, self.hyperparameters, scoring = 'neg_mean_squared_error', cv = self.cv) # self.classifier_grid_search = GridSearchCV(self.pipeline_clf, self.hyperparameters, scoring = 'accuracy', cv = self.cv) self.best_model = None def BuildModel(self): if self.DataBars.IsReady(): bars = self.DataBars.Bars quotebars = self.DataBars.QuoteBars # TradeBar _time = np.flip(np.array([bar.Time for bar in bars])).reshape(-1,1).flatten() _open = np.flip(np.array([bar.Open for bar in bars])).reshape(-1,1).flatten() _high = np.flip(np.array([bar.High for bar in bars])).reshape(-1,1).flatten() _low = np.flip(np.array([bar.Low for bar in bars])).reshape(-1,1).flatten() _close = np.flip(np.array([bar.Close for bar in bars])).reshape(-1,1).flatten() _volume = np.flip(np.array([bar.Volume for bar in bars])).reshape(-1,1).flatten() #_close = pd.DataFrame(_close, columns = ['close']) df = pd.DataFrame({'time': _time, 'open': _open, 'high': _high, 'low': _low, 'close': _close, 'volume': _volume }) df = compute_indicators(df) df = add_features(df) df = mod_duration(df) # close_above_previous_close = _close.close > _close.close.shift() # close_above_current_open = _close > _open # close_pct_change = _close.close.pct_change() # def multi_condition(x): # if all(((i is True) or (i > 0)) for i in x): # return 'Up' # elif all(((i is False) or (i < 0)) for i in x): # return 'Down' # else: # return 'Chop' # features = close_above_previous_close + close_above_current_open + close_pct_change # features = pd.DataFrame(features) # features['Price_Movement'] = features.apply(lambda x: multi_condition(x), axis = 1) # QuoteBar # q_askopen = np.flip(np.array([bar.Ask.Open for bar in quotebars])).reshape(-1,1) # q_askhigh = np.flip(np.array([bar.Ask.High for bar in quotebars])).reshape(-1,1) # q_asklow = np.flip(np.array([bar.Ask.Low for bar in quotebars])).reshape(-1,1) # q_asksize = np.flip(np.array([bar.LastAskSize for bar in quotebars])).reshape(-1,1) # q_bidopen = np.flip(np.array([bar.Bid.Open for bar in quotebars])).reshape(-1,1) # q_bidhigh = np.flip(np.array([bar.Bid.High for bar in quotebars])).reshape(-1,1) # q_bidlow = np.flip(np.array([bar.Bid.Low for bar in quotebars])).reshape(-1,1) # q_bidsize = np.flip(np.array([bar.LastBidSize for bar in quotebars])).reshape(-1,1) # X = _open + _high + _low + q_askopen + q_askhigh + q_asklow + q_bidopen + q_bidhigh + q_bidlow # y = np.flip(np.array([bar.Close for bar in bars])).reshape(-1,1) df = df.dropna() X = df.drop(['close', 'time', 'date', 'Price_Direction', 'Price_Movement_Duration'], axis=1) le = LabelEncoder() y_clf = le.fit_transform(df['Price_Direction']) #y_clf = (y_clf == 2).astype(int) y1 = df['close'] y2 = df['Price_Movement_Duration'] X_train, X_test, y1_train, y1_test, y2_train, y2_test = train_test_split(X, y1, y2, test_size = 0.2, random_state = 1990) X_train_clf, X_test_clf, y_train_clf, y_test_clf = train_test_split(X, y_clf, test_size = 0.2, random_state = 1990) self.regressor_model1.fit(X_train, y1_train) # self.regressor1.fit(X_train, y_train) self.regressor_model2.fit(X_train, y2_train) # self.regressor2.fit(X_train, y_train) self.classifier_model.fit(X_train, y_train_clf) # self.classifier.fit(X_train, y_train_clf) y_pred1 = self.regressor_model1.predict(X_test) y_pred2 = self.regressor_model2.predict(X_test) y_pred_clf = self.classifier_model.predict(X_test_clf) # self.Algorithm.Plot("Metrics", 'r2-price', r2_score(y1_test, y_pred1)) # self.Algorithm.Plot("Metrics", 'r2-movement-duration', r2_score(y2_test, y_pred2)) # self.Algorithm.Plot("Metrics", 'accuracy-direction', accuracy_score(y_test_clf, y_pred_clf)) actual = str(le.inverse_transform(y_test_clf.reshape(-1,1)[-1])[0]) pred = str(le.inverse_transform(y_pred_clf.reshape(-1,1)[-1])[0]) # def movement_score(i): # if i == 'Up': # return 1.0 # elif i == 'Down': # return -1.0 # else: # return 0.0 #self.Algorithm.Plot("Movement", 'Actual', float(movement_score(actual))) #self.Algorithm.Plot("Movement", 'Predicted', float(movement_score(pred))) # self.Algorithm.Plot("Error", 'Mean Absolute Error', metrics.mean_absolute_error(y_test, y_pred)) # self.Algorithm.Plot("Error", 'Mean Squared Error', metrics.mean_squared_error(y_test, y_pred, squared=True)) # self.Algorithm.Plot("Error", 'Root Mean Squared Error', np.sqrt(metrics.mean_squared_error(y_test, y_pred, squared=False))) # self.Algorithm.Plot("Differences", "Actual", round(float(y_test[-1] - y_test[-2]), 3)) # self.Algorithm.Plot("Differences", "Predicted", round(float(y_pred[-1] - y_pred[-2]), 3)) # self.Algorithm.Plot("SPY", 'Actual_15', float(y1_test.iloc[-1])) # self.Algorithm.Plot("SPY", 'Pred_15', float(y_pred1[-1])) # self.Algorithm.Plot("SPY_Duration", 'Actual_15', float(y2_test.iloc[-1])) # self.Algorithm.Plot("SPY_Duration", 'Pred_15', float(y_pred2[-1])) # self.Algorithm.Plot("SPY_Direction", 'Actual_15', float(y_test_clf[-1])) # self.Algorithm.Plot("SPY_Direction", 'Pred_15', float(y_pred_clf[-1])) return y1_test.iloc[-1], y_pred1[-1], y2_test.iloc[-1], y_pred2[-1], y_test_clf[-1], y_pred_clf[-1], X['close_pct_change_p_value'].iloc[-1] def compute_indicators(df): indicator_kama = ta.momentum.KAMAIndicator(df.close, fillna=False) indicator_trix = ta.trend.TRIXIndicator(df.close, fillna=False) indicator_macd = ta.trend.MACD(df.close, fillna=False) indicator_bollinger = ta.volatility.BollingerBands(df.close, fillna=False) indicator_kelter = ta.volatility.KeltnerChannel(df.high, df.low, df.close, fillna=False) indicator_kst = ta.trend.KSTIndicator(df.close, fillna=False) indicator_aweosc = ta.momentum.AwesomeOscillatorIndicator(low=df.low, high=df.high, fillna=False) indicator_williams = ta.momentum.WilliamsRIndicator(close=df.close, low=df.low, high=df.high, fillna=False) indicator_ichimoku = ta.trend.IchimokuIndicator(low=df.low, high=df.high, fillna=False) indicator_truetrange = ta.volatility.AverageTrueRange(close=df.close, low=df.low, high=df.high, fillna=False) indicator_rsi = ta.momentum.RSIIndicator(close=df.close, fillna=False) indicator_vwap = ta.volume.VolumeWeightedAveragePrice(high=df.high, low=df.low, close=df.close, volume=df.volume, fillna=False) indicator_list = [indicator_kama, indicator_trix, indicator_macd, indicator_bollinger, indicator_kelter, indicator_kst, indicator_aweosc, indicator_williams, indicator_ichimoku, indicator_truetrange, indicator_rsi, indicator_vwap] for indicator in indicator_list: for _subfunction in inspect.getmembers(indicator): if (str(type(_subfunction[1])) == "<class 'method'>") & (str(_subfunction[0]) not in ['__init__', '_check_fillna', '_run']): col_name = str(_subfunction[0]) if col_name not in df.columns: vals = _subfunction[1]().values df[col_name] = vals return df def compare_with_previous(x): if x > 0: return 'Up' elif x < 0: return 'Down' else: return 'Chop' # Define a function to calculate the slope def calculate_slope(series): x = np.array(series.index) y = series.values slope = (len(series) * np.sum(x * y) - np.sum(x) * np.sum(y)) / (len(series) * np.sum(x**2) - np.sum(x)**2) return slope def calc_fib_levels(x, level): height = x.max() - x.min() fib_level = x.min() + (height * level) return fib_level def add_features(df_x): df_x = df_x.sort_values('time', ascending = True) df_x['time'] = pd.to_datetime(df_x['time']) df_x['date'] = pd.to_datetime(df_x['time']).dt.date df_x['close_diff'] = df_x['close'].diff(periods=2) df_x['close_pct_change'] = df_x.close.pct_change() * 100 df_x['close_pct_change_slope'] = df_x['close_pct_change'].rolling(window=2).apply(calculate_slope, raw=False) df_x['close_pct_change_p_value'] = df_x['close_pct_change'].rolling(window=20).apply(lambda x: ttest_1samp(x.iloc[:-1], x.iloc[-1])[-1]) df_x['Price_Direction'] = df_x['close_pct_change'].apply(lambda x: compare_with_previous(x))#df_x['close'].combine(df_x['close'].shift(-1), compare_with_previous) for col in ['open', 'high', 'low']: df_x[col+'_Fib_Level_786'] = df_x[col].rolling(window = 20).apply(lambda x: calc_fib_levels(x, level = 0.786)) df_x[col+'_Fib_Level_618'] = df_x[col].rolling(window = 20).apply(lambda x: calc_fib_levels(x, level = 0.618)) df_x[col+'_Fib_Level_500'] = df_x[col].rolling(window = 20).apply(lambda x: calc_fib_levels(x, level = 0.5)) df_x[col+'_Fib_Level_382'] = df_x[col].rolling(window = 20).apply(lambda x: calc_fib_levels(x, level = 0.382)) df_x[col+'_Fib_Level_236'] = df_x[col].rolling(window = 20).apply(lambda x: calc_fib_levels(x, level = 0.236)) curr = None count = 0 count_list = list() for x, y in zip(df_x['Price_Direction'], df_x['close_pct_change']): y = abs(y) if curr is None: curr = x if (curr == x) & (y >= 0.00005): count += 1 else: curr = x count = 0 count_list.append(count) def reverse_sublists_with_values_greater_than_zero(input_list): start_idx = None for i in range(len(input_list)): if input_list[i] > 0 and start_idx is None: start_idx = i elif input_list[i] == 0 and start_idx is not None: input_list[start_idx:i] = input_list[start_idx:i][::-1] start_idx = None # Handle the case where the last sublist extends to the end if start_idx is not None: input_list[start_idx:] = input_list[start_idx:][::-1] return input_list df_x['Price_Movement_Duration'] = reverse_sublists_with_values_greater_than_zero(count_list) df_x['Price_Movement_Duration'] = df_x['Price_Movement_Duration'].astype(int) #df_x['Price_Movement_Duration_p_value'] = df_x['Price_Movement_Duration'].rolling(window=20).apply(lambda x: ttest_1samp(x.iloc[:-1], x.iloc[-1])[-1]) percentile_075 = df_x['close_pct_change'].quantile(0.075) percentile_925 = df_x['close_pct_change'].quantile(0.925) def mod_direction(row): if (row[0] >= percentile_075) and (row[0] <= percentile_925) and (row[1] <= 1): return 'Chop' else: return row[2] df_x['Price_Direction'] = df_x[['close_pct_change', 'Price_Movement_Duration', 'Price_Direction']].apply(lambda x: mod_direction(x), axis = 1) return df_x def mod_duration(_df): # Iterate over rows using itertuples and compare current row with the next row for i, (current_row, prev_row) in enumerate(zip(_df[::-1].itertuples(index=False), _df[::-1].shift(-1).itertuples(index=False))): if i == 0: continue current_value, current_dur = getattr(current_row, 'Price_Direction'), getattr(current_row, 'Price_Movement_Duration') prev_value, prev_dur = getattr(prev_row, 'Price_Direction'), getattr(prev_row, 'Price_Movement_Duration') # if direction is the same and previous movement duration is 0, change previous movement duration to current movement duration to + 1 if (current_value == prev_value) & (prev_dur == 0): new_value = current_dur + 1 _df.at[_df.index[-(i+2)], 'Price_Movement_Duration'] = new_value return _df
#region imports from AlgorithmImports import * #endregion # Your New Python File class SymbolData(object): def __init__(self, symbol, barPeriod, windowSize): self.Symbol = symbol # The period used when population the Bars rolling window self.BarPeriod = barPeriod # A rolling window of data, data needs to be pumped into Bars by using Bars.Update( tradeBar ) and can be accessed like: # mySymbolData.Bars[0] - most first recent piece of data # mySymbolData.Bars[5] - the sixth most recent piece of data (zero based indexing) self.Bars = RollingWindow[IBaseDataBar](windowSize) self.QuoteBars = RollingWindow[QuoteBar](windowSize) self.MarketProfile = dict() self.MarketProfile['time'] = RollingWindow[DateTime](windowSize) self.MarketProfile["vp"] = RollingWindow[float](windowSize) self.MarketProfile["vp_profilehigh"] = RollingWindow[float](windowSize) self.MarketProfile["vp_profilelow"] = RollingWindow[float](windowSize) self.MarketProfile["vp_pocprice"] = RollingWindow[float](windowSize) self.MarketProfile["vp_pocvolume"] = RollingWindow[float](windowSize) self.MarketProfile["vp_valueareavolume"] = RollingWindow[float](windowSize) self.MarketProfile["vp_valueareahigh"] = RollingWindow[float](windowSize) self.MarketProfile["vp_valuearealow"] = RollingWindow[float](windowSize) # Returns true if all the data in this instance is ready (indicators, rolling windows, ect...) def IsReady(self): return self.Bars.IsReady # Returns true if the most recent trade bar time matches the current time minus the bar's period, this # indicates that update was just called on this instance def WasJustUpdated(self, current): return self.Bars.Count > 0 and self.Bars[0].Time == current - self.BarPeriod
from AlgorithmImports import * from System import * from QuantConnect import * from QuantConnect.Algorithm import * from QuantConnect.Indicators import * from QuantConnect.Data.Market import TradeBar from QuantConnect.Indicators.CandlestickPatterns import * import inspect import pandas as pd import numpy as np from scipy import stats from scipy.signal import argrelextrema import statistics from operator import itemgetter from functools import reduce from FilterIndicators import * from SmartRollingWindow import * from pykalman import KalmanFilter from levels import * from market_profile import Market_Profile class SymbolData(object): def __init__(self, algorithm, symbol, *args, **kwargs): super().__init__() self.Symbol = symbol self.resolution = Resolution.Daily self.lookback = 20 self.ceiling = 30 self.floor = 10 self.hh_all = False self.ll_all = False self.hh_sum = False self.ll_sum = False self.breakout = False self.breakdown = False self.fir = 0.00 self.EXCL = 21 self.scale = 0.00 self.tol = 0.98 self.is_uptrend = False self.is_downtrend = False self.volatility = 0.00 self.tolerance = 0.98 self.vwap = IntradayVwap() self.vol_slope = 0.00 self.roc_slope = 0.00 self.median_roc = 0.00 self.median_vol = 0.00 # Support Resistance self.long = False self.short = False self.Daily = RollingWindow[TradeBar](21) ### Market Profile self.market_profile = Market_Profile() self.mp_uptrend = False self.mp_downtrend = False self.mp_entry_signal = False self.mp_exit_signal = False self.poc_Win = RollingWindow[float](5) self.pocWin = SmartRollingWindow("float", 5) self.val_Win = RollingWindow[float](5) self.valWin = SmartRollingWindow("float", 5) self.vah_Win = RollingWindow[float](5) self.vahWin = SmartRollingWindow("float", 5) self.price_Win = RollingWindow[float](5) self.priceWin = SmartRollingWindow("float", 5) self.medpri_Win = RollingWindow[float](5) self.medpriWin = SmartRollingWindow("float", 5) self.vwap_fst = VolumeWeightedAveragePriceIndicator(50) self.vwap_med = VolumeWeightedAveragePriceIndicator(100) self.vwap_mlng = VolumeWeightedAveragePriceIndicator(150) self.vwap_lng = VolumeWeightedAveragePriceIndicator(200) self.vwap_fst_Win = RollingWindow[float](5) self.vwap_fstWin = SmartRollingWindow("float", 5) self.vwap_med_Win = RollingWindow[float](5) self.vwap_medWin = SmartRollingWindow("float", 5) self.vwap_lng_Win = RollingWindow[float](5) self.vwap_lngWin = SmartRollingWindow("float", 5) self.dont_buy = False self.fast = RateOfChange(int(8*1.0)) self.fast_Win = RollingWindow[float](41) self.slow = RateOfChange(int(14*1.0)) self.slow_Win = RollingWindow[float](41) self.roc = RateOfChange(int(5*1.0)) self.roc_fast = RateOfChange(int(3*1.0)) self.roc_med = RateOfChange(int(8*1.0)) self.roc_long = RateOfChange(int(14*1.0)) self.vol_roc = RateOfChange(int(5*1.0)) self.vol_roc_fast = RateOfChange(int(3*1.0)) self.vol_roc_med = RateOfChange(int(8*1.0)) self.vol_roc_long = RateOfChange(int(14*1.0)) self.roc_Win = RollingWindow[float](5) self.roclen_Win = RollingWindow[float](int(5)) self.rocSum_Win = RollingWindow[float](int(5)) self.vol_Win = RollingWindow[float](5) self.prices_Win = RollingWindow[float](41) self.low_Win = RollingWindow[float](41) self.high_Win = RollingWindow[float](41) self.roc_prices_Win = RollingWindow[float](41) self.roc_prices_lev_Win = RollingWindow[float](10) self.roc_volume_Win = RollingWindow[float](41) self.stochasticMACD = Stochastic(30, 3, 3) self.macd = MovingAverageConvergenceDivergence(12, 26, 9, MovingAverageType.Exponential) self.macd_stochfast_Win = RollingWindow[float](8) self.macdStochFastWin = SmartRollingWindow("float", 5) self.macd_stochk_Win = RollingWindow[float](8) self.macdStochKWin = SmartRollingWindow("float", 5) self.macd_stochd_Win = RollingWindow[float](8) self.macdStochDWin = SmartRollingWindow("float", 5) self.macd_Win = RollingWindow[float](8) self.macd_stoch_Win = RollingWindow[float](8) self.macdHist_Win = RollingWindow[float](8) self.macdFast_Win = RollingWindow[float](8) self.macdSlow_Win = RollingWindow[float](8) self.macdSignal_Win = RollingWindow[float](8) self.macdDelta_Win = RollingWindow[float](8) self.macd_uptrend = False self.macd_downtrend = False self.stochasticRSI = Stochastic(21, 3, 3) self.rsi = RelativeStrengthIndex(14, MovingAverageType.Wilders) self.rsi_Win = RollingWindow[float](8) self.rsiWin = SmartRollingWindow("float", 5) self.rsiFastStoch_Win = RollingWindow[float](8) self.rsiFastStochWin = SmartRollingWindow("float", 5) self.rsiStochD_Win = RollingWindow[float](5) self.rsiStochKWin = SmartRollingWindow("float", 5) self.rsiStochK_Win = RollingWindow[float](5) self.rsiStochDWin = SmartRollingWindow("float", 5) self.rsi_uptrend = False self.rsi_downtrend = False self.williamsPR = WilliamsPercentR(14) self.williamsPR_slow = WilliamsPercentR(21) self.williamsWindow = RollingWindow[float](5) self.williams_median_roc = 0.00 self.williams_median = 0.00 self.vpnIndicator = False self.vpnScale = 0.00 self.vpn_period = 10 self.atr = AverageTrueRange(self.vpn_period, MovingAverageType.Exponential) self.vpn_vol_Win = RollingWindow[float](self.vpn_period) self.vpn_hlc_Win = RollingWindow[float](self.vpn_period) self.vpn_list = RollingWindow[float](6) self.stochasticTrix = Stochastic(21, 3, 3) self.trix = Trix(9) self.trix_slow = Trix(18) self.trixFastStoch_Win = RollingWindow[float](int(5)) self.trixStochFastWin = SmartRollingWindow("float", 5) self.trixStochK_Win = RollingWindow[float](int(5)) self.trixStochKWin = SmartRollingWindow("float", 5) self.trixStochD_Win = RollingWindow[float](int(5)) self.trixStochDWin = SmartRollingWindow("float", 5) self.trix_uptrend = False self.trix_downtrend = False self.rocSignal_quick = IndicatorExtensions.Over(self.roc_fast, self.roc_med) self.volSignal_quick = IndicatorExtensions.Over(self.vol_roc_fast, self.vol_roc_med) self.rocSignal_fast = IndicatorExtensions.Over(self.roc_fast, self.roc) self.volSignal_fast = IndicatorExtensions.Over(self.vol_roc_fast, self.vol_roc) self.rocSignal_med = IndicatorExtensions.Over(self.roc, self.roc_med) self.volSignal_med = IndicatorExtensions.Over(self.vol_roc, self.vol_roc_med) self.rocSignal_long = IndicatorExtensions.Over(self.roc_med, self.roc_long) self.volSignal_long = IndicatorExtensions.Over(self.vol_roc_med, self.vol_roc_long) self.rocvolSignal_Win = RollingWindow[float](5) self.rocvolSignal_median = 0.00 self.roc_vol_signal_up = False self.roc_vol_signal_down = False self.kalFilter = KalmanFilterIndicator(name='Kalman', period=5, selector=Field.Close) self.kalFilterLow = KalmanFilterIndicator(name='Kalman', period=5, selector=Field.Low) self.kalFilterHigh = KalmanFilterIndicator(name='Kalman', period=5, selector=Field.High) self.kalWindow = SmartRollingWindow("float", 2) self.kalWindowLow = SmartRollingWindow("float", 2) self.kalWindowHigh = SmartRollingWindow("float", 2) self.priceWindow = SmartRollingWindow("float", 2) self.priceWindowLow = SmartRollingWindow("float", 2) self.priceWindowHigh = SmartRollingWindow("float", 2) self.exit_signal = False self.entry_signal = False # Candles self.cndl_abandonedbaby = AbandonedBaby() self.cndl_advanceblock = AdvanceBlock() self.cndl_belthold = BeltHold() self.cndl_breakway = Breakaway() self.cndl_closingmarubozu = ClosingMarubozu() self.cndl_concealedbabyswallow = ConcealedBabySwallow() self.cndl_counterattack = Counterattack() self.cndl_darkcloudcover = DarkCloudCover() self.cndl_doji = Doji() self.cndl_dojistar = DojiStar() self.cndl_dragonflydoji = DragonflyDoji() self.cndl_engulfing = Engulfing() self.cndl_eveningdojistar = EveningDojiStar() self.cndl_eveningstar = EveningStar() self.cndl_gapsidebysidewhite = GapSideBySideWhite() self.cndl_gravestonedoji = GravestoneDoji() self.cndl_hammer = Hammer() self.cndl_hangingman = HangingMan() self.cndl_harami = Harami() self.cndl_haramicross = HaramiCross() self.cndl_highwavecandle = HighWaveCandle() self.cndl_hikkake = Hikkake() self.cndl_hikkakemodified = HikkakeModified() self.cndl_homingpigeon = HomingPigeon() self.cndl_identicalthreecrows = IdenticalThreeCrows() self.cndl_inneck = InNeck() self.cndl_invertedhammer = InvertedHammer() self.cndl_kicking = Kicking() self.cndl_kickingbylength = KickingByLength() self.cndl_ladderbottom = LadderBottom() self.cndl_longleggeddoji = LongLeggedDoji() self.cndl_longlinecandle = LongLineCandle() self.cndl_marubozu = Marubozu() self.cndl_mathold = MatHold() self.cndl_matchinglow = MatchingLow() self.cndl_morningdojistar = MorningDojiStar() self.cndl_morningstar = MorningStar() self.cndl_onneck = OnNeck() self.cndl_pierce = Piercing() self.cndl_rickshawman = RickshawMan() self.cndl_risefallthreemethods = RiseFallThreeMethods() self.cndl_separatinglines = SeparatingLines() self.cndl_shootingstar = ShootingStar() self.cndl_shortlinecandle = ShortLineCandle() self.cndl_spinningtop = SpinningTop() self.cndl_stalledpattern = StalledPattern() self.cndl_sticksandwich = StickSandwich() self.cndl_takuri = Takuri() self.cndl_tasukigap = TasukiGap() self.cndl_threeblackcrows = ThreeBlackCrows() self.cndl_threeinside = ThreeInside() self.cndl_threelinest = ThreeLineStrike() self.cndl_threeoutside = ThreeOutside() self.cndl_threestarsinsouth = ThreeStarsInSouth() self.cndl_threewhitesoldiers = ThreeWhiteSoldiers() self.cndl_thrusting = Thrusting() self.cndl_tristar = Tristar() self.cndl_twocrows = TwoCrows() self.cndl_uniquethreeriver = UniqueThreeRiver() self.cndl_updowngapthreemethods = UpDownGapThreeMethods() self.cndl_upsidegaptwocrows = UpsideGapTwoCrows() self.candleWin = SmartRollingWindow("float", 5) self.candleavgWindow = SmartRollingWindow("float", 2) self.candleContainer = RollingWindow[float](2) self.cndl_uptrend = False self.cndl_downtrend = False self.candlescore = 0.00 self.indicators = [self.roc, self.roc_fast, self.roc_med, self.roc_long, self.vol_roc, self.vol_roc_fast, self.vol_roc_med, self.vol_roc_long, self.vwap, self.fast, self.slow, self.macd, self.stochasticMACD, self.rsi, self.stochasticRSI, self.williamsPR, self.williamsPR_slow, self.atr, self.stochasticTrix, self.trix, self.trix_slow, self.kalFilter, self.kalFilterLow, self.kalFilterHigh] self.candles = [self.cndl_abandonedbaby, self.cndl_advanceblock, self.cndl_belthold, self.cndl_breakway, self.cndl_closingmarubozu, self.cndl_concealedbabyswallow, self.cndl_counterattack, self.cndl_darkcloudcover, self.cndl_doji, self.cndl_dojistar, self.cndl_dragonflydoji, self.cndl_engulfing, self.cndl_eveningdojistar, self.cndl_eveningstar, self.cndl_gapsidebysidewhite, self.cndl_gravestonedoji, self.cndl_hammer, self.cndl_hangingman, self.cndl_harami, self.cndl_haramicross, self.cndl_highwavecandle, self.cndl_hikkake, self.cndl_hikkakemodified, self.cndl_homingpigeon, self.cndl_identicalthreecrows, self.cndl_inneck, self.cndl_invertedhammer, self.cndl_kicking, self.cndl_kickingbylength, self.cndl_ladderbottom, self.cndl_longleggeddoji, self.cndl_longlinecandle, self.cndl_marubozu, self.cndl_mathold, self.cndl_matchinglow, self.cndl_morningdojistar, self.cndl_morningstar, self.cndl_onneck, self.cndl_pierce, self.cndl_rickshawman, self.cndl_risefallthreemethods, self.cndl_separatinglines, self.cndl_shootingstar, self.cndl_shortlinecandle, self.cndl_spinningtop, self.cndl_stalledpattern, self.cndl_sticksandwich, self.cndl_takuri, self.cndl_tasukigap, self.cndl_threeblackcrows, self.cndl_threeinside, self.cndl_threelinest, self.cndl_threeoutside, self.cndl_threestarsinsouth, self.cndl_threewhitesoldiers, self.cndl_thrusting, self.cndl_tristar, self.cndl_twocrows, self.cndl_uniquethreeriver, self.cndl_updowngapthreemethods, self.cndl_upsidegaptwocrows] self.indicators = self.indicators + self.candles for indicator in self.indicators: consolidator = algorithm.ResolveConsolidator(symbol, self.resolution) algorithm.RegisterIndicator(symbol, indicator, consolidator) # Warm up history = algorithm.History(self.Symbol, 126, self.resolution) if history.empty or 'close' not in history.columns: return for tuple in history.loc[symbol].itertuples(): tradeBar = TradeBar(tuple.Index, symbol, tuple.open, tuple.high, tuple.low, tuple.close, tuple.volume) median_price = round(float(statistics.median([tuple.open, tuple.high, tuple.low, tuple.close])), 4) self.roc.Update(tuple.Index, median_price) self.roc_fast.Update(tuple.Index,median_price) self.roc_med.Update(tuple.Index,median_price) self.roc_long.Update(tuple.Index,median_price) self.rocSignal_quick.Update(tuple.Index,median_price) self.rocSignal_fast.Update(tuple.Index,median_price) self.rocSignal_med.Update(tuple.Index,median_price) self.rocSignal_long.Update(tuple.Index,median_price) self.vol_roc.Update(tuple.Index, tuple.volume) self.vol_roc_fast.Update(tuple.Index, tuple.volume) self.vol_roc_med.Update(tuple.Index, tuple.volume) self.vol_roc_long.Update(tuple.Index, tuple.volume) self.volSignal_fast.Update(tuple.Index, tuple.volume) self.volSignal_med.Update(tuple.Index, tuple.volume) self.volSignal_long.Update(tuple.Index, tuple.volume) self.atr.Update(tradeBar) self.macd.Update(tuple.Index, tuple.close) self.fast.Update(tuple.Index, median_price) self.slow.Update(tuple.Index, median_price) self.williamsPR.Update(tradeBar) self.williamsPR_slow.Update(tradeBar) self.rsi.Update(tuple.Index, median_price) # candles self.cndl_abandonedbaby.Update(tradeBar) self.cndl_advanceblock.Update(tradeBar) self.cndl_belthold.Update(tradeBar) self.cndl_breakway.Update(tradeBar) self.cndl_closingmarubozu.Update(tradeBar) self.cndl_concealedbabyswallow.Update(tradeBar) self.cndl_counterattack.Update(tradeBar) self.cndl_darkcloudcover.Update(tradeBar) self.cndl_doji.Update(tradeBar) self.cndl_dojistar.Update(tradeBar) self.cndl_dragonflydoji.Update(tradeBar) self.cndl_engulfing.Update(tradeBar) self.cndl_eveningdojistar.Update(tradeBar) self.cndl_eveningstar.Update(tradeBar) self.cndl_gapsidebysidewhite.Update(tradeBar) self.cndl_gravestonedoji.Update(tradeBar) self.cndl_hammer.Update(tradeBar) self.cndl_hangingman.Update(tradeBar) self.cndl_harami.Update(tradeBar) self.cndl_haramicross.Update(tradeBar) self.cndl_highwavecandle.Update(tradeBar) self.cndl_hikkake.Update(tradeBar) self.cndl_hikkakemodified.Update(tradeBar) self.cndl_homingpigeon.Update(tradeBar) self.cndl_identicalthreecrows.Update(tradeBar) self.cndl_inneck.Update(tradeBar) self.cndl_invertedhammer.Update(tradeBar) self.cndl_kicking.Update(tradeBar) self.cndl_kickingbylength.Update(tradeBar) self.cndl_ladderbottom.Update(tradeBar) self.cndl_longleggeddoji.Update(tradeBar) self.cndl_longlinecandle.Update(tradeBar) self.cndl_marubozu.Update(tradeBar) self.cndl_mathold.Update(tradeBar) self.cndl_matchinglow.Update(tradeBar) self.cndl_morningdojistar.Update(tradeBar) self.cndl_morningstar.Update(tradeBar) self.cndl_onneck.Update(tradeBar) self.cndl_pierce.Update(tradeBar) self.cndl_rickshawman.Update(tradeBar) self.cndl_risefallthreemethods.Update(tradeBar) self.cndl_separatinglines.Update(tradeBar) self.cndl_shootingstar.Update(tradeBar) self.cndl_shortlinecandle.Update(tradeBar) self.cndl_spinningtop.Update(tradeBar) self.cndl_stalledpattern.Update(tradeBar) self.cndl_sticksandwich.Update(tradeBar) self.cndl_takuri.Update(tradeBar) self.cndl_tasukigap.Update(tradeBar) self.cndl_threeblackcrows.Update(tradeBar) self.cndl_threeinside.Update(tradeBar) self.cndl_threelinest.Update(tradeBar) self.cndl_threeoutside.Update(tradeBar) self.cndl_threestarsinsouth.Update(tradeBar) self.cndl_threewhitesoldiers.Update(tradeBar) self.cndl_thrusting.Update(tradeBar) self.cndl_tristar.Update(tradeBar) self.cndl_twocrows.Update(tradeBar) self.cndl_uniquethreeriver.Update(tradeBar) self.cndl_updowngapthreemethods.Update(tradeBar) self.cndl_upsidegaptwocrows.Update(tradeBar) # Support Resistance def CloseTo(x, y, delta): return abs(x-y) < delta def Next_RS(self, algorithm, symbol): s, r = [], [] price = algorithm.Securities[symbol].Price # Rounded Price to $1 s.append(round(price)) r.append(math.ceil(price)) # Rounded Price to $10 s.append(int(math.floor(price / 10.0)) * 10) # Rounded Price Up to $10 r.append(int(math.ceil(price / 10.0)) * 10) # Yesterday's OHLC Price s.append( self.Daily[0].Close) s.append( self.Daily[0].Low ) r.append( self.Daily[0].Close) r.append( self.Daily[0].High) # Append 7 day Low: s.append( min([bar.Low for bar in self.Daily]) ) r.append( max([bar.High for bar in self.Daily]) ) s = sorted(s, reverse=True) r = sorted(r) return s[0], r[0] self.Daily.Add(tradeBar) if self.Daily.IsReady: support, resistance = Next_RS(self, algorithm, symbol) price = algorithm.Securities[symbol].Price mean = self.slow.Current.Value if CloseTo(price, support, 0.10) and mean > support*self.tol: self.long = True if CloseTo(price, resistance, 0.10) and mean < resistance*self.tol: self.short = True def calc_divergence(obj): x = np.array(list(obj)) local_maxima = argrelextrema(x, np.greater)[0] local_minima = argrelextrema(x, np.less)[0] if x[-1] > x[-2]: x = np.append(x, len(x) - 1) elif x[-1] > x[-2]: x = np.append(x, len(x) - 1) hh_all = all(x[local_maxima][i] < x[local_maxima][i+1] for i in range(len(local_maxima)-1)) ll_all = all(x[local_minima][i] > x[local_minima][i+1] for i in range(len(local_minima)-1)) return hh_all, ll_all # Stochastic RSI if self.rsi.IsReady: rsi = self.rsi.Current.Value trade_bar = TradeBar(tuple.Index, symbol, rsi, rsi, rsi, rsi, 0) self.stochasticRSI.Update(trade_bar) if self.stochasticRSI.IsReady: self.rsi_Win.Add(rsi) self.rsiFastStoch_Win.Add(self.stochasticRSI.FastStoch.Current.Value) self.rsiStochK_Win.Add(self.stochasticRSI.StochK.Current.Value) self.rsiStochD_Win.Add(self.stochasticRSI.StochD.Current.Value) self.rsiWin.Add(rsi) self.rsiFastStochWin.Add(self.stochasticRSI.FastStoch.Current.Value) self.rsiStochKWin.Add(self.stochasticRSI.StochK.Current.Value) self.rsiStochDWin.Add(self.stochasticRSI.StochD.Current.Value) if self.rsi_Win.IsReady: rsi_list = list(self.rsi_Win) rsifast_list = list(self.rsiFastStoch_Win) rsistochk_list = list(self.rsiStochK_Win) rsistochd_list = list(self.rsiStochD_Win) curr_rsi, prev_rsi, last_rsi, min_rsi, max_rsi = rsi_list[-1], rsi_list[-2], rsi_list[-3], min(rsi_list), max(rsi_list) curr_fast, prev_fast, last_fast, min_fast, max_fast = rsifast_list[-1], rsifast_list[-2], rsifast_list[-3], min(rsifast_list), max(rsifast_list) curr_stochk, prev_stochk, last_stochk, min_stochk, max_stochk = rsistochk_list[-1], rsistochk_list[-2], rsistochk_list[-3], min(rsistochk_list), max(rsistochk_list) curr_stochd, prev_stochd, last_stochd, min_stochd, max_stochd = rsistochd_list[-1], rsistochd_list[-2], rsistochd_list[-3], min(rsistochd_list), max(rsistochd_list) cond1 = (curr_fast >= curr_stochk*self.tolerance) and (curr_stochk >= curr_stochd*self.tolerance) cond11 = (curr_rsi >= max_rsi*self.tolerance) and (curr_fast >= max_fast*self.tolerance) and (curr_stochk >= max_stochk*self.tolerance) and (curr_stochd >= max_stochd*self.tolerance) cond2 = (curr_rsi >= prev_rsi*self.tolerance) and (curr_fast >= prev_fast*self.tolerance) and (curr_stochk >= prev_stochk*self.tolerance) and (curr_stochd >= prev_stochd*self.tolerance) cond3 = (prev_rsi >= last_rsi*self.tolerance) and (prev_fast >= last_fast*self.tolerance) and (prev_stochk >= last_stochk*self.tolerance) and (prev_stochd >= last_stochd*self.tolerance) cond4 = (curr_fast*self.tolerance <= curr_stochk) and (curr_stochk*self.tolerance <= curr_stochd) cond41 = (min_rsi*self.tolerance <= curr_rsi) and (min_fast*self.tolerance <= curr_fast) and (min_stochk*self.tolerance <= curr_stochk) and (min_stochd*self.tolerance <= curr_stochd) cond5 = (curr_rsi*self.tolerance <= prev_rsi) and (curr_fast*self.tolerance <= prev_fast) and (curr_stochk*self.tolerance <= prev_stochk) and (curr_stochd*self.tolerance <= prev_stochd) cond6 = (prev_rsi*self.tolerance <= last_rsi) and (prev_fast*self.tolerance <= last_fast) and (prev_stochk*self.tolerance <= last_stochk) and (prev_stochd*self.tolerance <= last_stochd) hh_rsi, ll_rsi = calc_divergence(rsi_list) hh_rsifast, ll_rsifast = calc_divergence(rsifast_list) hh_rsik, ll_rsik = calc_divergence(rsistochk_list) hh_rsid, ll_rsid = calc_divergence(rsistochd_list) cond7 = hh_rsi, hh_rsifast, hh_rsik, hh_rsid cond8 = ll_rsi, ll_rsifast, ll_rsik, ll_rsid if (cond1 and cond7) and (cond2 and cond3): self.rsi_uptrend = True else: self.rsi_uptrend = False if (cond4 and cond8) and (cond5 and cond6): self.rsi_downtrend = True else: self.rsi_downtrend = False exit = self.rsiFastStochWin.crossedBelow(self.rsiWin) and self.rsiFastStochWin.crossedBelow(self.rsiStochKWin) and self.rsiStochKWin.crossedBelow(self.rsiStochDWin) entry = self.rsiFastStochWin.crossedAbove(self.rsiWin) and self.rsiFastStochWin.crossedAbove(self.rsiStochKWin) and self.rsiStochKWin.crossedAbove(self.rsiStochDWin) if algorithm.Portfolio[symbol].Invested: if exit and self.short: self.rsi_exit_signal = True else: self.rsi_exit_signal = False if not algorithm.Portfolio[symbol].Invested: if entry and self.long: self.rsi_entry_signal = True else: self.rsi_entry_signal = False # MACD Trend if self.macd.IsReady: macd = self.macd.Current.Value trade_bar = TradeBar(tuple.Index, symbol, macd, macd, macd, macd, 0) self.stochasticMACD.Update(trade_bar) if self.stochasticMACD.IsReady: macd = self.macd.Current.Value macd_fast = self.macd.Fast.Current.Value macd_slow = self.macd.Slow.Current.Value macd_hist = self.macd.Histogram.Current.Value signal = self.macd.Signal.Current.Value delta = (macd - signal)/macd_fast macd_stoch = self.stochasticMACD.Current.Value macd_stochfast = self.stochasticMACD.FastStoch.Current.Value macd_stochk = self.stochasticMACD.StochK.Current.Value macd_stochd = self.stochasticMACD.StochD.Current.Value self.macd_Win.Add(macd) self.macdHist_Win.Add(macd_fast) self.macdFast_Win.Add(macd_hist) self.macdSlow_Win.Add(macd_slow) self.macdSignal_Win.Add(signal) self.macdDelta_Win.Add(delta) self.macd_stoch_Win.Add(macd_stoch) self.macd_stochfast_Win.Add(macd_stochfast) self.macd_stochk_Win.Add(macd_stochk) self.macd_stochd_Win.Add(macd_stochd) self.macdStochFastWin.Add(macd_stochfast) self.macdStochKWin.Add(macd_stochk) self.macdStochDWin.Add(macd_stochd) if self.macd_Win.IsReady: macd_list = list(self.macd_Win) macdhist_list = list(self.macdHist_Win) macdfast_list = list(self.macdFast_Win) macdslow_list = list(self.macdSlow_Win) macdsignal_list = list(self.macdSignal_Win) macddelta_list = list(self.macdDelta_Win) macdstoch_list = list(self.macd_stoch_Win) macdstochfast_list = list(self.macd_stochfast_Win) macdstochk_list = list(self.macd_stochk_Win) macdstochd_list = list(self.macd_stochd_Win) curr_macd, prev_macd, last_macd, min_macd, max_macd = macd_list[-1], macd_list[-2], macd_list[-3], min(macd_list), max(macd_list) curr_macd_fast, prev_macd_fast, last_macd_fast, min_macd_fast, max_macd_fast = macdfast_list[-1], macdfast_list[-2], macdfast_list[-3], min(macdfast_list), max(macdfast_list) curr_macd_slow, prev_macd_slow, last_macd_slow, min_macd_slow, max_macd_slow = macdslow_list[-1], macdslow_list[-2], macdslow_list[-3], min(macdslow_list), max(macdslow_list) curr_macd_hist, prev_macd_hist, last_macd_hist, min_macd_hist, max_macd_hist = macdhist_list[-1], macdhist_list[-2], macdhist_list[-3], min(macdhist_list), max(macdhist_list) curr_signal, prev_signal, last_signal, min_signal, max_signal = macdsignal_list[-1], macdsignal_list[-2], macdsignal_list[-3], min(macdsignal_list), max(macdsignal_list) curr_delta, prev_delta, last_delta, min_delta, max_delta = macddelta_list[-1], macddelta_list[-2], macddelta_list[-3], min(macddelta_list), max(macddelta_list) curr_macdstoch, prev_macdstoch, last_macdstoch, min_macdstoch, max_macdstoch = macdstoch_list[-1], macdstoch_list[-2], macdstoch_list[3], min(macdstoch_list), max(macdstoch_list) curr_macdstochfast, prev_macdstochfast, last_macdstochfast, min_macdstochfast, max_macdstochfast = macdstochfast_list[-1], macdstochfast_list[-2], macdstochfast_list[-3], min(macdstochfast_list), max(macdstochfast_list) curr_macdstochk, prev_macdstochk, last_macdstochk, min_macdstochk, max_macdstochk = macdstochk_list[-1], macdstochk_list[-2], macdstochk_list[-3], min(macdstochk_list), max(macdstochk_list) curr_macdstochd, prev_macdstochd, last_macdstochd, min_macdstochd, max_macdstochd = macdstochd_list[-1], macdstochd_list[-2], macdstochd_list[-3], min(macdstochd_list), max(macdstochd_list) cond1 = ((curr_macd_hist-curr_delta)>=0.0025) and (curr_macd >= curr_signal*self.tolerance) and (curr_macdstochfast >= curr_macdstochk*self.tolerance) and (curr_macdstochk >= curr_macdstochd*self.tolerance) cond11 = (curr_macd >= max_macd*self.tolerance) and (curr_macdstochfast >= max_macdstochfast*self.tolerance) and (curr_macdstochk >= max_macdstochk*self.tolerance) and (curr_macdstochd >= max_macdstochd*self.tolerance) cond2 = (curr_macd >= prev_macd*self.tolerance) and (curr_macd_fast >= prev_macd_fast*self.tolerance) and (curr_macd_hist >= prev_macd_hist*self.tolerance) and (curr_signal >= prev_signal*self.tolerance) cond3 = (prev_macd >= last_macd*self.tolerance) and (prev_macd_fast >= last_macd_fast*self.tolerance) and (prev_macd_hist >= last_macd_hist*self.tolerance) and (prev_signal >= last_signal*self.tolerance) cond4 = ((curr_macd_hist-curr_delta) <= -0.0025) and (curr_macd*self.tolerance <= curr_signal) and (curr_macdstochfast*self.tolerance <= curr_macdstochk) and (curr_macdstochk*self.tolerance <= curr_macdstochd) cond41 = (min_macd*self.tolerance <= curr_macd) and (min_macdstochfast*self.tolerance <= curr_macdstochfast) and (min_macdstochk*self.tolerance <= curr_macdstochk) and (min_macdstochd*self.tolerance <= curr_macdstochd) cond5 = (curr_macd*self.tolerance <= prev_macd) and (curr_macd_fast*self.tolerance <= prev_macd_fast) and (curr_macd_hist*self.tolerance <= prev_macd_hist) and (curr_signal*self.tolerance <= prev_signal) cond6 = (prev_macd*self.tolerance <= last_macd) and (prev_macd_fast*self.tolerance <= last_macd_fast) and (prev_macd_hist*self.tolerance <= last_macd_hist) and (prev_signal*self.tolerance <= last_signal) hh_macd, ll_macd = calc_divergence(macd_list) hh_macdhist, ll_macdhist = calc_divergence(macdhist_list) hh_macdfast, ll_macdfast = calc_divergence(macdfast_list) hh_macdslow, ll_macdslow = calc_divergence(macdslow_list) hh_macdsignal, ll_macdsignal = calc_divergence(macdsignal_list) hh_macdstochfast, ll_macdstochfast = calc_divergence(macdstochfast_list) hh_macdstochk, ll_macdstochk = calc_divergence(macdstochk_list) hh_macdstochd, ll_macdstochd = calc_divergence(macdstochd_list) cond7 = hh_macd, hh_macdhist, hh_macdfast, hh_macdslow, hh_macdsignal, hh_macdstochfast, hh_macdstochk, hh_macdstochd cond8 = ll_macd, ll_macdhist, ll_macdfast, ll_macdslow, ll_macdsignal, ll_macdstochfast, ll_macdstochk, ll_macdstochd if (cond1 and cond7) and (cond2 and cond3): self.macd_uptrend = True else: self.macd_uptrend = False if (cond4 and cond8) and (cond5 and cond6): self.macd_downtrend = True else: self.macd_downtrend = False exit = self.macdStochFastWin.crossedBelow(self.macdStochKWin) and self.macdStochKWin.crossedBelow(self.macdStochDWin) entry = self.macdStochFastWin.crossedAbove(self.macdStochKWin) and self.macdStochKWin.crossedAbove(self.macdStochDWin) if algorithm.Portfolio[symbol].Invested: if exit and self.short: self.macd_exit_signal = True else: self.macd_exit_signal = False if not algorithm.Portfolio[symbol].Invested: if entry and self.long: self.macd_entry_signal = True else: self.macd_entry_signal = False def roc_calc(obj): obj_list = list(obj) output_list = list() for i in range(-1, -len(obj_list)+1, -1): if obj_list[i-1] != 0: val = round((obj_list[i] - obj_list[i-1])/obj_list[i-1], 4) else: val = 0 output_list.append(val) return output_list self.roc_Win.Add(round(float(statistics.median([self.roc.Current.Value, self.roc_fast.Current.Value, self.roc_med.Current.Value, self.roc_long.Current.Value])), 4)) if self.roc_Win.IsReady: val = statistics.median(roc_calc(self.roc_Win)) roc_sum, roc_len = sum(list(self.roc_Win)), len(list(self.roc_Win)) self.roc_slope = round(float(roc_sum)/roc_len, 4) def calc_divergence(obj): x = np.array(list(obj)) local_maxima = argrelextrema(x, np.greater)[0] local_minima = argrelextrema(x, np.less)[0] if x[-1] > x[-2]: x = np.append(x, len(x) - 1) elif x[-1] > x[-2]: x = np.append(x, len(x) - 1) hh_all = all(x[local_maxima][i] < x[local_maxima][i+1] for i in range(len(local_maxima)-1)) ll_all = all(x[local_minima][i] > x[local_minima][i+1] for i in range(len(local_minima)-1)) return hh_all, ll_all self.rocSum_Win.Add(round(float(sum([self.roc.Current.Value, self.roc_fast.Current.Value, self.roc_med.Current.Value, self.roc_long.Current.Value])), 4)) self.roclen_Win.Add(round(float(statistics.median([self.roc.Current.Value, self.roc_fast.Current.Value, self.roc_med.Current.Value, self.roc_long.Current.Value])), 4)) if self.rocSum_Win.IsReady: self.hh_all, self.ll_all = calc_divergence(self.roclen_Win) self.hh_sum, self.ll_sum = calc_divergence(self.rocSum_Win) self.vol_Win.Add(round(float(statistics.median([self.vol_roc.Current.Value, self.vol_roc_fast.Current.Value, self.vol_roc_med.Current.Value, self.vol_roc_long.Current.Value])), 4)) if self.vol_Win.IsReady: val = statistics.median(roc_calc(self.vol_Win)) vol_sum, vol_len = sum(list(self.vol_Win)), len(list(self.vol_Win)) self.vol_slope = round(float(vol_sum)/vol_len, 4) self.roc_prices_Win.Add(round(statistics.median([self.roc.Current.Value, self.roc_fast.Current.Value, self.roc_med.Current.Value, self.roc_long.Current.Value]), 4)) self.roc_prices_lev_Win.Add(round(statistics.median([self.roc.Current.Value, self.roc_fast.Current.Value, self.roc_med.Current.Value]), 4)) self.roc_volume_Win.Add(round(statistics.median([self.vol_roc.Current.Value, self.vol_roc_fast.Current.Value, self.vol_roc_med.Current.Value, self.vol_roc_long.Current.Value]), 4)) self.prices_Win.Add(tuple.close) if self.prices_Win.IsReady and self.roc_prices_Win.IsReady: prices = list(self.roc_prices_Win) volumes = list(self.roc_volume_Win) frames = [i for i in range(-2, -21, -2)] frames_ = [i for i in range(-1, -21, -1)] prices_lev = list(self.roc_prices_lev_Win) _frames = [i for i in range(-1, -3, -1)] v1 = round(statistics.median([round(float(prices[i] - prices[i-5]/ prices[i-5]), 4) if prices[i-5] != 0 else 0 for i in frames]), 4) v11 = round(statistics.median([round(float(prices[i] - prices[i-5]/ prices[i-5]), 4) if prices[i-5] != 0 else 0 for i in frames_]), 4) v1_mom = round(statistics.median([round(float(prices_lev[i] - prices_lev[i-1]/ abs(abs(i)+(i-1))), 4) if abs(abs(i)+(i-1)) != 0 else 0 for i in _frames]), 4) self.median_roc = v1 if (v1 > v11) else -1 self.median_roc_momentum = v1_mom self.median_vol = round(statistics.median([round(float(volumes[i] - volumes[i-5]/ volumes[i-5]), 4) if volumes[i-5] != 0 else 0 for i in frames]), 4) C = list(self.prices_Win) avg = sum(list(self.prices_Win))/len(list(self.prices_Win)) self.volatility = float(np.sqrt(252)*reduce(lambda a,b:a+abs(avg-b),C,0)/len(C))/C[-1] rocSignal_lst = [self.rocSignal_quick.Current.Value, self.rocSignal_fast.Current.Value, self.rocSignal_med.Current.Value, self.rocSignal_long.Current.Value] volSignal_lst = [self.volSignal_quick.Current.Value, self.volSignal_fast.Current.Value, self.volSignal_med.Current.Value, self.volSignal_long.Current.Value] rocsignal_up = all(x > 0.0 for x in rocSignal_lst) rocsignal_down = all(x < 0.0 for x in rocSignal_lst) volsignal = all(x > 0.0 for x in volSignal_lst) self.roc_vol_signal_up = rocsignal_up and volsignal self.roc_vol_signal_down = rocsignal_down and volsignal self.williamsWindow.Add(round(statistics.median([self.williamsPR.Current.Value, self.williamsPR_slow.Current.Value]), 4)) if self.williamsWindow.IsReady: williams = list(self.williamsWindow) w_length = len(williams) frames = [i for i in range(-1, (w_length*-1)+1, -1)] self.williams_median_roc = round(statistics.median([round(float(williams[i] - williams[i-1]/ williams[i-1]), 4) if williams[i-1] != 0 else 0 for i in frames]), 4) self.williams_median = round(statistics.median(williams), 4) self.high_Win.Add(tuple.high) self.low_Win.Add(tuple.low) if self.high_Win.IsReady and self.low_Win.IsReady and self.prices_Win.IsReady: close = list(self.prices_Win) todayvol = np.std(close[1:31]) yesterdayvol = np.std(close[0:30]) deltavol = (todayvol - yesterdayvol) / todayvol self.lookback = round(self.lookback * (1 + deltavol)) # Account for upper/lower limit of lockback length if self.lookback > self.ceiling: self.lookback = self.ceiling elif self.lookback < self.floor: self.lookback = self.floor high = list(self.high_Win) low = list(self.low_Win) # Buy in case of breakout breakout_condition1 = (algorithm.Securities[symbol].Close >= max(high[:-1])) if breakout_condition1: self.breakout = True breakdown_condition1 = (algorithm.Securities[symbol].Close >= min(low[:-1])) if breakdown_condition1: self.breakdown = True fast = self.fast.Current.Value slow = self.slow.Current.Value median_roc = round(statistics.median([self.roc.Current.Value, self.roc_fast.Current.Value, self.roc_med.Current.Value, self.roc_long.Current.Value]), 4) self.fast_Win.Add(fast) self.slow_Win.Add(slow) self.is_uptrend = (((slow) >= (median_roc*self.tolerance)) and (tuple.close >= (median_roc*self.tolerance))) self.is_downtrend = (((slow*self.tolerance) <= (median_roc)) and (tuple.close*self.tolerance <= (median_roc))) if self.is_uptrend or self.fast_Win.IsReady: # triangle formula # base * height * 0.5 curr_fast, curr_slow = fast, slow prev_fast, prev_slow = min(list(self.fast_Win)), min(list(self.slow_Win)) self.scale = round(float(fast - slow) / ((fast+slow)/2.0), 4) else: self.scale = 0.00 self.kalWindow.Add(self.kalFilter.Value) self.kalWindowLow.Add(self.kalFilterLow.Value) self.kalWindowHigh.Add(self.kalFilterHigh.Value) self.priceWindow.Add(statistics.median([algorithm.Securities[symbol].Open, algorithm.Securities[symbol].High, algorithm.Securities[symbol].Low, algorithm.Securities[symbol].Close])) self.priceWindowLow.Add(algorithm.Securities[symbol].Low) self.priceWindowHigh.Add(algorithm.Securities[symbol].High) if self.kalFilterLow.IsReady: exit = self.priceWindowLow.crossedBelow(self.kalWindowLow) and self.priceWindowHigh.crossedBelow(self.kalWindowHigh) and self.priceWindow.crossedBelow(self.kalWindow) entry = self.priceWindowLow.crossedAbove(self.kalWindowLow) and self.priceWindowHigh.crossedAbove(self.kalWindowHigh) and self.priceWindow.crossedAbove(self.kalWindow) if algorithm.Portfolio[symbol].Invested: # exit if exit is True: self.exit_signal = True else: self.exit_signal = False elif not algorithm.Portfolio[symbol].Invested: # entry if entry is True: self.entry_signal = True else: self.entry_signal = False # VPN Indicator iATR = 0.1 ema_smooth = 3 vp = 0.0 vn = 0.0 vtot = 0.0 dist = self.atr.Current.Value * iATR self.vpn_vol_Win.Add(tuple.volume) self.vpn_hlc_Win.Add(round(statistics.median([tuple.high, tuple.low, tuple.close]), 4)) if self.vpn_vol_Win.IsReady and self.vpn_hlc_Win.IsReady: vpn_vol_Win = list(self.vpn_vol_Win) vpn_hlc_Win = list(self.vpn_hlc_Win) for i in range(-1, -self.vpn_period, -1): if (vpn_hlc_Win[i] >= vpn_hlc_Win[i-1] + dist): vp += vpn_vol_Win[i] elif (vpn_hlc_Win[i] <= vpn_hlc_Win[i-1] - dist): vn += vpn_vol_Win[i] vtot += vpn_vol_Win[i] vpn_val = (((vp - vn) / (vtot/self.vpn_period)) / self.vpn_period) * 100 self.vpn_list.Add(vpn_val) if self.vpn_list.IsReady: vpn_ema = pd.DataFrame(list(self.vpn_list)).ewm(span=ema_smooth, adjust=False).mean().iloc[-1][0] vpn_scale = self.vpn_list[-1] vpnIndicator = ((vpn_scale) >= (vpn_ema*self.tolerance)) and ((vpn_scale) >= (self.vpn_list[-2]*self.tolerance)) self.vpnIndicator = vpnIndicator if self.vpnIndicator: curr_vpn, curr_vpn_ema = vpn_scale, vpn_ema low_vpn, low_vpn_ema = min(self.vpn_list), min(pd.DataFrame(list(self.vpn_list)).ewm(span=ema_smooth, adjust=False).mean().iloc[-1]) vpnScale = round(float(curr_vpn - curr_vpn_ema) / ((low_vpn + low_vpn_ema) / 2.0), 4) self.vpnScale = vpnScale else: self.vpnScale = 0.00 # Candles cndl_coef = float(sum([x.Current.Value for x in self.candles])) self.candleContainer.Add(cndl_coef) self.candleWin.Add(cndl_coef) if self.candleContainer.IsReady and self.candleWin.IsReady: cndl_avg = statistics.median(list(self.candleContainer)) self.candleavgWin.Add(cndl_avg) if self.candleWin.IsReady and self.candleavgWin.IsReady: exit = self.candleWin.crossedBelow(self.candleavgWin) entry = self.candleWin.crossedAbove(self.candleavgWin) if algorithm.Portfolio[symbol].Invested: if exit and self.short: self.cndl_downtrend = True if not algorithm.Portfolio[symbol].Invested: if entry and self.long: self.cndl_uptrend = True # Price is Favorable if (algorithm.Securities[symbol].BidPrice < self.VWAP): self.PriceIsFavorable = True elif (algorithm.Securities[symbol].AskPrice > self.VWAP): self.PriceIsFavorable = True else: self.PriceIsFavorable = False # Market Profile if self.vwap_lng.IsReady: self.market_profile.CalcMarketProfile(algorithm, 21, [symbol]) a, val, vah, d = self.market_profile.GetMarketProfile(algorithm, symbol) poc = float(max(a, key=a.get)) self.poc_Win.Add(poc) self.pocWin.Add(poc) self.val_Win.Add(val) self.valWin.Add(val) self.vah_Win.Add(vah) self.vahWin.Add(vah) self.price_Win.Add(algorithm.Securities[symbol].Price) self.priceWin.Add(algorithm.Securities[symbol].Price) self.medpri_Win.Add(median_price) self.medpriWin.Add(median_price) mp_fst = self.vwap_fst.Current.Value mp_med = self.vwap_med.Current.Value mp_lng = self.vwap_lng.Current.Value self.vwap_fst_Win.Add(mp_fst) self.vwap_fstWin.Add(mp_fst) self.vwap_med_Win.Add(mp_med) self.vwap_medWin.Add(mp_med) self.vwap_lng_Win.Add(mp_lng) self.vwap_lngWin.Add(mp_lng) if self.poc_Win.IsReady: poc_lst = list(self.poc_Win) val_lst = list(self.val_Win) vah_lst = list(self.vah_Win) pri_lst = list(self.price_Win) medp_lst = list(self.medpri_Win) fst_lst = list(self.vwap_fst_Win) med_lst = list(self.vwap_med_Win) lng_lst = list(self.vwap_lng_Win) cur_poc, pre_poc, lst_poc = poc_lst[-1], poc_lst[-2], poc_lst[-3] cur_val, pre_val, lst_val = val_lst[-1], val_lst[-2], val_lst[-3] cur_vah, pre_vah, lst_vah = vah_lst[-1], vah_lst[-2], vah_lst[-3] cur_pri, pre_pri, lst_pri = pri_lst[-1], pri_lst[-2], pri_lst[-3] cur_medp, pre_medp, lst_medp = medp_lst[-1], medp_lst[-2], medp_lst[-3] cur_fst, pre_fst, lst_fst = fst_lst[-1], fst_lst[-2], fst_lst[-3] cur_med, pre_med, lst_med = med_lst[-1], med_lst[-2], med_lst[-3] cur_lng, pre_lng, lst_lng = lng_lst[-1], lng_lst[-2], lng_lst[-3] cond1 = (cur_pri >= cur_poc*self.tol) and (cur_pri >= cur_medp*self.tol) and (cur_fst >= cur_med*self.tol) and (cur_med >= cur_lng*self.tol) cond2 = (cur_pri >= pre_pri*self.tol) and (cur_medp >= pre_medp*self.tol) and (cur_poc >= pre_poc*self.tol) and (cur_val >= pre_val*self.tol) and (cur_vah >= pre_vah*self.tol) and (cur_fst >= pre_fst*self.tol) and (cur_med >= pre_med*self.tol) and (cur_lng >= pre_lng*self.tol) cond3 = (pre_pri >= lst_pri*self.tol) and (pre_medp >= lst_medp*self.tol) and (pre_poc >= lst_poc*self.tol) and (pre_val >= lst_val*self.tol) and (pre_vah >= lst_vah*self.tol) and (pre_fst >= lst_fst*self.tol) and (pre_med >= lst_med*self.tol) and (pre_lng >= lst_lng*self.tol) cond4 = (cur_pri <= cur_poc*self.tol) and (cur_pri <= cur_medp*self.tol) and (cur_fst <= cur_med*self.tol) and (cur_med <= cur_lng*self.tol) cond5 = (cur_pri <= pre_pri*self.tol) and (cur_medp <= pre_medp*self.tol) and (cur_poc <= pre_poc*self.tol) and (cur_val <= pre_val*self.tol) and (cur_vah <= pre_vah*self.tol) and (cur_fst <= pre_fst*self.tol) and (cur_med <= pre_med*self.tol) and (cur_lng <= pre_lng*self.tol) cond6 = (pre_pri <= lst_pri*self.tol) and (pre_medp <= lst_medp*self.tol) and (pre_poc <= lst_poc*self.tol) and (pre_val <= lst_val*self.tol) and (pre_vah <= lst_vah*self.tol) and (pre_fst <= lst_fst*self.tol) and (pre_med <= lst_med*self.tol) and (pre_lng <= lst_lng*self.tol) hh_poc, ll_poc = calc_divergence(poc_lst) hh_val, ll_val = calc_divergence(val_lst) hh_vah, ll_vah = calc_divergence(vah_lst) hh_pri, ll_pri = calc_divergence(pri_lst) hh_mpr, ll_mpr = calc_divergence(medp_lst) hh_fst, ll_fst = calc_divergence(fst_lng) hh_med, ll_med = calc_divergence(med_lng) hh_long, ll_long = calc_divergence(lng_lst) cond7 = hh_poc, hh_val, hh_vah, hh_pri, hh_mpr, hh_fst, hh_med, hh_long cond8 = ll_poc, ll_val, ll_vah, ll_pri, hh_mpr, ll_fst, ll_med, ll_long if (cond1 and cond7) and (cond2 and cond3): self.mp_uptrend = True if (cond4 and cond8) and (cond5 and cond6): self.mp_downtrend = True exit = self.valWin.crossedBelow(self.vwap_medWin) and self.valWin.crossedBelow(self.vwap_mlngWin) and self.valWin.crossedBelow(self.medpriWin) entry = self.valWin.crossedAbove(self.vwap_medWin) and self.valWin.crossedAbove(self.vwap_mlngWin) and self.valWin.crossedAbove(self.medpriWin) if algorithm.Portfolio[symbol].Invested: if exit and self.short: self.mp_exit_signal = True else: self.mp_exit_signal = False if not algorithm.Portfolio[symbol].Invested: if entry and self.long: self.mp_entry_signal = True else: self.mp_entry_signal = False # if algorithm.Portfolio[symbol].Invested: # if self.pocWin.crossedBelow(self.vwap_lngWin): #and self.medpriWin.crossedBelow(self.vwap_medWin) and self.valWin.crossedBelow(self.vwap_mlngWin) and self.valWin.crossedBelow(self.vwap_lngWin): # self.dont_buy = True # else: # self.dont_buy = False # if not algorithm.Portfolio[symbol].Invested: # if all(self.medpriWin[0] < x[0] for x in [self.vwap_lngWin]): # self.dont_buy = True # else: # self.dont_buy = False behavior = poc < mp_lng if behavior: self.dont_buy = True else: self.dont_buy = False @property def VWAP(self): return self.vwap.Value class IntradayVwap: '''Defines the canonical intraday VWAP indicator''' def __init__(self): self.Value = 0.0 self.lastDate = datetime.min self.sumOfVolume = 0.0 self.sumOfPriceTimesVolume = 0.0 @property def IsReady(self): return self.sumOfVolume > 0.0 def Update(self, input): '''Computes the new VWAP''' success, volume, averagePrice = self.GetVolumeAndAveragePrice(input) if not success: return self.IsReady # reset vwap on daily boundaries if self.lastDate != input.EndTime.date(): self.sumOfVolume = 0.0 self.sumOfPriceTimesVolume = 0.0 self.lastDate = input.EndTime.date() # running totals for Σ PiVi / Σ Vi self.sumOfVolume += volume self.sumOfPriceTimesVolume += averagePrice * volume if self.sumOfVolume == 0.0: # if we have no trade volume then use the current price as VWAP self.Value = input.Value return self.IsReady self.Value = self.sumOfPriceTimesVolume / self.sumOfVolume return self.IsReady def GetVolumeAndAveragePrice(self, input): '''Determines the volume and price to be used for the current input in the VWAP computation''' if type(input) is Tick: if input.TickType == TickType.Trade: return True, float(input.Quantity), float(input.LastPrice) if type(input) is TradeBar: if not input.IsFillForward: averagePrice = round(float(statistics.median([input.Open, input.High, input.Low, input.Close])), 4) return True, float(input.Volume), averagePrice return False, 0.0, 0.0
#region imports from AlgorithmImports import * #endregion import random import string import math class TradeManagement: def __init__(self, algorithm, ticker, optionSymbol): self.Trades = {} self.Algorithm = algorithm self.Ticker = ticker self.OptionSymbol = optionSymbol # Volatility indicators for position sizing self.atr = self.Algorithm.ATR(self.Ticker, 6, MovingAverageType.Exponential, Resolution.Daily) self.stddev = self.Algorithm.STD(self.Ticker, 6, Resolution.Daily) # Manage Open Positions def ManageOpenPositions(self): for t in self.OpenTrades(): # Scan for Profit-Loss if t.UnrealizedProfit() > t.Target: self.Close(t, "Profit") elif t.UnrealizedProfit() < -t.Target: self.Close(t, "Loss") # Stop Assignment if t.ExpiringSoon(): self.Close(t, "Expiring") # Base target contract count on the number of contracts to hit the profit assuming 2SD move. def ContractSizing(self, targetProfit): expectedDollarMovement = 1 * self.stddev.Current.Value * 100 # At least 1 contract contracts = min(10, math.ceil(targetProfit / expectedDollarMovement)) return int(contracts) # Base target profit per position on the volatility of the last few days. def TargetProfitEstimate(self): return round(self.atr.Current.Value * self.stddev.Current.Value * 100) # if abs(self.atr.Current.Value) > 0 else round(self.atr.Current.Value * 100) def OpenTrades(self): return [t for t in self.Trades.values() if t.IsOpen()] # Place a trade in the direction signalled def Create(self, direction): symbol = self.SelectOptionContract(direction) if symbol is None: return # If we already hold; skip alreadyOpen = [c for c in self.OpenTrades() if c.Symbol == symbol] if len(alreadyOpen) > 0: return # If today's the expiry don't trade # if (symbol.ID.Date < self.Algorithm.Time): # return targetProfit = self.TargetProfitEstimate() size = self.ContractSizing(targetProfit) price = self.Algorithm.Securities[symbol].Price asset = self.Algorithm.Securities[self.Ticker].Price tag = f"Asset: {asset} | Opened | Target of ${targetProfit} at ${price}" ticket = self.Algorithm.MarketOrder(symbol, size, False, tag) trade = Trade(self.Algorithm, self.Algorithm.Securities[symbol], ticket, targetProfit) #self.Algorithm.Log(str(self.Algorithm.Portfolio.Keys)) #self.Algorithm.Plot("Risk Management", "Unrealized Profit Percent", float(trade.UnrealizedProfit())) #self.Algorithm.Plot("Risk Management", "Unrealized Profit Percent (Portfolio)", float(self.Algorithm.Portfolio[trade.Contract].UnrealizedProfitPercent)) self.Trades[trade.Id] = trade return trade def Close(self, trade, reason): trade.Close(reason) if trade.Id in self.Trades: del self.Trades[trade.Id] # Select OOM Option Contract with Given Bias def SelectOptionContract(self, direction): if direction == OrderDirection.Buy: right = OptionRight.Call else: right = OptionRight.Put chain = self.Algorithm.CurrentSlice.OptionChains.GetValue(self.OptionSymbol) if chain is None: self.Algorithm.Log(f"{self.Algorithm.Time} - No option chains with {self.OptionSymbol}. Missing data for Mar-2nd.") return None # Select contracts expirying tomorrow at least. chain = [x for x in chain if (x.Right == right and x.Expiry > self.Algorithm.Time)] reverseSort = right == OptionRight.Call # Reverse sort of a call contracts = sorted(sorted(chain, key = lambda x: abs(x.Strike), reverse=reverseSort), key = lambda x: x.Expiry) contracts = [x for x in contracts if x.OpenInterest > 20000] #contracts_IV = sorted(sorted(chain, key = lambda x: x.ImpliedVolatility, reverse=reverseSort), key = lambda x: x.Expiry)[:2] #contracts_OI = sorted(sorted(chain, key = lambda x: x.OpenInterest, reverse=reverseSort), key = lambda x: x.Expiry)[:5] #contracts = list(set.intersection(*map(set, [contracts, contracts_IV]))) try: #self.Algorithm.Plot("Options", "Implied Volatility", round(float(contracts[0].ImpliedVolatility), 5)) #self.Algorithm.Plot("Options", "Open Interest", float(contracts[0].OpenInterest)) #self.Algorithm.Plot("Contract", "Delta", abs(float(self.Algorithm.Securities[self.Ticker].Price - contracts[0].Strike))) self.Algorithm.Plot("Options", "Relative Volume ROCP", float(self.rdv_roc.Current.Value)) self.Algorithm.Plot("Options", "ATR", float(self.atr.Current.Value)) self.Algorithm.Plot("Options", "STDDEV", float(self.stddev.Current.Value)) except: pass # No contracts found if len(contracts) == 0: return None return contracts[0].Symbol class Trade: def __init__(self, algorithm, contract, ticket, target): self.Id = ''.join(random.choice(string.ascii_lowercase) for i in range(10)) self.Ticket = ticket self.Contract = contract self.Symbol = contract.Symbol self.Algorithm = algorithm self.Open = True self.Target = target def ExpiringSoon(self): expiry = self.Symbol.ID.Date + timedelta(hours=16) if ( (expiry - self.Algorithm.Time) < timedelta(minutes=10)): self.Algorithm.Log(f"{self.Symbol} Close to Expiry: {expiry} - {self.Algorithm.Time} < 10min" ) return True else: return False def UnrealizedProfitPercent(self): return (self.Contract.Holdings.Price - self.Ticket.AverageFillPrice) / self.Contract.Holdings.Price def UnrealizedProfit(self): return 100*(self.Contract.Holdings.Price - self.Ticket.AverageFillPrice) * self.Ticket.Quantity def IsOpen(self): return self.Open def Close(self, reason): self.Open = False tag = f"Close | {reason} | {self.UnrealizedProfit()} Net" self.Algorithm.Liquidate(self.Symbol, tag)