| Overall Statistics |
|
Total Trades 73 Average Win 0.99% Average Loss -0.49% Compounding Annual Return 22.640% Drawdown 3.300% Expectancy 0.678 Net Profit 13.208% Sharpe Ratio 1.825 Probabilistic Sharpe Ratio 94.953% Loss Rate 44% Win Rate 56% Profit-Loss Ratio 2.02 Alpha 0.075 Beta 0.33 Annual Standard Deviation 0.055 Annual Variance 0.003 Information Ratio 0.275 Tracking Error 0.079 Treynor Ratio 0.305 Total Fees $0.00 Estimated Strategy Capacity $40000000.00 Lowest Capacity Asset SPY R735QTJ8XC9X Portfolio Turnover 30.51% |
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, 5, 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):
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.0)
# 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)
# 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', 'volume', 'Price_Direction'], 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)
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)