#
# Multiple Moving Average Concavity and Turning Points
# or
# The Second Derivative of the A Moving Average
#
# via useThinkScript
# request from chillc15
# Added Arnaud Legoux MA and other Moving Averages
#
# Author: Seth Urion (Mahsume)
# Version: 2020-02-22 V2
#
# This code is licensed (as applicable) under the GPL v3
#
# ----------------------
declare upper;
input Price = HL2;
input MA_Length = 21;
input lookback = 2;
input MovingAverage = {default "HMA", "EMA", "SMA", "WMA", "ALMA"};
script ALMA {
# Attributed to Miket
# https://tos.mx/9mznij
# https://usethinkscript.com/threads/alma-arnaud-legoux-ma-indicator-for-thinkorswim.174/
input Data = close;
input Window = 9;
input Sigma = 6;
input Offset = 0.85;
def m = (Offset * (Window - 1));
def s = Window / Sigma;
def SumVectorData = fold y = 0 to Window with WS do WS + Exp(-(Sqr(y - m)) / (2 * Sqr(s))) * GetValue(Data, (Window - 1) - y);
def SumVector = fold z = 0 to Window with CW do CW + Exp(-(Sqr(z - m)) / (2 * Sqr(s)));
plot ALMA = SumVectorData / SumVector;
}
plot MA;
switch (MovingAverage) {
case EMA:
MA = MovAvgExponential(price, length = MA_Length);
case SMA:
MA = SimpleMovingAvg(price, length = MA_Length);
case WMA:
MA = WMA(price, length = MA_Length);
case ALMA:
MA = ALMA(Data = price, window = MA_Length);
default:
MA = HullMovingAvg(price = price, length = MA_Length);
}
def delta = MA[1] - MA[lookback + 1];
def delta_per_bar = delta / lookback;
def next_bar = MA[1] + delta_per_bar;
def concavity = if MA > next_bar then 1 else -1;
plot turning_point = if concavity[-1] != concavity then MA else Double.NaN;
MA.AssignValueColor(color = if concavity == -1 then
if MA > MA[1] then Color.DARK_ORANGE else Color.RED else
if MA < MA[1] then Color.DARK_GREEN else Color.GREEN);
MA.SetLineWeight(2);
turning_point.SetLineWeight(2);
turning_point.SetPaintingStrategy(paintingStrategy = PaintingStrategy.POINTS);
turning_point.SetDefaultColor(Color.WHITE);
plot MA_Max = if MA[-1] < MA and MA > MA[1] then MA else Double.NaN;
MA_Max.SetDefaultColor(Color.BLUE);
MA_Max.SetPaintingStrategy(PaintingStrategy.SQUARES);
MA_Max.SetLineWeight(4);
plot MA_Min = if MA[-1] > MA and MA < MA[1] then MA else Double.NaN;
MA_Min.SetDefaultColor(Color.GRAY);
MA_Min.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
MA_Min.SetLineWeight(4);
plot sell = if turning_point and concavity == 1 then high else Double.NaN;
sell.SetDefaultColor(Color.DARK_ORANGE);
sell.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
sell.SetLineWeight(3);
plot buy = if turning_point and concavity == -1 then low else Double.NaN;
buy.SetDefaultColor(Color.CYAN);
buy.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
buy.SetLineWeight(3);
def divergence = MA - next_bar;
AddLabel(yes, Concat("DIVERGENCE: " , divergence), color = if concavity < 0 then if divergence[1] > divergence then Color.RED else Color.PINK else if divergence[1] < divergence then Color.GREEN else Color.YELLOW);
AddLabel(yes, "MA Length: " + MA_Length, color = Color.CYAN);
#####################
#
## 5% PROFIT INPUT ##
#
#####################
input percentGainGoal = 5;
def percentChange = 100 * (high - EntryPrice()) / EntryPrice();
def exitGood = percentChange >= percentGainGoal;
#####################
#
## MACD (8, 21, 5, EXPONENTIAL, NO) ##
#
#####################
input MACD_fastLength = 8;
input MACD_slowLength = 21;
input MACD_Length = 5;
def averageType = AverageType.EXPONENTIAL;
def showBreakoutSignals = no;
def Value = MovingAverage(averageType, close, MACD_fastLength) - MovingAverage(averageType, close, MACD_slowLength);
def Avg = MovingAverage(averageType, Value, MACD_Length);
#####################
#
## ORIGINAL ORDERS ##
#
#####################
#AddOrder(OrderType.BUY_TO_OPEN, buy, tickcolor = Color.CYAN, arrowcolor = Color.CYAN, name = "Buy", tradeSize = 1);
#AddOrder(OrderType.SELL_TO_CLOSE, sell, name = "Sell", tradeSize = 1);
##############
#
## 5% ORDER ##
#
##############
#addOrder(OrderType.SELL_TO_CLOSE, exitGood, name = "Sell 5%", tradeSize = 1);
####################
#
## ORIGINAL WITH MACD CONFIRM ORDER ##
#
####################
AddOrder(OrderType.BUY_TO_OPEN, buy and value > avg, tickcolor = Color.CYAN, arrowcolor = Color.CYAN, name = "Buy", tradeSize = 1);
AddOrder(OrderType.SELL_TO_CLOSE, sell, name = "Sell", tradeSize = 1);
####################
#
## ORIGINAL BUY AND MA_MIN WITH MACD CONFIRM ORDER ##
#
####################
#AddOrder(OrderType.BUY_TO_OPEN, buy and value > avg or MA_Min and value > avg, tickcolor = Color.CYAN, arrowcolor = Color.CYAN, name = "Buy", tradeSize = 1);
#AddOrder(OrderType.SELL_TO_CLOSE, sell, name = "Sell", tradeSize = 1);
###################
#
# ALERTS
#
###################
Alert(condition = buy, text = "Buy", "alert type" = Alert.BAR, sound = Sound.Bell);
Alert(condition = sell, text = "Sell", "alert type" = Alert.BAR, sound = Sound.Chimes);
###################
#
# 2020-05-01
#
# MOBILE TOS SUPPORT
#
# Each color of the HMA needs to be a separate plot as ToS Mobile
# lacks the ability to assign colors the way ToS Desktop does.
# I recommend a plain colored HMA behind the line
# Set the line color of the HMA above to gray or some neutral
#
# CCD_D -> ConCave Down and Decreasing
# CCD_I -> ConCave Down and Increasing
# CCU_D -> ConCave Up and Decreasing
# CCU_I -> ConCave Up and Increasing
#
###################
plot CCD_D = if concavity == -1 and MA < MA[1] then MA else double.nan;
CCD_D.SetDefaultColor(Color.RED);
CCD_D.SetLineWeight(2);
plot CCD_I = if concavity == -1 and MA >= MA[1] then MA else double.nan;
CCD_I.SetDefaultColor(Color.DARK_ORANGE);
CCD_I.SetLineWeight(2);
plot CCU_D = if concavity == 1 and MA <= MA[1] then MA else double.nan;
CCU_D.SetDefaultColor(COLOR.DARK_GREEN);
CCU_D.SetLineWeight(2);
plot CCU_I = if concavity == 1 and MA > MA[1] then MA else double.nan;
CCU_I.SetDefaultColor(COLOR.GREEN);
CCU_I.SetLineWeight(2);