| Overall Statistics |
|
Total Trades 710 Average Win 2.23% Average Loss -0.82% Compounding Annual Return 33.432% Drawdown 16.500% Expectancy 1.923 Net Profit 5725.025% Sharpe Ratio 1.791 Probabilistic Sharpe Ratio 99.785% Loss Rate 21% Win Rate 79% Profit-Loss Ratio 2.71 Alpha 0.211 Beta 0.221 Annual Standard Deviation 0.129 Annual Variance 0.017 Information Ratio 0.802 Tracking Error 0.179 Treynor Ratio 1.043 Total Fees $1767.83 Estimated Strategy Capacity $710000.00 Lowest Capacity Asset TLH TP8J6Z7L419H |
################################################################################
# KalmanFilterIndicator
#
# Core logic from @vladimir's KalmanFilter implementation:
# https://www.quantconnect.com/forum/discussion/12741/kalman-filter-for-bitcoin/p1
#
################################################################################
from pykalman import KalmanFilter
class KalmanFilterIndicator(PythonIndicator):
def __init__(self,name, period, selector=Field.Low,
transition_matrices = [1], observation_matrices = [1],
initial_state_mean = 0, initial_state_covariance = 1,
observation_covariance=1, transition_covariance=.01):
self.Name = name
self.period = period
self.Value = 0
self.barCalc = selector
self.transition_matrices = transition_matrices
self.observation_matrices = observation_matrices
self.initial_state_mean = initial_state_mean
self.initial_state_covariance = initial_state_covariance
self.observation_covariance = observation_covariance
self.transition_covariance = transition_covariance
self.rollingWindow = RollingWindow[float](self.period)
# ---------------------------------
def Update(self, inputBar):
effectiveBarValue = self.barCalc(inputBar)
self.rollingWindow.Add(effectiveBarValue)
if(not self.rollingWindow.IsReady):
return False
else:
basisValue = np.flipud(np.array([self.rollingWindow[i] for i in range(self.period)]))
self.kf = KalmanFilter( transition_matrices = self.transition_matrices,
observation_matrices = self.observation_matrices,
initial_state_mean = self.initial_state_mean,
initial_state_covariance = self.initial_state_covariance,
observation_covariance = self.observation_covariance,
transition_covariance = self.transition_covariance)
kf,_ = self.kf.filter(basisValue)
currKalman = kf[-1]
self.Value = float(currKalman)
return True
################################################################################
#
# LaguerreFilterIndicator
# ==============================
# Laguerre Filter as defined by John F. Ehlers in `Cybernetic Analysis for
# Stock and Futures`, 2004, published by Wiley. `ISBN: 978-0-471-46307-8
# https://www.mt5users.com/wp-content/uploads/2020/01/timewarp.pdf
#
# Copied from @vladimir's implementation
# https://www.quantconnect.com/forum/discussion/11788/another-digital-filter-laguerre-filter/p1/comment-34897
#
################################################################################
class LaguerreFilterIndicator(PythonIndicator):
def __init__(self, name, gamma ):
self.Name = name
self.gamma = gamma
self.prices = np.array([])
self.Value = 0
self.L0 = 0.0; self.L1 = 0.0; self.L2 = 0.0; self.L3 = 0.0
def Update(self, input):
mp = (input.High + input.Low)/2
self.prices = np.append(self.prices, mp)[-4:]
if len(self.prices) <= 1:
self.L0 = mp; self.L1 = mp; self.L2 = mp; self.L3 = mp;
if len(self.prices) != 4 : return
L01 = self.L0; L11 = self.L1; L21 = self.L2; L31 = self.L3;
g = self.gamma
self.L0 = (1 - g)*mp + g*L01
self.L1 = L01 - g*self.L0 + g*L11
self.L2 = L11 - g*self.L1 + g*L21
self.L3 = L21 - g*self.L2 + g*L31
if len(self.prices) != 4 :
self.Value = mp
return False
self.Value = (self.L0 + (2*self.L1) + 2*(self.L2) + self.L3) / 6
return True
###################################################
#
# Smart Rolling window
# ========================
# Convenience object to build on RollingWindow functionality
#
# Methods:
# -------------------------
# mySmartWindow.IsRising()
# mySmartWindow.IsFalling()
# mySmartWindow.crossedAboveValue(value)
# mySmartWindow.crossedBelowValue(value)
# mySmartWindow.crossedAbove(otherWindow)
# mySmartWindow.crossedBelow(otherWindow)
# mySmartWindow.IsFlat(decimalPrecision)
# mySmartWindow.hasAtLeastThisMany(value)
#
###################################################
class SmartRollingWindow():
def __init__(self, windowType, windowLength):
self.window = None
self.winLength = windowLength
if (windowType is "int"):self.window = RollingWindow[int](windowLength)
elif (windowType is "bool"):self.window = RollingWindow[bool](windowLength)
elif (windowType is "float"):self.window = RollingWindow[float](windowLength)
elif (windowType is "TradeBar"):self.window = RollingWindow[TradeBar](windowLength)
def crossedAboveValue(self, value): return (self.window[1] <= value < self.window[0])
def crossedBelowValue(self, value): return (self.window[1] >= value > self.window[0])
def crossedAbove(self, series): return (any(self.window[i+1] <= series[i+1] and self.window[i] > series[i] for i in range(0, self.winLength-1)))
def crossedBelow(self, series): return (any(self.window[i+1] >= series[i+1] and self.window[i] < series[i] for i in range(0, self.winLength-1)))
def isAbove(self, series): return (self.window[0] > series[0])
def isBelow(self, series): return (self.window[0] < series[0])
def isFlat(self): return (self.window[1] == self.window[0])
def isFalling(self): return (self.window[1] > self.window[0])
def isRising(self): return (self.window[1] < self.window[0])
def Add(self,value):
self.window.Add(value)
def IsReady(self):
return (self.window is not None) and \
(self.window.Count >= self.winLength) ## TODO: just use rw.IsReady?
def __getitem__(self, index):
return self.window[index]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
from helpers import myTrailingStopRiskManagementModel
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]
# # ML Model
# pairs = [self.MKT, self.SLV, self.GLD, self.XLI, self.XLU, self.DBB, self.UUP]
# data = self.history
# data['vola'] = data[self.MKT].pct_change().rolling(246).std() * np.sqrt(252)
# data['wait_days'] = data['vola'].map(lambda x: int(int(x)*self.BASE_RET), na_action='ignore')
# data['period'] = data['vola'].map(lambda x: int((1.0 - int(x)) * self.BASE_RET), na_action='ignore')
# market_signals = list()
# for i in range(0, len(data['period'])):
# if 'na' not in str(data['period'][i]):
# count = int(i)
# period = int(data['period'][i])
# r = data[count:count+246].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])
# market_signals.append(exit_market)
# else:
# market_signals.append('na')
# data['market_signals'] = market_signals
# del market_signals
# data['Market_Change'] = data[self.MKT].pct_change()
# # # Load LabelEncoder to process string variables
# le = preprocessing.LabelEncoder()
# ml_data = data.dropna()
# pairs = [self.MKT, self.SLV, self.GLD, self.XLI, self.XLU, self.DBB, self.UUP, 'vola', 'wait_days', 'period', 'Market_Change']
# X = ml_data.drop(['market_signals'], axis=1)
# y = np.ravel(ml_data[['market_signals']].astype(str).apply(le.fit_transform))
# #algorithm.Debug(str(X.shape) + ";" + str(y.shape))
# X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# model = ExtraTreeClassifier(max_depth = 40,
# max_features = 'sqrt',
# criterion = 'gini',
# class_weight = 'balanced',
# random_state = 42)
# model.fit(X_train, y_train)
# y_pred = model.predict(X_test)
# algorithm.Plot("Model Score", "Score", model.score(X_test, y_test))
# algorithm.Plot("MAE:", "Mae", mean_absolute_error(y_test, y_pred))
# algorithm.Plot("Coef of Determination:", "r-squared", r2_score(y_test, y_pred))
# algorithm.Plot("Actual vs Pred", "Actual", r2_score(y_test, y_pred))
# clf_results = metrics.precision_recall_fscore_support(y_test, y_pred)
# algorithm.Plot("Confusion_Matrix", "Precision", clf_results[0].round(2))
# algorithm.Plot("Confusion_Matrix", "Recall", clf_results[1].round(2))
# algorithm.Plot("Confusion_Matrix", "f1-score", clf_results[2].round(2))
# algorithm.Plot("Confusion_Matrix", "Support", clf_results[3].round(2))
# signal_actual = np.log(self.history[self.MKT]).iloc[-1]
# signal_pred = model.predict(np.ravel(np.log(self.history[pairs]).iloc[-1]).reshape(1, -1))
# prev = np.log(self.history[self.MKT]).iloc[-2]
# signal_actual = 1 if signal_actual > prev else -1
# signal_pred = 1 if signal_pred > prev else -1
# agreement= 1 if signal_actual == signal_pred else -1
# algorithm.Plot("Actual vs Pred", "Actual", float(signal_actual))
# algorithm.Plot("Actual vs Pred", "Pred", float(signal_pred))
# algorithm.Plot("Actual vs Pred", "Agreement", float(agreement))
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
# algorithm.Plot("Wait Days", "Actual", self.count)
# algorithm.Plot("Wait Days", "Expected", float(wait_days + self.outday))
# algorithm.Plot("Market Volatility", str(self.MKT), float(vola))
# if direction == InsightDirection.Down:
# val = -1.0
# elif direction == InsightDirection.Up:
# val = 1.0
# else:
# val = 0.0
# algorithm.Plot("IN vs Out", "Before", float(val))
insights.append(Insight.Price(self.MKT, self.predictionInterval, direction))
return insights
def returns_custom(self, symbol, timeframe, algorithm):
frames = [i for i in range(-1, -11, -2)]
prices = algorithm.History(symbol, TimeSpan.FromDays(timeframe), self.resolution).close.pct_change()
return round(statistics.median([round(float(prices[i] - min(prices[i-9:i])/ min(prices[i-9:i])), 4) if min(prices[i-9:i]) != 0 else 0 for i in frames]), 4)import pandas as pd
import numpy as np
from scipy.optimize import minimize
class myTrailingStopRiskManagementModel:
'''
Credit goes to: Alex Catarino and many of his friends at QuantConnect
https://github.com/QuantConnect/Lean/blob/master/Algorithm.Framework/Risk/TrailingStopRiskManagementModel.py
Description:
Limits the maximum possible loss measured from the highest unrealized profit
'''
def __init__(self, maximumDrawdownPercent = 0.08):
'''initializes the class
Args: maximumDrawdownPercent: The maximum percentage drawdown allowed for algorithm portfolio compared with the highest unrealized profit, defaults to 5% drawdown
'''
self.maximumDrawdownPercent = -abs(maximumDrawdownPercent)
self.trailingHighs = dict()
def setDD(self, maximumDrawdownPercent = 0.08):
'''allows to change the drawdown
Args: maximumDrawdownPercent: The maximum percentage drawdown allowed for algorithm portfolio compared with the highest unrealized profit, defaults to 5% drawdown
'''
self.maximumDrawdownPercent = -abs(maximumDrawdownPercent)
def setWTtoZeroIfDDtooHigh(self, algorithm, targets=None):
'''If drawdown is too high, set wt[symbol] to zero
algo.wt[symbol] = weights which will be set to 0 in case drawdown exceeds the maximum
'''
for kvp in algorithm.Securities:
symbol = kvp.Key
security = kvp.Value
# Remove from trailingHighs dict if not invested
if not security.Invested:
self.trailingHighs.pop(symbol, None)
continue
# Add newly invested securities to trailingHighs dict
if symbol not in self.trailingHighs:
self.trailingHighs[symbol] = security.Holdings.AveragePrice
continue
# Check for new highs and update trailingHighs dict
if self.trailingHighs[symbol] < security.High:
self.trailingHighs[symbol] = security.High
continue
# Calc the drawdown
securityHigh = self.trailingHighs[symbol]
drawdown = (security.Low / securityHigh) - 1
# If drawdown is too high, set symbol weight to zero
if drawdown < self.maximumDrawdownPercent:
algorithm.wt[symbol] = 0
return
class myPortfolioOptimizer:
'''
Credit goes to: Emilio Freire / InnoQuantivity
https://innoquantivity.com/blogs/inno-blog/portfolio-optimization-quantconnect-research-algorithm
https://www.quantconnect.com/forum/discussion/8128/portfolio-optimization-research-amp-algorithm-for-better-workflows/p1/comment-22952
Description:
Implementation of a custom optimizer that calculates the weights for each asset to optimize a given objective function
Details:
Optimization can be:
- Equal Weighting
- Maximize Portfolio Return
- Minimize Portfolio Standard Deviation
- Mean-Variance (minimize Standard Deviation given a target return)
- Maximize Portfolio Sharpe Ratio
- Maximize Portfolio Sortino Ratio
- Risk Parity Portfolio
Constraints:
- Weights must be between some given boundaries
- Weights must sum to 1
'''
def __init__(self,
minWeight = 0,
maxWeight = 1):
'''
Description:
Initialize the CustomPortfolioOptimizer
Args:
minWeight(float): The lower bound on portfolio weights
maxWeight(float): The upper bound on portfolio weights
'''
self.minWeight = minWeight
self.maxWeight = maxWeight
def CalcWeights(self, algorithm, symbols, objectiveFunction='riskParity', lookback=63, targetReturn=None):
'''
Description:
Calculate weights from daily returns, return a pandas Series
'''
history = np.log10(algorithm.History(symbols, lookback, Resolution.Daily)['close'].unstack(level = 0))
returnsDf = history.pct_change().dropna()
returnsDf.columns = [algorithm.AddEquity(i).Symbol.Value for i in list(returnsDf.columns)]
weights = self.Optimize(objectiveFunction, returnsDf, targetReturn)
return pd.Series(weights, index=returnsDf.columns, name='weights')
def Optimize(self, objFunction, dailyReturnsDf, targetReturn = None):
'''
Description:
Perform portfolio optimization given a series of returns
Args:
objFunction: The objective function to optimize (equalWeighting, maxReturn, minVariance, meanVariance, maxSharpe, maxSortino, riskParity)
dailyReturnsDf: DataFrame of historical daily arithmetic returns
Returns:
Array of double with the portfolio weights (size: K x 1)
'''
# initial weights: equally weighted
size = dailyReturnsDf.columns.size # K x 1
self.initWeights = np.array(size * [1. / size])
# get sample covariance matrix
covariance = dailyReturnsDf.cov()
# get the sample covariance matrix of only negative returns for sortino ratio
negativeReturnsDf = dailyReturnsDf[dailyReturnsDf < 0]
covarianceNegativeReturns = negativeReturnsDf.cov()
if objFunction == 'equalWeighting':
return self.initWeights
bounds = tuple((self.minWeight, self.maxWeight) for x in range(size))
constraints = [{'type': 'eq', 'fun': lambda x: np.sum(x) - 1.0}]
if objFunction == 'meanVariance':
# if no target return is provided, use the resulting from equal weighting
if targetReturn is None:
targetReturn = self.CalculateAnnualizedPortfolioReturn(dailyReturnsDf, self.initWeights)
constraints.append( {'type': 'eq', 'fun': lambda weights:
self.CalculateAnnualizedPortfolioReturn(dailyReturnsDf, weights) - targetReturn} )
opt = minimize(lambda weights: self.ObjectiveFunction(objFunction, dailyReturnsDf,
covariance, covarianceNegativeReturns,
weights),
x0 = self.initWeights,
bounds = bounds,
constraints = constraints,
method = 'SLSQP')
return opt['x']
def ObjectiveFunction(self, objFunction, dailyReturnsDf, covariance, covarianceNegativeReturns, weights):
'''
Description:
Compute the objective function
Args:
objFunction: The objective function to optimize (equalWeighting, maxReturn, minVariance, meanVariance,
maxSharpe, maxSortino, riskParity)
dailyReturnsDf: DataFrame of historical daily returns
covariance: Sample covariance
covarianceNegativeReturns: Sample covariance matrix of only negative returns
weights: Portfolio weights
'''
if objFunction == 'maxReturn':
f = self.CalculateAnnualizedPortfolioReturn(dailyReturnsDf, weights)
return -f # convert to negative to be minimized
elif objFunction == 'minVariance':
f = self.CalculateAnnualizedPortfolioStd(covariance, weights)
return f
elif objFunction == 'meanVariance':
f = self.CalculateAnnualizedPortfolioStd(covariance, weights)
return f
elif objFunction == 'maxSharpe':
f = self.CalculateAnnualizedPortfolioSharpeRatio(dailyReturnsDf, covariance, weights)
return -f # convert to negative to be minimized
elif objFunction == 'maxSortino':
f = self.CalculateAnnualizedPortfolioSortinoRatio(dailyReturnsDf, covarianceNegativeReturns, weights)
return -f # convert to negative to be minimized
elif objFunction == 'riskParity':
f = self.CalculateRiskParityFunction(covariance, weights)
return f
else:
raise ValueError(f'PortfolioOptimizer.ObjectiveFunction: objFunction input has to be one of equalWeighting,'
+ ' maxReturn, minVariance, meanVariance, maxSharpe, maxSortino or riskParity')
def CalculateAnnualizedPortfolioReturn(self, dailyReturnsDf, weights):
annualizedPortfolioReturns = np.sum( ((1 + dailyReturnsDf.mean())**252 - 1) * weights )
return annualizedPortfolioReturns
def CalculateAnnualizedPortfolioStd(self, covariance, weights):
annualizedPortfolioStd = np.sqrt( np.dot(weights.T, np.dot(covariance * 252, weights)) )
if annualizedPortfolioStd == 0:
raise ValueError(f'PortfolioOptimizer.CalculateAnnualizedPortfolioStd: annualizedPortfolioStd cannot be zero. Weights: {weights}')
return annualizedPortfolioStd
def CalculateAnnualizedPortfolioNegativeStd(self, covarianceNegativeReturns, weights):
annualizedPortfolioNegativeStd = np.sqrt( np.dot(weights.T, np.dot(covarianceNegativeReturns * 252, weights)) )
if annualizedPortfolioNegativeStd == 0:
raise ValueError(f'PortfolioOptimizer.CalculateAnnualizedPortfolioNegativeStd: annualizedPortfolioNegativeStd cannot be zero. Weights: {weights}')
return annualizedPortfolioNegativeStd
def CalculateAnnualizedPortfolioSharpeRatio(self, dailyReturnsDf, covariance, weights):
annualizedPortfolioReturn = self.CalculateAnnualizedPortfolioReturn(dailyReturnsDf, weights)
annualizedPortfolioStd = self.CalculateAnnualizedPortfolioStd(covariance, weights)
annualizedPortfolioSharpeRatio = annualizedPortfolioReturn / annualizedPortfolioStd
return annualizedPortfolioSharpeRatio
def CalculateAnnualizedPortfolioSortinoRatio(self, dailyReturnsDf, covarianceNegativeReturns, weights):
annualizedPortfolioReturn = self.CalculateAnnualizedPortfolioReturn(dailyReturnsDf, weights)
annualizedPortfolioNegativeStd = self.CalculateAnnualizedPortfolioNegativeStd(covarianceNegativeReturns, weights)
annualizedPortfolioSortinoRatio = annualizedPortfolioReturn / annualizedPortfolioNegativeStd
return annualizedPortfolioSortinoRatio
def CalculateRiskParityFunction(self, covariance, weights):
''' Spinu formulation for risk parity portfolio '''
assetsRiskBudget = self.initWeights
portfolioVolatility = self.CalculateAnnualizedPortfolioStd(covariance, weights)
x = weights / portfolioVolatility
riskParity = (np.dot(x.T, np.dot(covariance, x)) / 2) - np.dot(assetsRiskBudget.T, np.log(x))
return riskParityfrom itertools import groupby
import tweepy
from datetime import datetime, timedelta, date
import time
import pandas as pd
import numpy as np
import re, math
import scipy
from math import ceil
from collections import deque
from itertools import chain
from pytz import timezone
import statistics
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *
from QuantConnect.Data.Market import TradeBar
from QuantConnect.Algorithm.Framework.Execution import StandardDeviationExecutionModel, VolumeWeightedAveragePriceExecutionModel
from QuantConnect.Algorithm.Framework.Risk import MaximumDrawdownPercentPortfolio, MaximumUnrealizedProfitPercentPerSecurity, MaximumDrawdownPercentPerSecurity, TrailingStopRiskManagementModel
from dual_momentum_with_out_days_alpha import DualMomentumWithOutDaysAlphaModel
from portfolio_management import PortfolioManagementModel
from trade_execution import ScheduledExecutionModel
from manage_risk import CustomRiskModel
from symbol_data_functions import SymbolData
VOLA = 126; BASE_RET = 83; RET = 252; EXCL = 21; LEV = 1.00;
class HorizontalQuantumCoil(QCAlgorithm):
def Initialize(self):
self.Portfolio.MarginCallModel = MarginCallModel.Null
self.SetStartDate(2008, 1, 1)
self.SetCash(10000)
self.added_cash = 115
self.upkeep = 28
self.simulate_live = False
self.SetWarmUp(timedelta(252))
self.Settings.FreePortfolioValuePercentage = 0.05
# self.SetBrokerageModel(BrokerageName.AlphaStreams)
self.SetAlpha(DualMomentumWithOutDaysAlphaModel(self, VOLA, BASE_RET, Resolution.Daily))
stonks = ['FDN', 'QQQ', 'IWM', 'SPY', 'VTI', 'DIA', 'IWF', 'TLT', 'TLH', 'IEI', 'IEF'] # , 'SPDN' # 'IYW', 'IVV',
#lev_stonks = ['TQQQ', 'URTY', 'SPXL', 'TMF']# , 'AGQ', 'UGL']
symbols = []
# stonks = stonks + lev_stonks
for stonk in stonks:
val = Symbol.Create(stonk, SecurityType.Equity, Market.USA)
symbols.append(val)
self.SetUniverseSelection(ManualUniverseSelectionModel(symbols))
self.UniverseSettings.Resolution = Resolution.Daily
self.SetPortfolioConstruction(PortfolioManagementModel(self, RET, EXCL, LEV, Resolution.Daily, portfolioBias = PortfolioBias.Long))
self.SetExecution(ScheduledExecutionModel(self))
self.SetRiskManagement(CustomRiskModel(self, maximumDrawdownPercent = 0.025, maximumUnrealizedProfitPercent = 0.175, resolution = Resolution.Daily))
self.createPlots("SPY")
for time in range(55, 295, 30):
self.Schedule.On(self.DateRules.EveryDay("SPY"), \
self.TimeRules.AfterMarketOpen("SPY", time), \
self.UpdateTickets)
if self.simulate_live:
self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), \
self.TimeRules.BeforeMarketClose("SPY", 0), \
self.AddCash)
self.Schedule.On(self.DateRules.MonthStart("SPY"), \
self.TimeRules.BeforeMarketClose("SPY", 0), \
self.UpKeep)
def AddCash(self):
self.Portfolio.SetCash(self.Portfolio.Cash + self.added_cash)
def UpKeep(self):
self.Portfolio.SetCash(self.Portfolio.Cash - self.upkeep)
def consolidation_handler(self, sender, consolidated):
self.history.loc[consolidated.EndTime, consolidated.Symbol] = consolidated.Close
self.history = self.history.iloc[-(VOLA + 1):]
def createPlots(self, benchmark):
self.__benchmark = benchmark
self.__plot_every_n_days = 5
self.__plot_every_n_days_i = 0
plot = Chart('Performance')
plot.AddSeries(Series(self.__benchmark, SeriesType.Line, 0, '%'))
plot.AddSeries(Series("Algorithm", SeriesType.Line, 0, '%'))
self.AddChart(plot)
self.ResetPlot()
def ResetPlot(self):
self.year = self.Time.year
self.__cost_portfolio = None
self.__cost_benchmark = None
def CalculateBenchmarkPerformance(self):
price = self.Securities[self.__benchmark].Price
if self.__cost_benchmark == None:
self.__cost_benchmark = price
return 100.0 * ((price / self.__cost_benchmark) - 1.0)
def CalculatePortfolioPerformance(self):
if self.__cost_portfolio == None:
self.__cost_portfolio = self.Portfolio.TotalPortfolioValue
return 100.0 * ((self.Portfolio.TotalPortfolioValue / self.__cost_portfolio) - 1.0)
def OnEndOfDay(self):
if self.IsWarmingUp or not self.Securities[self.__benchmark].HasData:
return
openOrders = self.Transactions.GetOpenOrders()
openLimitOrders = [order for order in openOrders if (order.Type == OrderType.Limit) or (order.Type == OrderType.StopMarket)]
if len(openLimitOrders)> 0:
for x in openLimitOrders:
self.Transactions.CancelOrder(x.Id)
if self.Time.year != self.year:
self.ResetPlot()
self.__plot_every_n_days_i == -1
self.__plot_every_n_days_i += 1
if self.__plot_every_n_days_i % self.__plot_every_n_days != 0:
return
self.Plot('Performance', self.__benchmark, self.CalculateBenchmarkPerformance())
self.Plot('Performance', "Algorithm", self.CalculatePortfolioPerformance())
# self.Plot(f"Cash", "Remaining", self.Portfolio.Cash)
# for kvp in self.Portfolio:
# security_holding = kvp.Value
# sec = security_holding.Symbol.Value
# if self.Portfolio[sec].Invested:
# self.Plot(f"UnrealizedProfitPercent", str(sec), self.Portfolio[sec].UnrealizedProfitPercent)
# security_holding = round(float(self.Portfolio[sec].AveragePrice*self.Portfolio[sec].Quantity), 3)
# if security_holding >= int(self.Portfolio.Cash*0.4):
# self.Plot(f"UnrealizedProfitPercent", str(sec)+"_at 0.5 bp", self.Portfolio[sec].UnrealizedProfitPercent)
# elif security_holding >= int(self.Portfolio.Cash*0.1):
# self.Plot(f"UnrealizedProfitPercent", str(sec)+"_at 0.1 bp", self.Portfolio[sec].UnrealizedProfitPercent)
# self.Plot(f"Cash", str(sec), round(self.Portfolio[sec].AveragePrice*self.Portfolio[sec].Quantity, 4))
def MarketOpen(self):
return self.Time.hour != 0 and self.Time.minute == 1
def UpdateTickets(self):
openOrders = self.Transactions.GetOpenOrders()
openLimitOrders = [order for order in openOrders if (order.Type == OrderType.Limit) or (order.Type == OrderType.StopMarket)]
if len(openLimitOrders)> 0:
for x in openLimitOrders:
self.Transactions.CancelOrder(x.Id)
invested = [x.Key for x in self.Portfolio if x.Value.Invested]
for symbol in invested:
security_holding = self.Portfolio[symbol]
quantity = security_holding.Quantity
price = security_holding.AveragePrice
unrealized_profit_pct = self.Portfolio[symbol].UnrealizedProfitPercent
security_holding = round(float(self.Portfolio[symbol].AveragePrice*self.Portfolio[symbol].Quantity), 3)
if security_holding >= int(self.Portfolio.Cash*0.4):
if self.Securities[symbol].Price > round(self.Portfolio[symbol].AveragePrice*1.1, 3):
stopPrice = self.Securities[symbol].Price * 0.9725
limitPrice = self.Securities[symbol].Price * 1.0375
self.StopMarketOrder(symbol, -quantity, stopPrice)
self.LimitOrder(symbol, -quantity, limitPrice)
elif security_holding <= int(self.Portfolio.Cash*0.25):
if self.Securities[symbol].Price > round(self.Portfolio[symbol].AveragePrice*1.1, 3):
stopPrice = self.Securities[symbol].Price * 0.97
limitPrice = self.Securities[symbol].Price * 1.05
self.StopMarketOrder(symbol, -quantity, stopPrice)
self.LimitOrder(symbol, -quantity, limitPrice)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 pandas as pd
import numpy as np
from scipy import stats
import statistics
from operator import itemgetter
from functools import reduce
from symbol_data_functions import SymbolData
class CustomRiskModel(RiskManagementModel):
def __init__(self, algorithm, maximumDrawdownPercent = 0.03, maximumUnrealizedProfitPercent = 0.15, resolution = Resolution.Daily, *args, **kwargs):
super().__init__()
'''Initializes a new instance class with various risk management systems
Args:
maximumDrawdownPercent: The maximum percentage drawdown allowed for algorithm portfolio compared with the highest unrealized profit, defaults to 5% drawdown
maximumUnrealizedProfitPercent: The maximum percentage unrealized profit allowed for any single security holding, defaults to 5% drawdown per security'''
self.maximumDrawdownPercent = abs(maximumDrawdownPercent)
self.maximumUnrealizedProfitPercent = abs(maximumUnrealizedProfitPercent)
self.resolution = resolution
self.trailing = dict()
# self.data = {}
# invested = [x.Key for x in algorithm.Portfolio if x.Value.Invested]
# for symbol in invested:
# symbol = algorithm.Portfolio[symbol]
# algorithm.AddEquity(symbol, Resolution.Hour).Symbol
# self.data[symbol] = SymbolData(algorithm, symbol)
def ManageRisk(self, algorithm, targets):
'''Manages the algorithm's risk at each time step
Args:
algorithm: The algorithm instance
targets: The current portfolio targets to be assessed for risk'''
targets = []
for kvp in algorithm.Securities:
security = kvp.Value
if not security.Invested:
# self.trailing.pop(security.Symbol, None)
continue
unrealized_profit_pct = security.Holdings.UnrealizedProfitPercent
# cond = (self.data[security.Symbol].rocSignal_fast.Current.Value < 0.0) and (self.data[security.Symbol].volSignal_fast.Current.Value < 0.0)
# signals = ((self.data[security.Symbol].breakdown or ((not self.data[security.Symbol].vpnIndicator) and (self.data[security.Symbol].is_downtrend) or (self.data[security.Symbol].exit_signal and self.data[security.Symbol].rsi_exit_signal and self.data[security.Symbol].macd_exit_signal and self.data[security.Symbol].quick_down))) or (self.data[security.Symbol].macd_downtrend and self.data[security.Symbol].rsi_downtrend))
# roc_sum = sum([self.data[security.Symbol].roc.Current.Value, self.data[security.Symbol].roc_fast.Current.Value, self.data[security.Symbol].roc_med.Current.Value, self.data[security.Symbol].roc_long.Current.Value]) < -5
# cost = security.Holdings.AveragePrice * security.Holdings.Quantity
# # # Add newly invested securities
# value = self.trailing.get(security.Symbol)
# if value == None:
# newValue = unrealized_profit_pct if unrealized_profit_pct > 0 else 0
# self.trailing[security.Symbol] = newValue
# continue
# # # Check for new high and update
# if value < unrealized_profit_pct:
# self.trailing[security.Symbol] = unrealized_profit_pct
# continue
# If maximum unrealized profit percent reached, liquidate
if unrealized_profit_pct > self.maximumUnrealizedProfitPercent:
targets.append(PortfolioTarget(security.Symbol, 0))
# If unrealized profit percent deviates from local max for more than affordable percentage and \
# if unrealized profit >= 10%
# # If exit signal triggered, liquidate
# if ((self.data[security.Symbol].candle_downtrend) and (cond or signals or (self.data[security.Symbol].ll_sum and self.data[security.Symbol].ll_all))):
# targets.append(PortfolioTarget(security.Symbol, 0))
return targets
# def OnSecuritiesChanged(self, algorithm, changes):
# addedSymbols = []
# for security in changes.AddedSecurities:
# addedSymbols.append(security.Symbol)
# if security.Symbol not in self.data:
# self.data[security.Symbol] = SymbolData(algorithm, security.Symbol)
# for removed in changes.RemovedSecurities:
# # clean up removed security data
# if removed.Symbol in self.data:
# if self.IsSafeToRemove(algorithm, removed.Symbol):
# data = self.data.pop(removed.Symbol)
# algorithm.SubscriptionManager.RemoveConsolidator(removed.Symbol, data.Consolidator)
# if len(addedSymbols) > 0:
# history = algorithm.History(addedSymbols, 84, Resolution.Daily).loc[addedSymbols]
# for symbol in addedSymbols:
# try:
# self.data[security.Symbol].Warmup(history.loc[security.Symbol])
# except:
# algorithm.Debug(str(security.Symbol))
# continue
# def IsSafeToRemove(self, algorithm, symbol):
# '''Determines if it's safe to remove the associated symbol data'''
# # confirm the security isn't currently a member of any universe
# return not any([kvp.Value.ContainsMember(symbol) for kvp in algorithm.UniverseManager])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 pandas as pd
import numpy as np
from scipy import stats
import statistics
import datetime as dt
from operator import itemgetter
from functools import reduce
from helpers import myPortfolioOptimizer
from symbol_data_functions import SymbolData
class PortfolioManagementModel(PortfolioConstructionModel):
def __init__(self,
algorithm,
RET=252,
EXCL=21,
LEV=1.00,
resolution = Resolution.Daily,
portfolioBias = PortfolioBias.Long,
*args, **kwargs):
super().__init__()
self.portfolioBias = portfolioBias
self.resolution = resolution
self.RET = RET
self.EXCL = EXCL
self.LEV = LEV
self.VOLA = 126
self.bull = False
self.STK1 = algorithm.AddEquity('SPY', self.resolution).Symbol # SPXL/SPY
self.STK2 = algorithm.AddEquity('QQQ', self.resolution).Symbol # TQQQ/QQQ
self.STK3 = algorithm.AddEquity('IWM', self.resolution).Symbol # URTY/IWM
self.STK4 = algorithm.AddEquity('DIA', self.resolution).Symbol # FDN/FDN
self.STK5 = algorithm.AddEquity('VTI', self.resolution).Symbol # AGQ/VTI
self.STK6 = algorithm.AddEquity('FDN', self.resolution).Symbol # AGQ/VTI
self.STK7 = algorithm.AddEquity('IWF', self.resolution).Symbol # AGQ/VTI
self.BND1 = algorithm.AddEquity('TLH', self.resolution).Symbol # TMF/TLH
self.BND2 = algorithm.AddEquity('TLT', self.resolution).Symbol # UGL/TLT
self.BND3 = algorithm.AddEquity('IEI', self.resolution).Symbol # TMF/TLH
self.BND4 = algorithm.AddEquity('IEF', self.resolution).Symbol # UGL/TLT
# self.LEV1 = algorithm.AddEquity('SPXL', self.resolution).Symbol
# self.LEV2 = algorithm.AddEquity('TQQQ', self.resolution).Symbol
# self.LEV3 = algorithm.AddEquity('URTY', self.resolution).Symbol
# self.LEV4 = algorithm.AddEquity('TMF', self.resolution).Symbol
self.STOCKS = [self.STK1, self.STK2, self.STK3, self.STK4, self.STK5, self.STK6, self.STK7]
#self.STOCKS_LEV = [self.LEV1, self.LEV2, self.LEV3]
self.BONDS = [self.BND1, self.BND2, self.BND3, self.BND4]
#self.BONDS_LEV = [self.LEV4]
self.ASSETS = self.STOCKS + self.BONDS #+ self.STOCKS_LEV + self.BONDS_LEV
self.data = dict()
self.dataWeek = dict()
for symbol in self.ASSETS:
self.consolidator = TradeBarConsolidator(timedelta(days=1))
self.consolidator.DataConsolidated += self.consolidation_handler
algorithm.SubscriptionManager.AddConsolidator(symbol, self.consolidator)
self.history = np.log(algorithm.History(self.ASSETS, self.VOLA + 1, self.resolution))
self.pfo = myPortfolioOptimizer(minWeight=0, maxWeight=1)
for symbol in self.ASSETS:
algorithm.Securities[symbol].SetLeverage(1)
def consolidation_handler(self, sender, consolidated):
self.history.loc[consolidated.EndTime, consolidated.Symbol] = consolidated.Close
self.history = self.history.iloc[-(self.VOLA + 1):]
def OnSecuritiesChanged(self, algorithm, changes):
addedSymbols = []
for security in changes.AddedSecurities:
addedSymbols.append(security.Symbol)
if security.Symbol not in self.data:
self.data[security.Symbol] = SymbolData(algorithm, security.Symbol, Resolution.Daily)
if len(addedSymbols) > 0:
history = algorithm.History(addedSymbols, self.VOLA + 1, self.resolution).loc[addedSymbols]
for symbol in addedSymbols:
try:
self.data[symbol].Warmup(history.loc[symbol])
except:
algorithm.Debug(str(symbol))
continue
def returns_custom(self, symbol, timeframe):
prices = np.log(algorithm.History(symbol, TimeSpan.FromDays(21), self.resolution).close)
return round((prices[-timeframe] - prices[-5]) / prices[-5], 4)
def calc_cndl_score(self, asset):
cndl_coef = sum([
self.data[asset].cndl_abandonedbaby.Current.Value,
self.data[asset].cndl_advanceblock.Current.Value,
self.data[asset].cndl_belthold.Current.Value,
self.data[asset].cndl_breakway.Current.Value,
self.data[asset].cndl_closingmarubozu.Current.Value,
self.data[asset].cndl_concealedbabyswallow.Current.Value,
self.data[asset].cndl_counterattack.Current.Value,
self.data[asset].cndl_darkcloudcover.Current.Value,
self.data[asset].cndl_doji.Current.Value,
self.data[asset].cndl_dojistar.Current.Value,
self.data[asset].cndl_dragonflydoji.Current.Value,
self.data[asset].cndl_engulfing.Current.Value,
self.data[asset].cndl_eveningdojistar.Current.Value,
self.data[asset].cndl_eveningstar.Current.Value,
self.data[asset].cndl_gapsidebysidewhite.Current.Value,
self.data[asset].cndl_gravestonedoji.Current.Value,
self.data[asset].cndl_hammer.Current.Value,
self.data[asset].cndl_hangingman.Current.Value,
self.data[asset].cndl_harami.Current.Value,
self.data[asset].cndl_haramicross.Current.Value,
self.data[asset].cndl_highwavecandle.Current.Value,
self.data[asset].cndl_hikkake.Current.Value,
self.data[asset].cndl_hikkakemodified.Current.Value,
self.data[asset].cndl_homingpigeon.Current.Value,
self.data[asset].cndl_identicalthreecrows.Current.Value,
self.data[asset].cndl_inneck.Current.Value,
self.data[asset].cndl_invertedhammer.Current.Value,
self.data[asset].cndl_kicking.Current.Value,
self.data[asset].cndl_kickingbylength.Current.Value,
self.data[asset].cndl_ladderbottom.Current.Value,
self.data[asset].cndl_longleggeddoji.Current.Value,
self.data[asset].cndl_longlinecandle.Current.Value,
self.data[asset].cndl_marubozu.Current.Value,
self.data[asset].cndl_mathold.Current.Value,
self.data[asset].cndl_matchinglow.Current.Value,
self.data[asset].cndl_morningdojistar.Current.Value,
self.data[asset].cndl_morningstar.Current.Value,
self.data[asset].cndl_onneck.Current.Value,
self.data[asset].cndl_pierce.Current.Value,
self.data[asset].cndl_rickshawman.Current.Value,
self.data[asset].cndl_risefallthreemethods.Current.Value,
self.data[asset].cndl_separatinglines.Current.Value,
self.data[asset].cndl_shootingstar.Current.Value,
self.data[asset].cndl_shortlinecandle.Current.Value,
self.data[asset].cndl_spinningtop.Current.Value,
self.data[asset].cndl_stalledpattern.Current.Value,
self.data[asset].cndl_sticksandwich.Current.Value,
self.data[asset].cndl_takuri.Current.Value,
self.data[asset].cndl_tasukigap.Current.Value,
self.data[asset].cndl_threeblackcrows.Current.Value,
self.data[asset].cndl_threeinside.Current.Value,
self.data[asset].cndl_threelinest.Current.Value,
self.data[asset].cndl_threeoutside.Current.Value,
self.data[asset].cndl_threestarsinsouth.Current.Value,
self.data[asset].cndl_threewhitesoldiers.Current.Value,
self.data[asset].cndl_thrusting.Current.Value,
self.data[asset].cndl_tristar.Current.Value,
self.data[asset].cndl_twocrows.Current.Value,
self.data[asset].cndl_uniquethreeriver.Current.Value,
self.data[asset].cndl_updowngapthreemethods.Current.Value,
self.data[asset].cndl_upsidegaptwocrows.Current.Value
])
return cndl_coef
def custom_filter(self, algorithm, symbol, filter_type = 'both'):
slope_cond = (self.data[symbol].roc_slope > 0.00) and (self.data[symbol].vol_slope > 0.00)
signals = (self.data[symbol].breakout or (self.data[symbol].vpnIndicator and (self.data[symbol].is_uptrend and self.data[symbol].trix_uptrend or (self.data[symbol].entry_signal and self.data[symbol].rsi_entry_signal and self.data[symbol].macd_entry_signal and self.data[symbol].williams_entry_signal and self.data[symbol].trix_entry_signal))) or (self.data[symbol].macd_uptrend and self.data[symbol].rsi_uptrend))
quick_signals = (self.data[symbol].vpnIndicator and (self.data[symbol].breakout or self.data[symbol].entry_signal or self.data[symbol].rsi_entry_signal or self.data[symbol].macd_entry_signal or self.data[symbol].williams_entry_signal or self.data[symbol].quick_up))
not_signals = (self.data[symbol].breakdown or ((not self.data[symbol].vpnIndicator) and (self.data[symbol].is_downtrend or (self.data[symbol].exit_signal and self.data[symbol].rsi_exit_signal and self.data[symbol].macd_exit_signal and self.data[symbol].williams_exit_signal))) or (self.data[symbol].macd_downtrend and self.data[symbol].rsi_downtrend))
hh_cond = self.data[symbol].hh and self.data[symbol].hh_all and self.data[symbol].hh_sum
ll_cond = self.data[symbol].ll and self.data[symbol].ll_all and self.data[symbol].ll_sum
rocsignal = all(x > 0.0 for x in [self.data[symbol].rocSignal_fast.Current.Value, self.data[symbol].rocSignal_med.Current.Value, self.data[symbol].rocSignal_long.Current.Value])
volsignal = all(x > 0.0 for x in [self.data[symbol].volSignal_fast.Current.Value, self.data[symbol].volSignal_med.Current.Value, self.data[symbol].volSignal_long.Current.Value])
roc_vol_signal = rocsignal and volsignal
median_zero = round(statistics.median([self.data[symbol].roc.Current.Value, self.data[symbol].roc_fast.Current.Value, self.data[symbol].roc_med.Current.Value, self.data[symbol].roc_long.Current.Value]), 4) > -3.00
median_vol_zero = round(statistics.median([self.data[symbol].vol_roc.Current.Value, self.data[symbol].vol_roc_fast.Current.Value, self.data[symbol].vol_roc_med.Current.Value, self.data[symbol].vol_roc_long.Current.Value]), 4) > -3.00
roc_any = any(x > -3.00 for x in [self.data[symbol].roc.Current.Value, self.data[symbol].roc_fast.Current.Value, self.data[symbol].roc_med.Current.Value, self.data[symbol].roc_long.Current.Value])
median_cond = median_zero and median_vol_zero and roc_any
if filter_type == 'both':
if (slope_cond) and (signals):
return True
else:
return False
if filter_type == 'either':
if (slope_cond) or (signals):
return True
else:
return False
if filter_type == 'quick':
if roc_vol_signal and quick_signals:
return True
else:
return False
if filter_type == 'lev':
if (slope_cond) and (self.data[symbol].median_roc_momentum >= 0.005) and (signals):
return True
else:
return False
def calc_vola(self, algorithm, sec):
prices = np.log(algorithm.History(sec, TimeSpan.FromDays(126), self.resolution).close)
volatility = prices.pct_change().std() * np.sqrt(252)
return volatility
def CreateTargets(self, algorithm, insights):
if algorithm.IsWarmingUp:
return []
targets = []
# We expect at most only one active insight since we only
# generate insights for one equity.
assert len(insights) <= 1
if len(insights) == 1:
insight = insights[0]
#if insight.Direction != InsightDirection.Flat:
williams_fast = ((self.data[self.STK1].williamsPR.Current.Value >= -95.00) and (self.data[self.STK2].williamsPR.Current.Value >= -95.00))
williams_slow = ((self.data[self.STK1].williamsPR_slow.Current.Value >= -95.00) and (self.data[self.STK2].williamsPR_slow.Current.Value >= -95.00))
williams_median = ((self.data[self.STK1].williams_median >= -80.00) and (self.data[self.STK2].williams_median >= -80.00))
williams = williams_fast and williams_slow and williams_median
hh_cond = all(self.data[symbol].hh for symbol in [self.STK1, self.STK2])
ll_cond = all(self.data[symbol].ll for symbol in [self.STK1, self.STK2])
market_uptrend = all(self.custom_filter(algorithm, symbol, filter_type = 'both') for symbol in [self.STK1, self.STK2, self.STK3, self.STK4]) and (hh_cond or (not ll_cond))
bond_uptrend = all(self.custom_filter(algorithm, symbol, filter_type = 'both') for symbol in [self.BND1, self.BND2, self.BND3, self.BND4]) and (all(self.data[symbol].hh for symbol in [self.BND1, self.BND2, self.BND3, self.BND4]) or (not all(self.data[symbol].ll for symbol in [self.BND1, self.BND2, self.BND3, self.BND4])))
if insight.Direction == InsightDirection.Down and williams and (not market_uptrend):
self.bull = False
elif not bond_uptrend:
self.bull = True
for sec in self.STOCKS:
#algorithm.Plot("RoC", str(sec), self.data[sec].roc.Current.Value*self.data[sec].vol_roc.Current.Value)
algorithm.Plot("RoC", str(sec), self.data[sec].roc.Current.Value)
# algorithm.Plot("RoC", str(sec)+"_fast", self.data[sec].roc_fast.Current.Value)
# algorithm.Plot("RoC", str(sec)+"_med", self.data[sec].roc_med.Current.Value)
# algorithm.Plot("RoC", str(sec)+"_long", self.data[sec].roc_long.Current.Value)
#algorithm.Plot("RoC STD", str(sec), self.data[sec].std_roc.Current.Value*self.data[sec].std_vol_roc.Current.Value)
algorithm.Plot("RoC STD", str(sec), self.data[sec].std_roc.Current.Value)
# algorithm.Plot("RoC STD", str(sec)+"_fast", self.data[sec].std_roc_fast.Current.Value)
# algorithm.Plot("RoC STD", str(sec)+"_med", self.data[sec].std_roc_med.Current.Value)
# algorithm.Plot("RoC STD", str(sec)+"_long", self.data[sec].std_roc_long.Current.Value)
selected = list()
if self.bull: # float(self.calc_vola(algorithm, symbol))
stocks = [(symbol, self.data[symbol].median_roc, self.data[symbol].scale, self.data[symbol].volatility) for symbol in self.STOCKS if self.custom_filter(algorithm, symbol, filter_type = 'both') is True]
stocks.sort(key=itemgetter(1, 2, 3), reverse=True)
for sec, roc, vpn, vola in stocks:
if (len(selected) < 2):
selected.append(sec)
if len(selected) < 2:
stocks = [(symbol, self.data[symbol].median_roc, self.data[symbol].scale, self.data[symbol].volatility) for symbol in self.STOCKS if self.custom_filter(algorithm, symbol, filter_type = 'either') is True]
stocks.sort(key=itemgetter(1, 2, 3), reverse=True)
for sec, roc, vpn, vola in stocks:
if (len(selected) < 2) and (sec not in selected):
selected.append(sec)
elif not self.bull:
bonds = [(symbol, self.data[symbol].median_roc, self.data[symbol].scale, self.data[symbol].volatility) for symbol in self.BONDS if self.custom_filter(algorithm, symbol, filter_type = 'both') is True]
bonds.sort(key=itemgetter(1, 2, 3), reverse=True)
for sec, roc, vpn, vola in bonds:
if (len(selected) < 2):
selected.append(sec)
if len(selected) < 2:
bonds = [(symbol, self.data[symbol].median_roc, self.data[symbol].scale, self.data[symbol].volatility) for symbol in self.BONDS if self.custom_filter(algorithm, symbol, filter_type = 'either') is True]
bonds.sort(key=itemgetter(1, 2, 3), reverse=True)
for sec, roc, vpn, vola in bonds:
if (len(selected) < 2) and (sec not in selected):
selected.append(sec)
# if insight.Direction == InsightDirection.Flat:
# return []
# self.asset_weights = self.pfo.CalcWeights(algorithm, selected, 'riskParity', lookback=21)
# self.asset_weights_max = self.pfo.CalcWeights(algorithm, selected, 'maxReturn', lookback=21)
# self.asset_weights_max_two = self.pfo.CalcWeights(algorithm, selected, 'maxReturn', lookback=42)
for asset in self.ASSETS:
if asset in selected:
# weight = self.asset_weights[self.asset_weights.index == str(asset.Value)][0]
# weight_max = self.asset_weights_max_two[self.asset_weights_max_two.index == str(asset.Value)][0]
cond_both = self.custom_filter(algorithm, asset, filter_type = 'both')
cond_either = self.custom_filter(algorithm, asset, filter_type = 'either')
rocsignal = all(x > 0.0 for x in [self.data[asset].rocSignal_quick.Current.Value, self.data[asset].rocSignal_fast.Current.Value, self.data[asset].rocSignal_med.Current.Value, self.data[asset].rocSignal_long.Current.Value])
volsignal = all(x > 0.0 for x in [self.data[asset].volSignal_quick.Current.Value, self.data[asset].volSignal_fast.Current.Value, self.data[asset].volSignal_med.Current.Value, self.data[asset].volSignal_long.Current.Value])
roc_vol_signal = rocsignal and volsignal
cond1 = ((self.calc_cndl_score(asset) > 0) and cond_both)
cond2 = ((self.calc_cndl_score(asset) >= -2) or (cond_both and self.data[asset].cndl_uptrend))
cond3 = ((self.calc_cndl_score(asset) >= -2) or (cond_either and self.data[asset].cndl_uptrend))
if (algorithm.Portfolio[asset].Invested and (cond2 or cond3)) or cond1:
targets.append(PortfolioTarget.Percent(algorithm, asset, 0.5))
elif not algorithm.Portfolio[asset].Invested and (cond2 or cond3):
if roc_vol_signal:
targets.append(PortfolioTarget.Percent(algorithm, asset, 0.25))
else:
targets.append(PortfolioTarget.Percent(algorithm, asset, 0.1))
else:
targets.append(PortfolioTarget.Percent(algorithm, asset, 0.0))
return targetsfrom 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
class SymbolData(object):
def __init__(self, algorithm, symbol, resolution = Resolution.Daily):
self.Symbol = symbol
self.res = Resolution.Daily
self.lookback = 20
self.ceiling = 30
self.floor = 10
self.breakout = False
self.breakdown = False
self.quick_up = False
self.quick_down = False
self.hh_all = False
self.ll_all = False
self.hh_sum = False
self.ll_sum = False
self.EXCL = 21
self.scale = 0.00
self.is_uptrend = False
self.is_downtrend = False
self.volatility = 0.00
self.PriceIsFavorable = False
self.vwap = IntradayVwap()
self.SpreadIsFavorable = False
self.tolerance = 0.98
self.acceptingSpreadPercent = 0.001
self.vol_slope = 0.00
self.vol_fast_slope = 0.00
self.roc_slope = 0.00
self.roc_fast_slope = 0.00
self.median_roc = 0.00
self.median_roc_std = 0.00
self.median_roc_hh = False
self.median_roc_ll = False
self.median_vol = 0.00
self.stochasticFast = Stochastic(14, 3, 3)
self.fast = VolumeWeightedAveragePriceIndicator(int(8*1.0))
self.fast_window = RollingWindow[float](41)
self.stochasticSlow = Stochastic(21, 3, 3)
self.slow = VolumeWeightedAveragePriceIndicator(int(14*1.0))
self.slow_window = 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.roc_Window = SmartRollingWindow("float", 5)
self.roc_fast_Window = SmartRollingWindow("float", 5)
self.roc_med_Window = SmartRollingWindow("float", 5)
self.roc_long_Window = SmartRollingWindow("float", 5)
self.std_roc = IndicatorExtensions.Of(StandardDeviation(5),self.roc)
self.std_roc_fast = IndicatorExtensions.Of(StandardDeviation(3),self.roc_fast)
self.std_roc_med = IndicatorExtensions.Of(StandardDeviation(8),self.roc_med)
self.std_roc_long = IndicatorExtensions.Of(StandardDeviation(14),self.roc_long)
self.std_roc_Window = SmartRollingWindow("float", 5)
self.std_roc_fast_Window = SmartRollingWindow("float", 5)
self.std_roc_med_Window = SmartRollingWindow("float", 5)
self.std_roc_long_Window = SmartRollingWindow("float", 5)
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.vol_roc_Window = SmartRollingWindow("float", 5)
self.vol_roc_fast_Window = SmartRollingWindow("float", 5)
self.vol_roc_med_Window = SmartRollingWindow("float", 5)
self.vol_roc_long_Window = SmartRollingWindow("float", 5)
self.std_vol_roc = IndicatorExtensions.Of(StandardDeviation(5),self.vol_roc)
self.std_vol_roc_fast = IndicatorExtensions.Of(StandardDeviation(3),self.vol_roc_fast)
self.std_vol_roc_med = IndicatorExtensions.Of(StandardDeviation(8),self.vol_roc_med)
self.std_vol_roc_long = IndicatorExtensions.Of(StandardDeviation(14),self.vol_roc_long)
self.std_vol_roc_Window = SmartRollingWindow("float", 5)
self.std_vol_roc_fast_Window = SmartRollingWindow("float", 5)
self.std_vol_roc_med_Window = SmartRollingWindow("float", 5)
self.std_vol_roc_long_Window = SmartRollingWindow("float", 5)
self.roc_window = RollingWindow[float](5)
self.roclen_window = RollingWindow[float](41)
self.rocSum_window = RollingWindow[float](41)
self.vol_window = RollingWindow[float](5)
self.prices_window = RollingWindow[float](126)
self.low_window = RollingWindow[float](41)
self.high_window = RollingWindow[float](41)
self.roc_prices_window = RollingWindow[float](41)
self.roc_prices_std_window = RollingWindow[float](41)
self.roc_prices_lev_window = RollingWindow[float](10)
self.roc_volume_window = RollingWindow[float](41)
self.stochasticMACD = Stochastic(34, 3, 3)
self.macd = MovingAverageConvergenceDivergence(12, 26, 9, MovingAverageType.Exponential)
self.macd_stochfast_window = RollingWindow[float](5)
self.macdStochFastWindow = SmartRollingWindow("float", 5)
self.macd_stochk_window = RollingWindow[float](5)
self.macdStochKWindow = SmartRollingWindow("float", 5)
self.macd_stochd_window = RollingWindow[float](5)
self.macdStochDWindow = SmartRollingWindow("float", 5)
self.macd_window = RollingWindow[float](5)
self.macdHist_window = RollingWindow[float](5)
self.macdFast_window = RollingWindow[float](5)
self.macdSlow_window = RollingWindow[float](5)
self.macdSignal_window = RollingWindow[float](5)
self.macdDelta_window = RollingWindow[float](5)
self.macd_uptrend = False
self.macd_downtrend = False
self.macd_entry_signal = False
self.macd_exit_signal = False
self.stochasticRSI = Stochastic(21, 3, 3)
self.rsi = RelativeStrengthIndex(14, MovingAverageType.Wilders)
self.rsi_window = RollingWindow[float](5)
self.rsiWindow = SmartRollingWindow("float", 5)
self.rsiFastStoch_window = RollingWindow[float](5)
self.rsiStochFastWindow = SmartRollingWindow("float", 5)
self.rsiStochK_window = RollingWindow[float](5)
self.rsiStochKWindow = SmartRollingWindow("float", 5)
self.rsiStochD_window = RollingWindow[float](5)
self.rsiStochDWindow = SmartRollingWindow("float", 5)
self.rsi_uptrend = False
self.rsi_downtrend = False
self.rsi_entry_signal = False
self.rsi_exit_signal = False
self.williamsPR = WilliamsPercentR(14)
self.williamsPR_slow = WilliamsPercentR(21)
self.williamsWindow = RollingWindow[float](5)
self.williamsPR_window = RollingWindow[float](5)
self.williamsPRWindow = SmartRollingWindow("float", 5)
self.williamsPR_slow_window = RollingWindow[float](5)
self.williamsPR_slowWindow = SmartRollingWindow("float", 5)
self.williams_median_roc = 0.00
self.williams_median = 0.00
self.williams_uptrend = False
self.williams_downtrend = False
self.vpnIndicator = False
self.vpnScale = 0.00
self.vpn_period = 10
self.atr = AverageTrueRange(self.vpn_period, MovingAverageType.Exponential)
self.vpn_vol_window = RollingWindow[float](self.vpn_period)
self.vpn_hlc_window = RollingWindow[float](self.vpn_period)
self.vpn_lst = RollingWindow[float](6)
self.stochasticTrix = Stochastic(21, 3, 3)
self.trix = Trix(9)
self.trix_slow = Trix(18)
self.trixFastStoch_window = RollingWindow[float](5)
self.trixStochFastWindow = SmartRollingWindow("float", 5)
self.trixStochK_window = RollingWindow[float](5)
self.trixStochKWindow = SmartRollingWindow("float", 5)
self.trixStochD_window = RollingWindow[float](5)
self.trixStochDWindow = SmartRollingWindow("float", 5)
self.trix_uptrend = False
self.trix_downtrend = False
self.trix_entry_signal = False
self.trix_exit_signal = 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_Window = RollingWindow[float](5)
self.rocvolSignal_median = 0.00
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", 5)
self.kalWindowLow = SmartRollingWindow("float", 5)
self.kalWindowHigh = SmartRollingWindow("float", 5)
self.priceWindow = SmartRollingWindow("float", 5)
self.priceWindowLow = SmartRollingWindow("float", 5)
self.priceWindowHigh = SmartRollingWindow("float", 5)
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.candleWindow = SmartRollingWindow("float", 5)
self.candleavgWindow = SmartRollingWindow("float", 5)
self.candleContainer = RollingWindow[float](2)
self.cndl_uptrend = False
self.cndl_downtrend = False
self.candlescore = 0.00
if self.res == Resolution.Daily:
consolidator = algorithm.ResolveConsolidator(symbol, self.res)
tf_coef = 1
else:
consolidator = TradeBarConsolidator(timedelta(minutes=240))
tf_coef = 6
self.indicators = [self.roc, self.roc_fast, self.roc_med, self.roc_long,
self.std_roc, self.std_roc_fast, self.std_roc_med, self.std_roc_long,
self.vol_roc, self.vol_roc_fast, self.vol_roc_med, self.vol_roc_long,
self.std_vol_roc, self.std_vol_roc_fast, self.std_vol_roc_med, self.std_vol_roc_long,
self.vwap, self.fast, self.stochasticFast, self.slow, self.stochasticSlow,
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.res)
algorithm.RegisterIndicator(symbol, indicator, consolidator)
# Warm up
history = algorithm.History(symbol, 126*tf_coef, self.res)
if history.empty or 'close' not in history.columns:
return
for index, row in history.loc[symbol].iterrows():
tradeBar = TradeBar(index, row['open'], row['high'], row['low'], row['close'], row['volume'])
median_price = round(float(statistics.median([row['open'], row['high'], row['low'], row['close']])), 4)
self.roc.Update(index, median_price)
self.roc_fast.Update(index, median_price)
self.roc_med.Update(index, median_price)
self.roc_long.Update(index, median_price)
self.rocSignal_quick.Update(index, median_price)
self.rocSignal_fast.Update(index, median_price)
self.rocSignal_med.Update(index, median_price)
self.rocSignal_long.Update(index, median_price)
self.vol_roc.Update(index, row['volume'])
self.vol_roc_fast.Update(index, row['volume'])
self.vol_roc_med.Update(index, row['volume'])
self.vol_roc_long.Update(index, row['volume'])
self.volSignal_quick.Update(index, row['volume'])
self.volSignal_fast.Update(index, row['volume'])
self.volSignal_med.Update(index, row['volume'])
self.volSignal_long.Update(index, row['volume'])
self.atr.Update(tradeBar)
self.macd.Update(index, median_price)
self.fast.Update(tradeBar)
self.slow.Update(tradeBar)
self.williamsPR.Update(tradeBar)
self.williamsPR_slow.Update(tradeBar)
self.rsi.Update(index, median_price)
self.trix.Update(index, median_price)
self.trix_slow.Update(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)
def calc_divergence(obj):
x = np.array(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)
# All higher highs
hh = all(x[local_maxima][i] <= x[local_maxima][i+1] for i in range(len(local_maxima)-1))
# All lower lows
ll = all(x[local_minima][i] >= x[local_minima][i+1] for i in range(len(local_minima)-1))
return hh, ll
# Stochastic RSI
if self.rsi.IsReady:
rsi = self.rsi.Current.Value
trade_bar = TradeBar(index, rsi, rsi, rsi, rsi, 0)
self.stochasticRSI.Update(trade_bar)
if self.stochasticRSI.IsReady:
self.rsi_window.Add(rsi)
self.rsiWindow.Add(rsi)
self.rsiFastStoch_window.Add(self.stochasticRSI.FastStoch.Current.Value)
self.rsiStochFastWindow.Add(self.stochasticRSI.FastStoch.Current.Value)
self.rsiStochK_window.Add(self.stochasticRSI.StochK.Current.Value)
self.rsiStochKWindow.Add(self.stochasticRSI.StochK.Current.Value)
self.rsiStochD_window.Add(self.stochasticRSI.StochD.Current.Value)
self.rsiStochDWindow.Add(self.stochasticRSI.StochD.Current.Value)
if self.rsi_window.IsReady:
rsi_lst = list(self.rsi_window)
rsifast_lst = list(self.rsiFastStoch_window)
rsistochk_lst = list(self.rsiStochK_window)
rsistochd_lst = list(self.rsiStochD_window)
cur_rsi, pre_rsi, lst_rsi = rsi_lst[-1], rsi_lst[-2], rsi_lst[-3]
cur_fast, pre_fast, lst_fast = rsifast_lst[-1], rsifast_lst[-2], rsifast_lst[-3]
cur_stochk, pre_stochk, lst_stochk = rsistochk_lst[-1], rsistochk_lst[-2], rsistochk_lst[-3]
cur_stochd, pre_stochd, lst_stochd = rsistochd_lst[-1], rsistochd_lst[-2], rsistochd_lst[-3]
cond1 = (cur_fast >= cur_stochk*self.tolerance) and (cur_fast >= cur_stochd*self.tolerance) and (cur_stochk >= cur_stochd*self.tolerance)
cond2 = (cur_rsi >= pre_rsi*self.tolerance) and (cur_fast >= pre_fast*self.tolerance) and (cur_stochk >= pre_stochk*self.tolerance) and (cur_stochd >= pre_stochd*self.tolerance)
cond3 = (pre_rsi >= lst_rsi*self.tolerance) and (pre_fast >= lst_fast*self.tolerance) and (pre_stochk >= lst_stochk*self.tolerance) and (pre_stochd >= lst_stochd*self.tolerance)
cond4 = (cur_fast <= cur_stochk*self.tolerance) and (cur_fast <= cur_stochd*self.tolerance) and (cur_stochk <= cur_stochd*self.tolerance)
cond5 = (cur_rsi <= pre_rsi*self.tolerance) and (cur_fast <= pre_fast*self.tolerance) and (cur_stochk <= pre_stochk*self.tolerance) and (cur_stochd <= pre_stochd*self.tolerance)
cond6 = (pre_rsi <= lst_rsi*self.tolerance) and (pre_fast <= lst_fast*self.tolerance) and (pre_stochk <= lst_stochk*self.tolerance) and (pre_stochd <= lst_stochd*self.tolerance)
hh_rsi, ll_rsi = calc_divergence(rsi_lst)
hh_rsifast, ll_rsifast = calc_divergence(rsifast_lst)
hh_rsik, ll_rsik = calc_divergence(rsistochk_lst)
hh_rsid, ll_rsid = calc_divergence(rsistochd_lst)
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
if (cond4 and cond8) and (cond5 and cond6):
self.rsi_downtrend = True
exit = self.rsiStochFastWindow.crossedBelow(self.rsiWindow) and self.rsiStochFastWindow.crossedBelow(self.rsiStochKWindow) and self.rsiStochKWindow.crossedBelow(self.rsiStochDWindow)
entry = self.rsiStochFastWindow.crossedAbove(self.rsiWindow) and self.rsiStochFastWindow.crossedAbove(self.rsiStochKWindow) and self.rsiStochKWindow.crossedAbove(self.rsiStochDWindow)
if algorithm.Portfolio[symbol].Invested:
if exit:
self.rsi_exit_signal = True
if not algorithm.Portfolio[symbol].Invested:
if entry:
self.rsi_entry_signal = True
# MACD Trend
if self.macd.IsReady:
macd = self.macd.Current.Value
trade_bar = TradeBar(index, 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_stochfast = self.stochasticMACD.FastStoch.Current.Value
macd_stochk = self.stochasticMACD.StochK.Current.Value
macd_stochd = self.stochasticMACD.StochD.Current.Value
self.macd_window.Add(macd)
self.macdFast_window.Add(macd_fast)
self.macdSlow_window.Add(macd_slow)
self.macdHist_window.Add(macd_hist)
self.macdSignal_window.Add(signal)
self.macdDelta_window.Add(delta)
self.macd_stochfast_window.Add(macd_stochfast)
self.macdStochFastWindow.Add(macd_stochfast)
self.macd_stochk_window.Add(macd_stochk)
self.macdStochKWindow.Add(macd_stochk)
self.macd_stochd_window.Add(macd_stochd)
self.macdStochDWindow.Add(macd_stochd)
if self.macd_window.IsReady:
macd_lst = list(self.macd_window)
macdhist_lst = list(self.macdHist_window)
macdfast_lst = list(self.macdFast_window)
macdslow_lst = list(self.macdSlow_window)
macdsignal_lst = list(self.macdSignal_window)
macddelta_lst = list(self.macdDelta_window)
macdstochfast_lst = list(self.macd_stochfast_window)
macdstochk_lst = list(self.macd_stochk_window)
macdstochd_lst = list(self.macd_stochd_window)
cur_macd, pre_macd, lst_macd = macd_lst[-1], macd_lst[-2], macd_lst[-3]
cur_macd_fast, pre_macd_fast, lst_macd_fast = macdfast_lst[-1], macdfast_lst[-2], macdfast_lst[-3]
cur_macd_slow, pre_macd_slow, lst_macd_slow = macdslow_lst[-1], macdslow_lst[-2], macdslow_lst[-3]
cur_macd_hist, pre_macd_hist, lst_macd_hist = macdhist_lst[-1], macdhist_lst[-2], macdhist_lst[-3]
cur_signal, pre_signal, lst_signal = macdsignal_lst[-1], macdsignal_lst[-2], macdsignal_lst[-3]
cur_delta, pre_delta, lst_delta = macddelta_lst[-1], macddelta_lst[-2], macddelta_lst[-3]
cur_macdstochfast, pre_macdstochfast, lst_macdstochfast = macdstochfast_lst[-1], macdstochfast_lst[-2], macdstochfast_lst[-3]
cur_macdstochk, pre_macdstochk, lst_macdstochk = macdstochk_lst[-1], macdstochk_lst[-2], macdstochk_lst[-3]
cur_macdstochd, pre_macdstochd, lst_macdstochd = macdstochd_lst[-1], macdstochd_lst[-2], macdstochd_lst[-3]
cond1 = ((cur_macd_hist-cur_delta)>=0.0025) and (cur_macd >= cur_signal*self.tolerance) and (cur_macdstochfast >= cur_macdstochk*self.tolerance) and (cur_macdstochk >= cur_macdstochd*self.tolerance)
cond2 = (cur_macd >= pre_macd*self.tolerance) and (cur_macd_fast >= pre_macd_fast*self.tolerance) and (cur_macd_hist >= pre_macd_hist*self.tolerance) and (cur_signal >= pre_signal*self.tolerance)
cond3 = (pre_macd >= lst_macd*self.tolerance) and (pre_macd_fast >= lst_macd_fast*self.tolerance) and (pre_macd_hist >= lst_macd_hist*self.tolerance) and (pre_signal >= lst_signal*self.tolerance)
cond4 = ((cur_macd_hist-cur_delta) <= -0.0025) and (cur_macd <= cur_signal*self.tolerance) and (cur_macdstochfast <= cur_macdstochk*self.tolerance) and (cur_macdstochk <= cur_macdstochd*self.tolerance)
cond5 = (cur_macd <= pre_macd*self.tolerance) and (cur_macd_fast <= pre_macd_fast*self.tolerance) and (cur_macd_hist <= pre_macd_hist*self.tolerance) and (cur_signal <= pre_signal*self.tolerance)
cond6 = (pre_macd <= lst_macd*self.tolerance) and (pre_macd_fast <= lst_macd_fast*self.tolerance) and (pre_macd_hist <= lst_macd_hist*self.tolerance) and (pre_signal <= lst_signal*self.tolerance)
hh_macd, ll_macd = calc_divergence(macd_lst)
hh_macdhist, ll_macdhist = calc_divergence(macdhist_lst)
hh_macdfast, ll_macdfast = calc_divergence(macdfast_lst)
hh_macdslow, ll_macdslow = calc_divergence(macdslow_lst)
hh_macdsignal, ll_macdsignal = calc_divergence(macdsignal_lst)
hh_macdstochfast, ll_macdstochfast = calc_divergence(macdstochfast_lst)
hh_macdstochk, ll_macdstochk = calc_divergence(macdstochk_lst)
hh_macdstochd, ll_macdstochd = calc_divergence(macdstochd_lst)
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
if (cond4 and cond8) and (cond5 and cond6):
self.macd_downtrend = True
exit = self.macdStochFastWindow.crossedBelow(self.macdStochKWindow) and self.macdStochKWindow.crossedBelow(self.macdStochDWindow)
entry = self.macdStochFastWindow.crossedAbove(self.macdStochKWindow) and self.macdStochKWindow.crossedAbove(self.macdStochDWindow)
if algorithm.Portfolio[symbol].Invested:
if exit:
self.macd_exit_signal = True
if not algorithm.Portfolio[symbol].Invested:
if entry:
self.macd_entry_signal = True
# if self.roc.IsReady and self.roc_fast.IsReady and self.roc_med.IsReady and self.roc_long.IsReady:
# # self.roc_Window.Add(self.roc.Current.Value)
# # self.roc_fast_Window.Add(self.roc_fast.Current.Value)
# # self.roc_med_Window.Add(self.roc_med.Current.Value)
# # self.roc_long_Window.Add(self.roc_long.Current.Value)
# self.std_roc_Window.Add(self.std_roc.Current.Value)
# self.std_roc_fast_Window.Add(self.std_roc_fast.Current.Value)
# self.std_roc_med_Window.Add(self.std_roc_med.Current.Value)
# self.std_roc_long_Window.Add(self.std_roc_long.Current.Value)
# # self.vol_roc_Window.Add(self.vol_roc.Current.Value)
# # self.vol_roc_fast_Window.Add(self.vol_roc_fast.Current.Value)
# # self.vol_roc_med_Window.Add(self.vol_roc_med.Current.Value)
# # self.vol_roc_long_Window.Add(self.vol_roc_long.Current.Value)
# # self.std_vol_roc_Window.Add(self.std_vol_roc.Current.Value)
# # self.std_vol_roc_fast_Window.Add(self.std_vol_roc_fast.Current.Value)
# # self.std_vol_roc_med_Window.Add(self.std_vol_roc_med.Current.Value)
# # self.std_vol_roc_long_Window.Add(self.std_vol_roc_long.Current.Value)
# if self.std_roc_fast_Window.IsReady and self.std_roc_Window.IsReady and self.std_roc_med_Window.IsReady and self.std_roc_long_Window.IsReady:
# entry = self.std_roc_fast_Window.crossedAbove(self.std_roc_Window)# and self.roc_Window.crossedAbove(self.roc_med_Window) and self.roc_med_Window.crossedAbove(self.roc_long_Window)
# exit = self.std_roc_fast_Window.crossedBelow(self.std_roc_Window)# and self.roc_Window.crossedBelow(self.roc_med_Window) and self.roc_med_Window.crossedBelow(self.roc_long_Window)
# if algorithm.Portfolio[symbol].Invested:
# if exit:
# self.roc_exit_signal = True
# if not algorithm.Portfolio[symbol].Invested:
# if entry:
# self.roc_entry_signal = True
def roc_calc(obj):
obj_lst = list(obj)
output_lst = list()
for i in range(-1, -len(obj_lst)+1, -1):
if obj_lst[i-1] != 0:
val = round((obj_lst[i] - obj_lst[i-1])/obj_lst[i-1], 4)
else:
val = 0
output_lst.append(val)
return output_lst
self.roc_window.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_window.IsReady:
val = statistics.median(roc_calc(self.roc_window))
roc_sum, roc_len = sum(list(self.roc_window)), len(list(self.roc_window))
self.roc_slope = round(float(roc_sum)/roc_len, 4)
vol_sum, vol_len = sum(list(self.roc_window)[-3:-1]), len(list(self.roc_window)[-3:-1])
self.roc_fast_slope = round(float(vol_sum)/vol_len, 4)
self.roc_hh, self.roc_ll = hh_ll_calc(self.roc_window)
self.quick_up = all(x > 0.0 for x in [self.roc_fast_slope, self.volSignal_quick.Current.Value])
self.quick_down = all(x < 0.0 for x in [self.roc_fast_slope, self.volSignal_quick.Current.Value])
def hh_ll_calc(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_window.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_window.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_window.IsReady:
self.hh_all, self.ll_all = hh_ll_calc(self.roclen_window)
self.hh_sum, self.ll_sum = hh_ll_calc(self.rocSum_window)
self.vol_window.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_window.IsReady:
val = statistics.median(roc_calc(self.vol_window))
vol_sum, vol_len = sum(list(self.vol_window)), len(list(self.vol_window))
self.vol_slope = round(float(vol_sum)/vol_len, 4)
vol_sum, vol_len = sum(list(self.vol_window)[-3:-1]), len(list(self.vol_window)[-3:-1])
self.vol_fast_slope = round(float(vol_sum)/vol_len, 4)
self.vol_hh, self.vol_ll = hh_ll_calc(self.vol_window)
self.roc_prices_window.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_std_window.Add(round(statistics.median([self.std_roc.Current.Value, self.std_roc_fast.Current.Value, self.std_roc_med.Current.Value, self.std_roc_long.Current.Value]), 4))
self.roc_prices_lev_window.Add(round(statistics.median([self.roc.Current.Value, self.roc_fast.Current.Value, self.roc_med.Current.Value]), 4))
self.roc_volume_window.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_window.Add(row['close'])
if self.prices_window.IsReady and self.roc_prices_window.IsReady and self.roc_prices_std_window.IsReady:
prices = list(self.roc_prices_window)
prices_std = list(self.roc_prices_std_window)
volumes = list(self.roc_volume_window)
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_window)
_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)
v1_std = round(statistics.median([round(float(prices_std[i] - prices_std[i-5]/ prices_std[i-5]), 4) if prices_std[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)
v11_std = round(statistics.median([round(float(prices_std[i] - prices_std[i-5]/ prices_std[i-5]), 4) if prices_std[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_std = v1_std #if (v1_std > v11_std) 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)
self.median_roc_hh, self.median_roc_ll = hh_ll_calc(roc_calc(prices))
self.median_vol_hh, self.median_vol_ll = hh_ll_calc(roc_calc(volumes))
C = list(self.prices_window)
avg = sum(list(self.prices_window))/len(list(self.prices_window))
self.volatility = float(np.sqrt(252)*reduce(lambda a,b:a+abs(avg-b),C,0)/len(C))/C[-1]
self.hh, self.ll = hh_ll_calc(self.prices_window)
rocsignal_up = all(x > 0.0 for x in [self.rocSignal_quick.Current.Value, self.rocSignal_fast.Current.Value, self.rocSignal_med.Current.Value, self.rocSignal_long.Current.Value])
rocsignal_down = all(x < 0.0 for x in [self.rocSignal_quick.Current.Value, self.rocSignal_fast.Current.Value, self.rocSignal_med.Current.Value, self.rocSignal_long.Current.Value])
volsignal = all(x > 0.0 for x in [self.volSignal_quick.Current.Value, self.volSignal_fast.Current.Value, self.volSignal_med.Current.Value, self.volSignal_long.Current.Value])
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)
if self.williamsPR.IsReady and self.williamsPR_slow.IsReady:
self.williamsPR_window.Add(self.williamsPR.Current.Value)
self.williamsPRWindow.Add(self.williamsPR.Current.Value)
self.williamsPR_slow_window.Add(self.williamsPR_slow.Current.Value)
self.williamsPR_slowWindow.Add(self.williamsPR_slow.Current.Value)
if self.williamsPR_window.IsReady and self.williamsPRWindow.IsReady and self.williamsPR_slow_window.IsReady and self.williamsPR_slowWindow.IsReady:
wills_lst = list(self.williamsPR_window)
willss_lst = list(self.williamsPR_slow_window)
cur_wills, pre_wills, lst_wills = wills_lst[-1], wills_lst[-2], wills_lst[-3]
cur_willss, pre_willss, lst_willss = willss_lst[-1], willss_lst[-2], willss_lst[-3]
cond1 = (cur_wills >= cur_willss*self.tolerance)
cond2 = (cur_wills >= pre_wills*self.tolerance) and (cur_willss >= pre_willss*self.tolerance)
cond3 = (pre_wills >= lst_wills*self.tolerance) and (pre_willss >= lst_willss*self.tolerance)
cond4 = (cur_wills <= cur_willss*self.tolerance)
cond5 = (cur_wills <= pre_wills*self.tolerance) and (cur_willss <= pre_willss*self.tolerance)
cond6 = (pre_wills <= lst_wills*self.tolerance) and (pre_willss <= lst_willss*self.tolerance)
hh_wills, ll_wills = calc_divergence(wills_lst)
hh_willss, ll_willss = calc_divergence(willss_lst)
cond7 = hh_wills, hh_willss
cond8 = ll_wills, ll_willss
if (cond1 and cond7) and (cond2 and cond3):
self.williams_uptrend = True
if (cond4 and cond8) and (cond5 and cond6):
self.williams_downtrend = True
exit = self.williamsPRWindow.crossedBelow(self.williamsPR_slowWindow)
entry = self.williamsPRWindow.crossedAbove(self.williamsPR_slowWindow)
if algorithm.Portfolio[symbol].Invested:
if exit:
self.williams_exit_signal = True
if not algorithm.Portfolio[symbol].Invested:
if entry:
self.williams_entry_signal = True
self.high_window.Add(row['high'])
self.low_window.Add(row['low'])
if self.high_window.IsReady and self.low_window.IsReady and self.prices_window.IsReady:
close = list(self.prices_window)
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_window)
low = list(self.low_window)
# Buy in case of breakout
breakout_condition1 = (algorithm.Securities[symbol].Close >= max(high[:-1]))
if not algorithm.Portfolio[symbol].Invested:
if breakout_condition1:
self.breakout = True
breakdown_condition1 = (algorithm.Securities[symbol].Close <= min(low[:-1]))
if algorithm.Portfolio[symbol].Invested:
if breakdown_condition1:
self.breakdown = True
fast = self.fast.Current.Value
slow = self.slow.Current.Value
fastBar = TradeBar(index, fast, fast, fast, fast, 0)
self.stochasticFast.Update(fastBar)
slowBar = TradeBar(index, slow, slow, slow, slow, 0)
self.stochasticSlow.Update(slowBar)
if self.stochasticFast.IsReady and self.stochasticSlow.IsReady:
fast_stoch = self.stochasticFast.FastStoch.Current.Value
fast_stochk = self.stochasticFast.StochK.Current.Value
fast_stochd = self.stochasticFast.StochD.Current.Value
slow_stoch = self.stochasticSlow.FastStoch.Current.Value
slow_stochk = self.stochasticSlow.StochK.Current.Value
slow_stochd = self.stochasticSlow.StochD.Current.Value
fast_cond = ((fast >= fast_stochk*self.tolerance) and (fast_stoch >= fast_stochk*self.tolerance) and (fast_stochk >= fast_stochd*self.tolerance))
slow_cond = ((slow >= slow_stochk*self.tolerance) and (slow_stoch >= slow_stochk*self.tolerance) and (slow_stochk >= slow_stochd*self.tolerance))
self.is_uptrend = ((fast) >= slow*self.tolerance) and (row['close'] >= slow*self.tolerance) and fast_cond and slow_cond
fast_cond = ((fast <= fast_stochk*self.tolerance) and (fast_stoch <= fast_stochk*self.tolerance) and (fast_stochk <= fast_stochd*self.tolerance))
slow_cond = ((slow <= slow_stochk*self.tolerance) and (slow_stoch <= slow_stochk*self.tolerance) and (slow_stochk <= slow_stochd*self.tolerance))
self.is_downtrend = ((fast) <= slow*self.tolerance) and (row['close'] <= slow*self.tolerance) and fast_cond and slow_cond
if self.is_uptrend:
# triangle formula
# base * height * 0.5
self.scale = round(float(fast - slow) / ((fast+slow)/2.0), 4) if (fast+slow) != 0.0 else 0
else:
self.scale = 0.00
if self.trix.IsReady:
trix = self.trix.Current.Value
trixBar = TradeBar(index, trix, trix, trix, trix, 0)
self.stochasticTrix.Update(trixBar)
if self.stochasticTrix.IsReady:
self.trixFastStoch_window.Add(self.stochasticTrix.FastStoch.Current.Value)
self.trixStochFastWindow.Add(self.stochasticTrix.FastStoch.Current.Value)
self.trixStochK_window.Add(self.stochasticTrix.StochK.Current.Value)
self.trixStochKWindow.Add(self.stochasticTrix.StochK.Current.Value)
self.trixStochD_window.Add(self.stochasticTrix.StochD.Current.Value)
self.trixStochDWindow.Add(self.stochasticTrix.StochD.Current.Value)
if self.trixFastStoch_window.IsReady:
trix_lst = list(self.trixFastStoch_window)
trixfast_lst = list(self.trixFastStoch_window)
trixstochk_lst = list(self.trixStochK_window)
trixstochd_lst = list(self.trixStochD_window)
cur_trix, pre_trix, lst_trix = trix_lst[-1], trix_lst[-2], trix_lst[-3]
cur_fast, pre_fast, lst_fast = trixfast_lst[-1], trixfast_lst[-2], trixfast_lst[-3]
cur_stochk, pre_stochk, lst_stochk = trixstochk_lst[-1], trixstochk_lst[-2], trixstochk_lst[-3]
cur_stochd, pre_stochd, lst_stochd = trixstochd_lst[-1], trixstochd_lst[-2], trixstochd_lst[-3]
cond1 = (cur_trix >= cur_stochk*self.tolerance) and (cur_fast >= cur_stochk*self.tolerance) and (cur_stochk >= cur_stochd*self.tolerance)
cond2 = (cur_trix >= pre_trix*self.tolerance) and (cur_fast >= pre_fast*self.tolerance) and (cur_stochk >= pre_stochk*self.tolerance) and (cur_stochd >= pre_stochd*self.tolerance)
cond3 = (pre_trix >= lst_trix*self.tolerance) and (pre_fast >= lst_fast*self.tolerance) and (pre_stochk >= lst_stochk*self.tolerance) and (pre_stochd >= lst_stochd*self.tolerance)
cond4 = (cur_trix <= cur_stochk*self.tolerance) and (cur_fast <= cur_stochk*self.tolerance) and (cur_stochk <= cur_stochd*self.tolerance)
cond5 = (cur_trix <= pre_trix*self.tolerance) and (cur_fast <= pre_fast*self.tolerance) and (cur_stochk <= pre_stochk*self.tolerance) and (cur_stochd <= pre_stochd*self.tolerance)
cond6 = (pre_trix <= lst_trix*self.tolerance) and (pre_fast <= lst_fast*self.tolerance) and (pre_stochk <= lst_stochk*self.tolerance) and (pre_stochd <= lst_stochd*self.tolerance)
hh_trix, ll_trix = calc_divergence(trix_lst)
hh_trixfast, ll_trixfast = calc_divergence(trixfast_lst)
hh_trixk, ll_trixk = calc_divergence(trixstochk_lst)
hh_trixd, ll_trixd = calc_divergence(trixstochd_lst)
cond7 = hh_trix, hh_trixfast, hh_trixk, hh_trixd
cond8 = ll_trix, ll_trixfast, ll_trixk, ll_rsid
if (cond1 and cond7) and (cond2 and cond3):
self.trix_uptrend = True
if (cond4 and cond8) and (cond5 and cond6):
self.trix_downtrend = True
exit = self.trixStochFastWindow.crossedBelow(self.trixStochKWindow) and self.trixStochKWindow.crossedBelow(self.trixStochDWindow)
entry = self.trixStochFastWindow.crossedAbove(self.trixStochKWindow) and self.trixStochKWindow.crossedAbove(self.trixStochDWindow)
if algorithm.Portfolio[symbol].Invested:
if exit:
self.trix_exit_signal = True
if not algorithm.Portfolio[symbol].Invested:
if entry:
self.trix_entry_signal = True
self.kalWindow.Add(self.kalFilter.Value)
self.kalWindowLow.Add(self.kalFilterLow.Value)
self.kalWindowHigh.Add(self.kalFilterHigh.Value)
self.priceWindow.Add(median_price)
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:
if exit:
self.exit_signal = True
if not algorithm.Portfolio[symbol].Invested:
if entry:
self.entry_signal = True
# 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_window.Add(row['volume'])
self.vpn_hlc_window.Add(round(statistics.median([row['high'], row['low'], row['close']]), 4))
if self.vpn_vol_window.IsReady and self.vpn_hlc_window.IsReady:
vpn_vol_window = list(self.vpn_vol_window)
vpn_hlc_window = list(self.vpn_hlc_window)
for i in range(-1, -self.vpn_period, -1):
if (vpn_hlc_window[i] >= vpn_hlc_window[i-1] + dist):
vp += vpn_vol_window[i]
elif (vpn_hlc_window[i] <= vpn_hlc_window[i-1] - dist):
vn += vpn_vol_window[i]
vtot += vpn_vol_window[i]
vpn_val = (((vp - vn) / (vtot/self.vpn_period)) / self.vpn_period) * 100
self.vpn_lst.Add(vpn_val)
if self.vpn_lst.IsReady:
vpn_ema = pd.DataFrame(list(self.vpn_lst)).ewm(span=ema_smooth, adjust=False).mean().iloc[-1][0]
vpn_scale = self.vpn_lst[-1]
vpnIndicator = ((vpn_scale) >= (vpn_ema*self.tolerance)) and ((vpn_scale) >= (self.vpn_lst[-2]*self.tolerance))
hh_vpn, ll_vpn = calc_divergence(self.vpn_lst)
self.vpnIndicator = vpnIndicator and hh_vpn and (not ll_vpn)
if self.vpnIndicator:
cur_vpn, cur_vpn_ema = vpn_scale, vpn_ema
low_vpn, low_vpn_ema = min(self.vpn_lst), min(pd.DataFrame(list(self.vpn_lst)).ewm(span=ema_smooth, adjust=False).mean().iloc[-1])
vpnScale = round(float(cur_vpn - cur_vpn_ema) / ((low_vpn + low_vpn_ema) / 2.0), 4)
self.vpnScale = vpnScale
else:
self.vpnScale = 0.00
# Candles
cndl_coef = float(sum([self.cndl_abandonedbaby.Current.Value,
self.cndl_advanceblock.Current.Value,
self.cndl_belthold.Current.Value,
self.cndl_breakway.Current.Value,
self.cndl_closingmarubozu.Current.Value,
self.cndl_concealedbabyswallow.Current.Value,
self.cndl_counterattack.Current.Value,
self.cndl_darkcloudcover.Current.Value,
self.cndl_doji.Current.Value,
self.cndl_dojistar.Current.Value,
self.cndl_dragonflydoji.Current.Value,
self.cndl_engulfing.Current.Value,
self.cndl_eveningdojistar.Current.Value,
self.cndl_eveningstar.Current.Value,
self.cndl_gapsidebysidewhite.Current.Value,
self.cndl_gravestonedoji.Current.Value,
self.cndl_hammer.Current.Value,
self.cndl_hangingman.Current.Value,
self.cndl_harami.Current.Value,
self.cndl_haramicross.Current.Value,
self.cndl_highwavecandle.Current.Value,
self.cndl_hikkake.Current.Value,
self.cndl_hikkakemodified.Current.Value,
self.cndl_homingpigeon.Current.Value,
self.cndl_identicalthreecrows.Current.Value,
self.cndl_inneck.Current.Value,
self.cndl_invertedhammer.Current.Value,
self.cndl_kicking.Current.Value,
self.cndl_kickingbylength.Current.Value,
self.cndl_ladderbottom.Current.Value,
self.cndl_longleggeddoji.Current.Value,
self.cndl_longlinecandle.Current.Value,
self.cndl_marubozu.Current.Value,
self.cndl_mathold.Current.Value,
self.cndl_matchinglow.Current.Value,
self.cndl_morningdojistar.Current.Value,
self.cndl_morningstar.Current.Value,
self.cndl_onneck.Current.Value,
self.cndl_pierce.Current.Value,
self.cndl_rickshawman.Current.Value,
self.cndl_risefallthreemethods.Current.Value,
self.cndl_separatinglines.Current.Value,
self.cndl_shootingstar.Current.Value,
self.cndl_shortlinecandle.Current.Value,
self.cndl_spinningtop.Current.Value,
self.cndl_stalledpattern.Current.Value,
self.cndl_sticksandwich.Current.Value,
self.cndl_takuri.Current.Value,
self.cndl_tasukigap.Current.Value,
self.cndl_threeblackcrows.Current.Value,
self.cndl_threeinside.Current.Value,
self.cndl_threelinest.Current.Value,
self.cndl_threeoutside.Current.Value,
self.cndl_threestarsinsouth.Current.Value,
self.cndl_threewhitesoldiers.Current.Value,
self.cndl_thrusting.Current.Value,
self.cndl_tristar.Current.Value,
self.cndl_twocrows.Current.Value,
self.cndl_uniquethreeriver.Current.Value,
self.cndl_updowngapthreemethods.Current.Value,
self.cndl_upsidegaptwocrows.Current.Value]))
self.candleContainer.Add(cndl_coef)
self.candleWindow.Add(cndl_coef)
if self.candleContainer.IsReady:
cndl_avg = statistics.median(list(self.candleContainer))
self.candleavgWindow.Add(cndl_avg)
if self.candleWindow.IsReady and self.candleavgWindow.IsReady:
exit = self.candleWindow.crossedBelow(self.candleavgWindow)
entry = self.candleWindow.crossedAbove(self.candleavgWindow)
if algorithm.Portfolio[symbol].Invested:
if exit:
self.cndl_downtrend = True
if not algorithm.Portfolio[symbol].Invested:
if entry:
self.cndl_uptrend = True
# Spread is Favorable
self.SpreadIsFavorable = algorithm.Securities[symbol].Price > 0 and algorithm.Securities[symbol].AskPrice > 0 and algorithm.Securities[symbol].BidPrice > 0 \
and (algorithm.Securities[symbol].AskPrice - algorithm.Securities[symbol].BidPrice) / algorithm.Securities[symbol].Price <= self.acceptingSpreadPercent
# 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
@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.0from System import *
from QuantConnect import *
from QuantConnect.Indicators import *
from QuantConnect.Data import *
from QuantConnect.Data.Market import *
from QuantConnect.Orders import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Execution import *
from QuantConnect.Algorithm.Framework.Portfolio import *
from QuantConnect.Indicators.CandlestickPatterns import *
import numpy as np
import tweepy
import statistics
from pykalman import KalmanFilter
from FilterIndicators import *
from SmartRollingWindow import *
from symbol_data_functions import SymbolData
# import datetime
from datetime import timedelta, datetime
class ScheduledExecutionModel(ExecutionModel):
'''Execution model that submits orders while the current market price is more favorable that the current volume weighted average price.'''
def __init__(self, algorithm, *args, **kwargs):
super().__init__()
'''Initializes a new instance of the VolumeWeightedAveragePriceExecutionModel class'''
self.targetsCollection = PortfolioTargetCollection()
self.deviations = 2
self.symbolData = {}
self.data = {}
# Gets or sets the maximum order quantity as a percentage of the current bar's volume.
# This defaults to 0.01m = 1%. For example, if the current bar's volume is 100,
# then the maximum order size would equal 1 share.
self.MaximumOrderQuantityPercentVolume = 0.1
# Gets or sets the maximum spread compare to current price in percentage.
self.acceptingSpreadPercent = 0.001
def Execute(self, algorithm, targets):
'''Executes market orders if the standard deviation of price is more
than the configured number of deviations in the favorable direction.
Args:
algorithm: The algorithm instance
targets: The portfolio targets'''
# update the complete set of portfolio targets with the new targets
self.targetsCollection.AddRange(targets)
# for performance we check count value, OrderByMarginImpact and ClearFulfilled are expensive to call
if self.targetsCollection.Count > 0:
for target in self.targetsCollection.OrderByMarginImpact(algorithm):
symbol = target.Symbol
# calculate remaining quantity to be ordered
unorderedQuantity = OrderSizing.GetUnorderedQuantity(algorithm, target)
# fetch our symbol data containing our VWAP indicator
data = self.symbolData.get(symbol, None)
if data is None: return
# check order entry conditions
if self.PriceIsFavorable(data, unorderedQuantity):
# adjust order size to respect maximum order size based on a percentage of current volume
orderSize = OrderSizing.GetOrderSizeForPercentVolume(data.Security, self.MaximumOrderQuantityPercentVolume, unorderedQuantity)
if (data.Security.BidPrice < data.VWAP):
price_est = round(statistics.median([data.VWAP, data.Security.BidPrice]), 4)
elif (data.Security.AskPrice > data.VWAP):
price_est = round(statistics.median([data.VWAP, data.Security.AskPrice]), 4)
max_quantity = algorithm.CalculateOrderQuantity(symbol, 0.95)
# suggested amount divided by the total possible amount
try:
order_percent = round(float(orderSize/max_quantity), 4)
except:
if max_quantity == 0:
order_percent = 0.0
else:
cash = algorithm.Portfolio.Cash
max_quantity = int(cash/price_est)
order_percent = round(float(orderSize/max_quantity), 4)
if ((orderSize != 0) and (abs(order_percent) >= 0.1)):
coef = abs(order_percent) * 0.5
if algorithm.Portfolio[symbol].Invested:
if coef <= 0.25:
coef = int(abs(float(order_percent))/0.025)*10
signals = (self.data[symbol].breakout or (self.data[symbol].vpnIndicator and (self.data[symbol].is_uptrend and self.data[symbol].trix_uptrend or (self.data[symbol].entry_signal and self.data[symbol].rsi_entry_signal and self.data[symbol].macd_entry_signal and self.data[symbol].williams_entry_signal and self.data[symbol].trix_entry_signal))) or (self.data[symbol].macd_uptrend and self.data[symbol].rsi_uptrend))
down_signals = ((self.data[symbol].breakdown or ((not self.data[symbol].vpnIndicator) and (self.data[symbol].is_downtrend and self.data[symbol].trix_downtrend) or (self.data[symbol].exit_signal and self.data[symbol].rsi_exit_signal and self.data[symbol].macd_exit_signal and self.data[symbol].williams_exit_signal and self.data[symbol].trix_exit_signal))) or (self.data[symbol].macd_downtrend and self.data[symbol].rsi_downtrend))
slope_cond = (self.data[symbol].roc_slope > 0.00) and (self.data[symbol].vol_slope > 0.00)
slope_down = (self.data[symbol].roc_slope > 0.00) and (self.data[symbol].vol_slope > 0.00)
if signals and slope_cond:
coef = coef * 30
elif signals or slope_cond:
coef = coef * 10
elif slope_down or down_signals:
coef = 0
orderSize = OrderSizing.GetOrderSizeForPercentVolume(data.Security, self.MaximumOrderQuantityPercentVolume*coef, unorderedQuantity)
projected_cost = round(price_est * orderSize, 4) * 1.0
if (algorithm.Portfolio.Cash > projected_cost) and (orderSize != 0):
algorithm.MarketOrder(symbol, orderSize)
self.targetsCollection.ClearFulfilled(algorithm)
def OnSecuritiesChanged(self, algorithm, changes):
'''Event fired each time the we add/remove securities from the data feed
Args:
algorithm: The algorithm instance that experienced the change in securities
changes: The security additions and removals from the algorithm'''
for removed in changes.RemovedSecurities:
# clean up removed security data
if removed.Symbol in self.symbolData:
if self.IsSafeToRemove(algorithm, removed.Symbol):
data = self.symbolData.pop(removed.Symbol)
algorithm.SubscriptionManager.RemoveConsolidator(removed.Symbol, data.Consolidator)
if removed.Symbol in self.data:
if self.IsSafeToRemove(algorithm, removed.Symbol):
data = self.data.pop(removed.Symbol)
algorithm.SubscriptionManager.RemoveConsolidator(removed.Symbol, data.Consolidator)
for added in changes.AddedSecurities:
if added.Symbol not in self.symbolData:
self.data[added.Symbol] = SymbolData(algorithm, added.Symbol, Resolution.Daily)
self.symbolData[added.Symbol] = SymbolDataExecuteModel(algorithm, added)
def PriceIsFavorable(self, data, unorderedQuantity):
'''Determines if the current price is favorable in the favorable direction.'''
sma = data.SMA.Current.Value
deviations = self.deviations * data.STD.Current.Value
sto = (data.STO.StochK.Current.Value >= data.STO.StochD.Current.Value) or (data.KWindow.crossedAbove(data.DWindow))
if unorderedQuantity > 0:
if (data.Security.BidPrice < data.VWAP) or (data.Security.BidPrice < sma - deviations) and sto:
return True
else:
if (data.Security.AskPrice > data.VWAP) or (data.Security.AskPrice > sma + deviations) and sto:
return True
return False
def SpreadIsFavorable(self, data):
'''Determines if the spread is in desirable range.'''
# Price has to be larger than zero to avoid zero division error, or negative price causing the spread percentage < 0 by error
# Has to be in opening hours of exchange to avoid extreme spread in OTC period
return data.Security.Price > 0 and data.Security.AskPrice > 0 and data.Security.BidPrice > 0 \
and (data.Security.AskPrice - data.Security.BidPrice) / data.Security.Price <= self.acceptingSpreadPercent
def IsSafeToRemove(self, algorithm, symbol):
'''Determines if it's safe to remove the associated symbol data'''
# confirm the security isn't currently a member of any universe
return not any([kvp.Value.ContainsMember(symbol) for kvp in algorithm.UniverseManager])
class SymbolDataExecuteModel:
def __init__(self, algorithm, security):
self.Security = security
self.period = 8
self.Consolidator = algorithm.ResolveConsolidator(security.Symbol, security.Resolution) # TradeBarConsolidator(timedelta(hours=4)) #
name = algorithm.CreateIndicatorName(security.Symbol, "VWAP", security.Resolution)
self.vwap = IntradayVwap(name)
algorithm.RegisterIndicator(security.Symbol, self.vwap, self.Consolidator)
smaName = algorithm.CreateIndicatorName(security.Symbol, f"SMA{self.period}", security.Resolution)
self.SMA = SimpleMovingAverage(smaName, self.period)
algorithm.RegisterIndicator(security.Symbol, self.SMA, self.Consolidator)
stoName = algorithm.CreateIndicatorName(security.Symbol, f"STO{self.period}", security.Resolution)
self.STO = Stochastic(smaName, self.period, 3, 3)
algorithm.RegisterIndicator(security.Symbol, self.STO, self.Consolidator)
self.DWindow = SmartRollingWindow("float", 5)
self.KWindow = SmartRollingWindow("float", 5)
stdName = algorithm.CreateIndicatorName(security.Symbol, f"STD{self.period}", security.Resolution)
self.STD = StandardDeviation(stdName, self.period)
algorithm.RegisterIndicator(security.Symbol, self.STD, self.Consolidator)
# warmup our indicators by pushing history through the indicators
history = algorithm.History(security.Symbol, 84, security.Resolution)
if 'close' in history:
for index, row in history.loc[security.Symbol].iterrows():
tradeBar = TradeBar(index, row['open'], row['high'], row['low'], row['close'], row['volume'])
median_price = round(float(statistics.median([row['open'], row['high'], row['low'], row['close']])), 4)
self.SMA.Update(index, median_price)
self.STD.Update(index, median_price)
sma = self.SMA.Current.Value
sma_bar = TradeBar(index, sma, sma, sma, sma, 0)
self.STO.Update(sma_bar)
if self.STO.IsReady:
self.KWindow.Add(self.STO.StochK.Current.Value)
self.DWindow.Add(self.STO.StochD.Current.Value)
@property
def VWAP(self):
return self.vwap.Value
def dispose(self, algorithm):
algorithm.SubscriptionManager.RemoveConsolidator(security.Symbol, self.consolidator)
class IntradayVwap:
'''Defines the canonical intraday VWAP indicator'''
def __init__(self, name):
self.Name = name
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.mean([input.Open, input.High, input.Low, input.Close])), 4)
return True, float(input.Volume), averagePrice
return False, 0.0, 0.0
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *
import sys
import tweepy
from tweepy import OAuthHandler
from time import sleep
import json
# Important - Don't name file 'tweepy.py'
# Used below to supress problems and continue instead of try/except/continue
from contextlib import suppress
# --- # --------------------------------------------------------------------- # --- #
# --- # --------------------------------------------------------------------- # --- #
# Set True to follow a defined list of twitter users.
# Set False to stream from all accounts based on defined keywords.
FollowerMode = True
# --- # --------------------------------------------------------------------- # --- #
# --- # --------------------------------------------------------------------- # --- #
# --- # ---------------------------------- # --- #
# --- # ---- Follower Mode Dictionary ---- # --- #
# --- # ---------------------------------- # --- #
# Lookup Twitter ID's here http://gettwitterid.com/ by entering the accounts @Usernamehandle (without the @)
# It doesn't care what you name them. The names are only displayed to the console.
idsdict = {'TT3Private'}
# --- # --------------------------------------------------------------------- # --- #
# --- # --------------------------------------------------------------------- # --- #
# --- # ------------------------------ # --- #
# --- # ---- Search Mode Keywords ---- # --- #
# --- # ------------------------------ # --- #
# --- # ----------------- # --- #
# --- # SEARCH BY KEYWORD # --- #
# --- # ----------------- # --- #
# Example
# search = ['breaking news']
# --- # ---------- # --- #
# --- # SEARCH ALL # --- #
# --- # ---------- # --- #
# [' '] and [''] yields no results. The only way to truly stream all of the tweets (unfiltered)
# requires a connection to the firehose(https://developer.twitter.com/en/docs/tweets/sample-realtime/overview/decahose.html),
# which is granted only in specific use enterprise cases by Twitter.
search = ['.','a','@','\'','this','to',':(','?','!','$',
'h','+','_','-','#','b','you', 'c',',','the',
'i','/','lol','at','this','need','and','RT',
'if','1', 'd','e','f','g'] # Feel free to expand on this. I believe there's a limit on how much you can add.
# --- # -------------------- # --- #
# --- # SEARCH BY USER INPUT # --- #
# --- # -------------------- # --- #
# search = [input('Enter keyword\n\n')]
# --- # -------------------------------------------------------------- # --- #
# --- # -------------------------------------------------------------- # --- #
# --- # ---------------------- # --- #
# --- # --- AUTHENTICATION --- # --- #
# --- # ---------------------- # --- #
consumer_key = self.GetParameter("Consumer_Api")
consumer_secret = self.GetParameter("Consumer_Api_Secret")
access_token = self.GetParameter("Access_Token")
access_token_secret = self.GetParameter("Access_Token_Secret")
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)
# --- # -------------------------------------------------------------- # --- #
# --- # -------------------------------------------------------------- # --- #
print('Listening for tweets...\n')
if FollowerMode == True:
# gets all IDs from 'idsdict' and converts them to strings
ids = [str(i) for i in list(idsdict.values())]
# Main Stream Listener Class
class MyStreamListener(tweepy.StreamListener):
global ids
global FollowerMode
tweets = 0
# on_status is a built in tweepy method to fetch tweets.
# on_data is another one and shows more detailed information for analytical reasons,
# but be aware that you will have to parse the json manually like data['text'], data['user']['location'], etc.
# print out status or data(if using on_data) and run the script to fetch the full JSON to see everything that it can do.
# You can find a good example of that here https://github.com/varadhbhatnagar/Emoyto
def on_status(self, status):
"""
# Use this if you plan to use the json functionality below.
# If you use this, tab the rest of this class below over by one indent(4 spaces)
# with open ('tweets.json', 'a', encoding='utf-8') as f:
# Supress errors so if that specific tweet has an issue for whatever reason, it will skip it. Similar to try/except.
# Don't use this if you want to debug/look for issues.
"""
with suppress(Exception):
userid = str(status.user.id)
# "userid in ids" mentioned below removes all of the mentions and retweets and makes sure it only comes from the original account.
# Tweepy has no built in way to exclude that to my knowledge based on stackoverflow answers.
if FollowerMode == True and userid in ids:
# You can do this for example - " if status.place.country == 'United States': ",
# but most people don't have their country listed. status.user.location often shows 'state' or 'city, state' and/or country,
# but their location is user set so it can really be something made up like 'outer space'. If it's that important,
# you could always try and use an API to see if it's a valid location.
print('-' * 80)
# Prints the name for this ID that's defined in 'idsdict'
with suppress(Exception):
print(list(idsdict.keys())[list(idsdict.values()).index(int(userid))])
print('User: ' + status.user.screen_name)
# Attempt to display location and/or country if it exists
with suppress(Exception):
if status.user.location != None and status.user.location != 'None':
print('Location: ' + status.user.location)
with suppress(Exception):
print('Country: ' + status.place.country)
# Checks to see if tweet is 'extended'/long. If it is, it will display the full tweet.
try:
text = status.extended_tweet['full_text']
except AttributeError:
text = status.text
print('Tweet: ' + text)
sleep(0.015)
elif FollowerMode == False:
print('-' * 80)
print('User: ' + status.user.screen_name)
with suppress(Exception):
if status.user.location != None and status.user.location != 'None':
print('Location: ' + status.user.location)
with suppress(Exception):
print('Country: ' + status.place.country)
try:
text = status.extended_tweet['full_text']
except AttributeError:
text = status.text
print('Tweet: ' + text)
# Prevents the display from hiccups and keeps the scrolling smooth when scanning all
sleep(0.016)
# --- # --------------------------------------------------------------------- # --- #
# --- # --------------------------------------------------------------------- # --- #
# Optional - Write tweet into json file. You can store just tweets for example
# Make sure to un-comment the 'with f.open' above and tab the rest of the class below it.
#json_str = json.dumps(status._json)
#f.write(status.text + '\n')
# --- # --------------------------------------------------------------------- # --- #
# --- # --------------------------------------------------------------------- # --- #
# # Optional - Print something out every certain number of tweets to show how many tweets have came through.
# MyStreamListener.tweets += 1
# if MyStreamListener.tweets % 1000 == 0:
# print(str(MyStreamListener.tweets) + ' Tweets')
# for i in range(15):
# print(f'|||||||||||||||||||||||||||||||||||----- {MyStreamListener.tweets} ------||||||||||||||||||||||||||||||||||||||| \n')
# sleep(1)
# Define the listener
listener = MyStreamListener()
stream = tweepy.Stream(auth, listener)
if FollowerMode == True:
stream.filter(follow=ids)
else:
stream.filter(languages=["en"], track = search )