Repaints Hull Moving Average Turning Points and Concavity (2nd Derivatives)

Repaints
Status
Not open for further replies.

New Version 4 Now with Mobile!

oh, and alerts.

Why? Because. :)

KNOWN ISSUE:
The Mobile plots leave 'gaps' when the color changes. I think it's the between the bar where the change happens and the current bar, so trends still show correctly, but the gray background HMA makes it look better.

Link in the first post, and here:
https://tos.mx/NXqbYE9

EDIT 2021-08-05. This version was released as a mobile version, and the 1st post was not edited. I believe now (2021) that this has been changed. I have removed the confusion causing statement here. This version is for mobile. The versions in post 1 are for whatever they are for. ;-) Glad you're all enjoying this one.

Code:
#
# Hull Moving Average Concavity and Turning Points
#  or
# The Second Derivative of the Hull Moving Average
#
# Author: Seth Urion (Mashume)
# Version: 2020-05-01 V4
#
# Now with support for ToS Mobile
#
# This code is licensed (as applicable) under the GPL v3
#
# ----------------------


declare upper;

input price = HL2;
input HMA_Length = 55;
input lookback = 2;

# I read somewhere that it's faster to define nan's and then use the def'd var rather than call double.nan every time.
def nan = double.nan;

plot HMA = HullMovingAvg(price = price, length = HMA_Length);

def delta = HMA[1] - HMA[lookback + 1];
def delta_per_bar = delta / lookback;

def next_bar = HMA[1] + delta_per_bar;

def concavity = if HMA > next_bar then 1 else -1;

plot turning_point = if concavity[1] != concavity then HMA else nan;

HMA.AssignValueColor(color = if concavity[1] == -1 then
    if HMA > HMA[1] then color.dark_orange else color.red else
    if HMA < HMA[1] then color.dark_green else color.green);

HMA.SetLineWeight(3);

turning_point.SetLineWeight(4);
turning_point.SetPaintingStrategy(paintingStrategy = PaintingStrategy.POINTS);
turning_point.SetDefaultColor(color.white);

plot MA_Max = if HMA[-1] < HMA and HMA > HMA[1] then HMA else NaN;
MA_Max.SetDefaultColor(Color.WHITE);
MA_Max.SetPaintingStrategy(PaintingStrategy.SQUARES);
MA_Max.SetLineWeight(3);

plot MA_Min = if HMA[-1] > HMA and HMA < HMA[1] then HMA else Nan;
MA_Min.SetDefaultColor(Color.WHITE);
MA_Min.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
MA_Min.SetLineWeight(3);

plot sell = if turning_point and concavity == -1 then high else 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 nan;
buy.SetDefaultColor(Color.CYAN);
buy.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
buy.SetLineWeight(3);

def divergence = HMA - next_bar;

addLabel(yes, concat("DIVERGENCE: " , divergence * 10000), 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);

###################
#
# 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 HMA < HMA[1] then HMA else nan;
CCD_D.SetDefaultColor(Color.RED);
CCD_D.SetLineWeight(3);

plot CCD_I = if concavity == -1 and HMA >= HMA[1] then HMA else nan;
CCD_I.SetDefaultColor(Color.DARK_ORANGE);
CCD_I.SetLineWeight(3);

plot CCU_D = if concavity == 1 and HMA <= HMA[1] then HMA else nan;
CCU_D.SetDefaultColor(COLOR.DARK_GREEN);
CCU_D.SetLineWeight(3);

plot CCU_I = if concavity == 1 and HMA > HMA[1] then HMA else nan;
CCU_I.SetDefaultColor(COLOR.GREEN);
CCU_I.SetLineWeight(3);

Happy trading.

-mashume
 
Last edited:
Thank you for your continued work. Sorry if this has been explained before-- how do you interpret the divergence level of the chart label? Is there a certain value we are looking for to long or short?
 
Last edited:
Thank you for your continued work. Sorry if this has been explained before-- how do you interpret the divergence level of the chart label? Is there a certain value we are looking for to long or short?

Good question @technicallydreaming ,

It's kind of my early-warning system. It lets me know what the slope of the lower indicator is, whether it's moving away from flipping or toward flipping, if I don't want to take up screen real estate with the lower indicator.

BTW, for anyone who finds the numbers annoyingly small, change
Code:
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);
to
Code:
addLabel(yes, concat("DIVERGENCE: " , divergence * 10000), 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);
See what I did there? just multiply the displayed value by 10,000 and it gives nicer human-domain numbers (generally 1 to 200). The bigger the number, the more it's curving away from or toward a flip. the smaller the number, the less it's curving (more straight line).

For those who get frustrated with the downtrending 'false signal flips', watching how far it's curving away may be telltale. If the lower indicator, and by extension the lable above, isn't moving very far from zero, it may not really be about to make a nice big move. It's perhaps analagous to a strength-of-change-in-trend meter. Maybe. Your mileage will, of course, vary. Considerably probably.

Have fun with it,

-mashume

EDIT

Not for the mathematically disinterested, but perhaps worth a read.

After playing around with this a bit to see if I could write a better explanation, I threw another label together. This one gives you the standard deviation over n periods of the concavity divergence. You can use this, compared with the value of the divergence label to decide whether the shift in divergence is large enough for you to play. It is not able to predict how fast it will turn in the future even a bar or two, but it can tell you how the turn this bar compares with a standard turn based over the last some bars.

Ponder, discover, trade, learn.

Code:
input stddev_len = 21;
def divergence_stddev = StandardDeviation(price = divergence, length = stddev_len);
addLabel(yes, concat("STDDEV: " , divergence_stddev * 10000), color = if absValue(divergence) > absValue(divergence_stddev) then color.blue else color.dark_gray);

I have no idea, currently, what value to use for stddev_len. I took a guess at 21. If you make it longer, it may encompass large swings in volitile trading conditions and you'll miss trades. If you make it short, it may be overly sensitive and you'll take too many trades. It's not a buy/sell trigger. It's just information. Use with intelligence.

-mashume
 
Last edited:
@mashume - Hi, thanks for the updates ! I cobbled together a zscore for divergence and wondered what you think- (I use vlevel at 0 as kinda 'stop & reverse' but it can be set to whatever sensitivity to avoid some of the choppiness prices offer

#zscore
input length1 = 13;
input vlevel = 0.00;
def min = lowest(divergence, length1);
def max = highest(divergence, length1);
def Zscore = (divergence - Average(divergence, length1)) / StDev(divergence, length1);
addlabel(1,"Zscore Div= " + round(zscore,2), if zscore > vlevel and zscore < 3 then color.blue else if zscore > 3 then color.red else if zscore < -vlevel and zscore > -3 then color.red else if zscore < -3 then color.blue else color.white);
 
Hi Mashume!!! Great indicator! Is there a way you could help us with the WL in order to change the numbers to a buy and sell text as soon as the buy and sell signal appears.
After
AssignBackgroundColor(if data >= 0 then if HMA > HMA[1] then Color.GREEN else Color.DARK_GREEN else if HMA > HMA[1] then color.DARK_ORANGE else color.DARK_RED);

ADDLABEL ..... I have been trying but getting errors

Thanks in advanced
 
@NikeNewl I am too having this problem. Do you just add this to the custom of the Scan?

error.png
 
Last edited by a moderator:
@jay2, @Berezowsky,
When you imported the study, either by link or by copy and paste, if you didn't name it exactly "Concavity" there will be a problem. If you did name it that, I'm not sure, because it works on my machine this way.

-mashume
 
@mashume @jay2
The code that is working for me right now is the following and I would only like to paint the background color green or red as to buy or sell

Code:
input price = HL2;
input HMA_Length = 20;
input lookback = 2;

plot HMA = HullMovingAvg(price = price, length = HMA_Length);

def delta = HMA[1] - HMA[lookback + 1];
def delta_per_bar = delta / lookback;

def next_bar = HMA[1] + delta_per_bar;

def concavity = if HMA > next_bar then 1 else -1;

plot turning_point = if concavity[1] != concavity then HMA else double.nan;

HMA.AssignValueColor(color = if concavity[1] == -1 then
    if HMA > HMA[1] then color.dark_orange else color.red else
    if HMA < HMA[1] then color.dark_green else color.green);

HMA.SetLineWeight(3);

turning_point.SetLineWeight(4);
turning_point.SetPaintingStrategy(paintingStrategy = PaintingStrategy.POINTS);
turning_point.SetDefaultColor(color.white);

plot MA_Max = if HMA[-1] < HMA and HMA > HMA[1] then HMA else Double.NaN;
MA_Max.SetDefaultColor(Color.WHITE);
MA_Max.SetPaintingStrategy(PaintingStrategy.SQUARES);
MA_Max.SetLineWeight(3);

plot MA_Min = if HMA[-1] > HMA and HMA < HMA[1] then HMA else Double.Nan;
MA_Min.SetDefaultColor(Color.WHITE);
MA_Min.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
MA_Min.SetLineWeight(3);

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 = HMA - next_bar;

addLabel(yes,
    if buy then "buy"
    else if sell then "sell"
    else  "-");

I'm trying to add the following but does not paint the background

assignbackgroundcolor(
if Buy is true then color.GREEN
else if sell is true then color.red
else color.black);
 
Last edited by a moderator:
Out of the 14 trades tonight on the S&P 500 futures, 11 wins 2 losses and 1 breakeven. Largest winner $300 and largest loser was $112.50. I should have done better because I missed a 10+ point run up when I stepped away to do something and I didn’t trail my trade properly and gotten out of many of them a bit too soon.

I use the Swing Hi Swing Lo indicator to let me know potential swing points. I use turning points on HMA Concavity Divergence for confirmation. Aggressive entry would be when the turning point appears. Conservative entry would be at the close of the bar with the turning point(signal bar), 50% of the turning point bar, or any price within the acceptable risk parameters. Stop would be a tick or two from the high/low of swing point or the signal bar depending on where my entry is or 8 ticks from my entry.

Since there can be many inflection points on smaller time frame as someone mentioned, I use a trailing stop and once I’m in the trade I should not care about other inflection points after that until I hit my target or my stop takes me out. Once out of the trade, wait for the next swing point and entry.

I’m having such great success with this that I’m getting this automated in Ninjatrader 8.

By the way, same concept can be use with the Ultimate Breakout Indicator for stops and targets.

@tradegeek, curious if you would post a screenshot with an example of the scalping method you mentioned, I ask because I am setting my renko chart for futs and or stocks, like TSLA, have to change my ticks for each but curious on your ES set up you mentioned earlier in thread if you could show sample of how you use confirmation candle, I have an OCO bracket with a hard stop for stocks, but looking at trailing instead and setting it for futs or stocks, thanks for any help
 
Last edited:
@tradegeek, curious if you would post a screenshot with an example of the scalping method you mentioned, I ask because I am setting my renko chart for futs and or stocks, like TSLA, have to change my ticks for each but curious on your ES set up you mentioned earlier in thread if you could show sample of how you use confirmation candle, I have an OCO bracket with a hard stop for stocks, but looking at trailing instead and setting it for futs or stocks, thanks for any help
What setting are you using
 
@mashume @BenTen

I have been working on this code for the WL with signals on Buy, Sell, TOP and Bottom.... I just got a single signal to color the background, but still missing 3 more signals to color the background. I hope you might be able to help.

Code:
input price = HL2;
input HMA_Length = 20;
input lookback = 2;

plot HMA = HullMovingAvg(price = price, length = HMA_Length);

def delta = HMA[1] - HMA[lookback + 1];
def delta_per_bar = delta / lookback;

def next_bar = HMA[1] + delta_per_bar;

def concavity = if HMA > next_bar then 1 else -1;

plot turning_point = if concavity[1] != concavity then HMA else double.nan;

#Hull Line

HMA.AssignValueColor(color = if concavity[1] == -1 then
    if HMA > HMA[1] then color.dark_orange else color.red else
    if HMA < HMA[1] then color.dark_green else color.green);

HMA.SetLineWeight(3);

#Turning Points

turning_point.SetLineWeight(4);
turning_point.SetPaintingStrategy(paintingStrategy = PaintingStrategy.POINTS);
turning_point.SetDefaultColor(color.white);

#MAX and MIN points

plot MA_Max = if HMA[-1] < HMA and HMA > HMA[1] then HMA else Double.NaN;
MA_Max.SetDefaultColor(Color.RED);
MA_Max.SetPaintingStrategy(PaintingStrategy.SQUARES);
MA_Max.SetLineWeight(3);

plot MA_Min = if HMA[-1] > HMA and HMA < HMA[1] then HMA else Double.Nan;
MA_Min.SetDefaultColor(Color.GREEN);
MA_Min.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
MA_Min.SetLineWeight(3);

#Buy and Sell Entry Price points, caution, not exact

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

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

addLabel(yes,
    if buy then "buy"
    else if sell then "sell"
    else if MA_min[1] then "Buy Bottom"
    else if MA_Max[1] then "Sell top"
    else  "-");

assignbackgroundcolor(
    if Buy[1] then color.dark_GREEN
    else if sell[1] then color.dark_red
    else if MA_Min then color.green
    else if MA_Max then color.red
    else color.black);
 
Last edited by a moderator:
@mashume , I've been trying to keep-up with this thread for changes in the code. Can you please confirm if Version: 2020-02-23 V3 for the lower study is the most current version. Thanks in advance!
 
@mashume , I've been trying to keep-up with this thread for changes in the code. Can you please confirm if Version: 2020-02-23 V3 for the lower study is the most current version. Thanks in advance!
You are correct, sir... probably. :) There are some developments I've tried but nothing that was of quality to release into the wild as yet.
-mashume
 
TSLA desktop screen grab using Renko bricks in TOS, top left has the HULL with concavity from this thread and other 2 are combo of regular HULL and EMA, working on a trading/scalping chart set to apply to beta stocks and futs, working different tick amounts to find the smoothest and least knee jerk amount for the bricks to create more reliable signal
EYDtELfXYAETlk-?format=jpg&name=large.jpg
 
Good question @technicallydreaming ,

It's kind of my early-warning system. It lets me know what the slope of the lower indicator is, whether it's moving away from flipping or toward flipping, if I don't want to take up screen real estate with the lower indicator.

BTW, for anyone who finds the numbers annoyingly small, change
Code:
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);
to
Code:
addLabel(yes, concat("DIVERGENCE: " , divergence * 10000), 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);
See what I did there? just multiply the displayed value by 10,000 and it gives nicer human-domain numbers (generally 1 to 200). The bigger the number, the more it's curving away from or toward a flip. the smaller the number, the less it's curving (more straight line).

For those who get frustrated with the downtrending 'false signal flips', watching how far it's curving away may be telltale. If the lower indicator, and by extension the lable above, isn't moving very far from zero, it may not really be about to make a nice big move. It's perhaps analagous to a strength-of-change-in-trend meter. Maybe. Your mileage will, of course, vary. Considerably probably.

Have fun with it,

-mashume

EDIT

Not for the mathematically disinterested, but perhaps worth a read.

After playing around with this a bit to see if I could write a better explanation, I threw another label together. This one gives you the standard deviation over n periods of the concavity divergence. You can use this, compared with the value of the divergence label to decide whether the shift in divergence is large enough for you to play. It is not able to predict how fast it will turn in the future even a bar or two, but it can tell you how the turn this bar compares with a standard turn based over the last some bars.

Ponder, discover, trade, learn.

Code:
input stddev_len = 21;
def divergence_stddev = StandardDeviation(price = divergence, length = stddev_len);
addLabel(yes, concat("STDDEV: " , divergence_stddev * 10000), color = if absValue(divergence) > absValue(divergence_stddev) then color.blue else color.dark_gray);

I have no idea, currently, what value to use for stddev_len. I took a guess at 21. If you make it longer, it may encompass large swings in volitile trading conditions and you'll miss trades. If you make it short, it may be overly sensitive and you'll take too many trades. It's not a buy/sell trigger. It's just information. Use with intelligence.

-mashume
I use the divergence label on every chart, in every scan.. Thank you.
 
What exactly is the look back period changing , particularly when it comes to the MA_Max MA_Min ? Also would setting this to "Close" wait for the next candle to form before painting those signals?
 
Last edited:
TSLA desktop screen grab using Renko bricks in TOS, top left has the HULL with concavity from this thread and other 2 are combo of regular HULL and EMA, working on a trading/scalping chart set to apply to beta stocks and futs, working different tick amounts to find the smoothest and least knee jerk amount for the bricks to create more reliable signal
EYDtELfXYAETlk-?format=jpg&name=large.jpg
I love this setup. Can you share this screenshot please
 
Status
Not open for further replies.

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
420 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top