Hull Moving Average Watchlist Column for ThinkorSwim

BenTen

BenTen

Administrative
Staff
VIP
Here is a custom watchlist column for ThinkorSwim that shows when the Hull Moving Average is changing direction. This is great for traders with a lot of stocks on their watchlist and need a quick way to identify potential trend changes via the Hull moving average (HMA) indicator.

When importing the watchlist, be sure to select the timeframe you wish to use. The Daily is set as default.



thinkScript Code

Code:
#Follow @Krose_TDA on twitter for updates to this and other custom columns
#TD Ameritrade IP Company, Inc. (c) 2008-2019
#Follow @Krose_TDA on twitter for updates to this and other custom columns
#Input desired parameters using the input statements below

input price = close;
input length = 20;
input WithinBars = 1;

def hma = HullMovingAvg(price,length);

def TriglableBull = hma[1]<hma[2] and hma>hma[1];
def TriglableBear = hma[1]>hma[2]and hma < hma[1];
def trigger = TriglableBear or TriglableBull;

addlabel(yes,if triglableBear then "bear" else if TriglableBull then "Bull" else " ");

Shareable Link

https://tos.mx/x3Rk12Z
Watch this video to learn more about it


Credit: Ken Rose
 
S

stocksniper

Member
This is great, but is there any way it could stay on the word "Bull" until it changes to Bearish, and when its Bearish to stay on that word until it turns back to bullish. The words disappear after one candle, if that could get fix this would be great I love it. Thanks!!!
 
D

diazlaz

Well-known member
2019 Donor
VIP
This is great, but is there any way it could stay on the word "Bull" until it changes to Bearish, and when its Bearish to stay on that word until it turns back to bullish. The words disappear after one candle, if that could get fix this would be great I love it. Thanks!!!

Here you go!

Chart Behavior



Watchlist:



Ruby:
#Follow @Krose_TDA on twitter for updates to this and other custom columns
#TD Ameritrade IP Company, Inc. (c) 2008-2019
#Follow @Krose_TDA on twitter for updates to this and other custom columns
#Input desired parameters using the input statements below
#
#2019.10.11 - @diazlaz - Updated to include persist state
#

input price = close;
input length = 20;
input WithinBars = 1;

def hma = HullMovingAvg(price,length);

def TriglableBull = hma[1]<hma[2] and hma>hma[1];
def TriglableBear = hma[1]>hma[2]and hma < hma[1];
def trigger = TriglableBear or TriglableBull;
def sTrigger = if TriglableBear then -100 else if TriglableBull then 100 else sTrigger[1];

AddLabel(yes,
if sTrigger == -100 then "Bear" else "Bull",
if sTrigger == -100 then COLOR.RED  else COLOR.GREEN
);

#plot results = sTrigger;
 
Last edited:
D

diazlaz

Well-known member
2019 Donor
VIP
What's also interesting, is that you can put let's say the SP500, with industry information, then export to excel, pivot on the Bear and Bull columns, wonder if this help you all build a watchlist and pivot on the market leaders by industry by sub-industry and then build travels with the highest momentum and index for the subset of the index.

If anyone has any good strategies or ideas on leveraging this column to help in sector rotation or sector stock selection please share ;)
 
BenTen

BenTen

Administrative
Staff
VIP
@diazlaz Appreciate you for making modification to it. Amazing work!
 
markos

markos

Well-known member
VIP
What's also interesting, is that you can put let's say the SP500, with industry information, then export to excel, pivot on the Bear and Bull columns, wonder if this help you all build a watchlist and pivot on the market leaders by industry by sub-industry and then build travels with the highest momentum and index for the subset of the index.
If anyone has any good strategies or ideas on leveraging this column to help in sector rotation or sector stock selection please share ;)
@diazlaz
If anyone has any good strategies or ideas on leveraging this column to help in sector rotation or sector stock selection please share
This is something that I and JohnnyQuotron from the TSL have been on a quest to find. It is an excellent idea. I don't know about leveraging that particular column but I do have one share to study which might help if a Hull(20) was used.
 
markos

markos

Well-known member
VIP
@diazlaz See if this concept is workable. Idealy, to me, SPY should be at ==0 with the others rotating around it. Thoughts?
@BenTen Please copy this to its own thread...
Code:
# beta_rotation_v2
#ETF_Rotate_Lower_ED_nn 4-2019
# from 4/4/2019 chat room:
# 06:37 Mobius: johnny - To find rotation quickly - Use primary ETF's in a watchlist with 2 columns first column is Correlation to SPX second is a stochastic of Beta, if Beta is 1 or close to 1 that ETF is moving at the fastest momentum in that range and if correlation is with SPX .85 or better it's moving with SPX cor# daily start with 13,34 as starting point
#markos #took out out Beta 1 & 2 4-19-19 # Put Back in 6-23-19

declare lower;

input BetaLength = 21;
input StochLength =34;
input showBeta = No;
input showOverlay = Yes;

input Cyclicals      = "XLY";
input Technology     = "XLK";
input Industrials    = "XLI";
input Materials      = "XLB";
input Energy         = "XLE";
input Staples        = "XLP";
input HealthCare     = "XLV";
input Utilities      = "XLU";
input Financials     = "XLF";

#------------------------------
#----purple colors
defineglobalColor(“PlumMedium“, createColor(221, 160, 221));
defineglobalColor(“Orchid“, createColor(218, 130, 214));
defineglobalColor(“MediumOrchid“, createColor(186, 85, 211));
defineglobalColor(“MediumPurple“, createColor(147, 112, 219));
defineglobalColor(“DarkOrchid“, createColor(153, 50, 204));


plot Scriptlabel = Double.NaN;
Scriptlabel.SetDefaultColor(CreateColor (0, 0, 0));

def Agg = GetAggregationPeriod();

#--------------------date start
addLabel(1,  getMonth() + "/" +
             getDayOfMonth(getYyyyMmDd()) + "/" +
             AsPrice(getYear()), GlobalColor("PlumMedium"));
#--------------------date end

#addLabel(1, " Ticker: '" + GetSymbol() + "' ", GlobalColor("Orchid"));

addLabel(1, "Agg: " +
              ( if Agg == 60000 then "1 Min"
           else if Agg == 120000 then "2 Min"
           else if Agg == 180000 then "3 Min"
           else if Agg == 240000 then "4 Min"
           else if Agg == 300000 then "5 Min"
           else if Agg == 600000 then "10 Min"
           else if Agg == 900000 then "15 Min"
           else if Agg == 1800000 then "30 Min"
           else if Agg == 3600000 then "1 Hour"
           else if Agg == 7200000 then "2 Hour"
           else if Agg == 14400000 then "4 Hours"
           else if Agg == 86400000 then "1 Day"
           else if Agg == 604800000 then "1 Week"
           else if Agg == 2592000000 then "1 Month"
           else  (Agg / 1000 / 60) + "Minutes")  +
           " (" + (if Agg<=23400000
                   then 23400000/Agg
                   else 86400000/Agg)+ ")"
          , GlobalColor("MediumPurple"));
#addLabel(1, BarNumber() + " Bars", GlobalColor("DarkOrchid"));

#-----------------------------
#-----------------------------

addLabel(1,"Rotation Beta/Stochastic (" + betaLength + "," +stochLength + ") ", color.Light_Gray);


script calcBeta {
  input secondSymbol = "XLF";
  input refSymbol = "SPX";
  input betaLength = 21;
  input returnLength = 1;

  def refPrice = close(refSymbol);
  def primary = if refPrice[returnLength] == 0
                then 0
                else (refPrice - refPrice[returnLength]) /
                      refPrice[returnLength] * 100;
  def secondPrice = close(secondSymbol);
  def secondary = if secondPrice[returnLength] == 0
                  then 0
                  else (secondPrice - secondPrice[returnLength]) /
                        secondPrice[returnLength] * 100;
  plot Beta = covariance(secondary, primary, betaLength) /
                         Sqr(stdev(primary, betaLength));
}

script EhlersESSfilter {
    input price = close;
    input length = 8;
    def ESS_coeff_0 = Exp(-Double.Pi * Sqrt(2) / length);
    def ESS_coeff_2 = 2 * ESS_coeff_0 * Cos(Sqrt(2) * Double.Pi / length);
    def ESS_coeff_3 = - Sqr(ESS_coeff_0);
    def ESS_coeff_1 = 1 - ESS_coeff_2 - ESS_coeff_3;
    def ESS_filter = if IsNaN(price + price[1]) then
                      ESS_filter[1]
                 else ESS_coeff_1 * (price + price[1]) / 2 +
                      ESS_coeff_2 * ESS_filter[1] +
                      ESS_coeff_3 * ESS_filter[2];
    plot Smooth_Filter =
         if barnumber() <  length then
              price
         else if !IsNaN(price) then
              ESS_filter
         else Double.NaN;
}

script calcStoch {
  input data = close;
  input StochLength = 21;
  def stochasticValue = ((data - lowest(data, StochLength)) /
                         (highest(data, StochLength) - lowest(data, StochLength)));
  plot stoch = stochasticValue;
}

plot beta1 = if showBeta then calcBeta(Cyclicals) else Double.NaN;
plot beta2 = if showBeta then calcBeta(Technology) else Double.NaN;
####
plot stoch1 = calcStoch(
                        data = EhlersESSfilter(
                               calcBeta(secondSymbol = Cyclicals,
                               betaLength = BetaLength)),
                                     stochLength = StochLength);
stoch1.SetDefaultColor(Color.VIOLET);
stoch1.SetLineWeight(2);
stoch1.SetPaintingStrategy(PaintingStrategy.LINE_VS_SQUARES);
stoch1.HideBubble();
AddLabel(ShowOverlay, " Cyclicals ", Color.VIOLET);
AddChartBubble(ShowOverlay and IsNaN(close[-1]) and !IsNaN(close), if stoch1 < 0.15 then 0 else if stoch1 > 0.85 then 1 else stoch1, "Cyclicals", Color.VIOLET, stoch1 > 0.5);

plot stoch2 = calcStoch(
                        data = EhlersESSfilter(
                               calcBeta(secondSymbol = Technology,
                               betaLength = BetaLength)),
                                     stochLength = StochLength);
stoch2.SetDefaultColor(CreateColor(90, 160, 120));
stoch2.SetLineWeight(5);
stoch2.SetStyle(Curve.LONG_DASH);
stoch2.HideBubble();
AddLabel(ShowOverlay, " Techology ", CreateColor(90, 160, 120));
AddChartBubble(ShowOverlay and IsNaN(close[-1]) and !IsNaN(close), if stoch2 < 0.15 then 0 else if stoch2 > 0.85 then 1 else stoch2, "Technology", CreateColor(90, 160, 120), stoch2 > 0.5);

plot stoch3 = calcStoch(
                        data = EhlersESSfilter(
                               calcBeta(secondSymbol = Industrials,
                               betaLength = BetaLength)),
                                     stochLength = StochLength);
stoch3.SetDefaultColor(Color.MAGENTA);
stoch3.SetLineWeight(5);
stoch3.SetStyle(Curve.SHORT_DASH);
stoch3.HideBubble();
AddLabel(ShowOverlay, " Industrials ", Color.MAGENTA);
AddChartBubble(ShowOverlay and IsNaN(close[-1]) and !IsNaN(close), if stoch3 < 0.15 then 0 else if stoch3 > 0.85 then 1 else stoch3, "Industrials", Color.MAGENTA, stoch3 > 0.5);

plot stoch4 = calcStoch(
                        data = EhlersESSfilter(
                               calcBeta(secondSymbol = Materials,
                               betaLength = BetaLength)),
                                     stochLength = StochLength);
stoch4.SetDefaultColor(Color.CYAN);
stoch4.SetLineWeight(2);
stoch4.SetPaintingStrategy(PaintingStrategy.LINE);
stoch4.HideBubble();
AddLabel(ShowOverlay, " Materials ", Color.CYAN);
AddChartBubble(ShowOverlay and IsNaN(close[-1]) and !IsNaN(close), if stoch4 < 0.15 then 0 else if stoch4 > 0.85 then 1 else stoch4, "Materials", Color.CYAN, stoch4 > 0.5);

plot stoch5 = calcStoch(
                        data = EhlersESSfilter(
                               calcBeta(secondSymbol = Energy,
                               betaLength = BetaLength)),
                                     stochLength = StochLength);
stoch5.SetDefaultColor(Color.YELLOW);
stoch5.SetLineWeight(1);
stoch5.SetPaintingStrategy(PaintingStrategy.Line_vs_POINTS);
stoch5.HideBubble();
AddLabel(ShowOverlay, " Energy ", Color.YELLOW);
AddChartBubble(ShowOverlay and IsNaN(close[-1]) and !IsNaN(close), if stoch5 < 0.15 then 0 else if stoch5 > 0.85 then 1 else stoch5, "Energy", Color.YELLOW, stoch5 > 0.5);

plot stoch6 = calcStoch(
                        data = EhlersESSfilter(
                               calcBeta(secondSymbol = Staples,
                               betaLength = BetaLength)),
                                     stochLength = StochLength);
stoch6.SetDefaultColor(CreateColor(80, 180, 70));
stoch6.SetLineWeight(2);
stoch6.SetPaintingStrategy(PaintingStrategy.LINE_VS_TRIANGLES);
stoch6.HideBubble();
AddLabel(ShowOverlay, " Staples ", CreateColor(80, 180, 70));
AddChartBubble(ShowOverlay and IsNaN(close[-1]) and !IsNaN(close), if stoch6 < 0.15 then 0 else if stoch6 > 0.85 then 1 else stoch6, "Staples", CreateColor(80, 180, 70), stoch6 > close);

plot stoch7 = calcStoch(
                        data = EhlersESSfilter(
                               calcBeta(secondSymbol = HealthCare,
                               betaLength = BetaLength)),
                                     stochLength = StochLength);
stoch7.SetDefaultColor(CreateColor(180, 80, 180));
stoch7.SetLineWeight(4);
stoch7.SetPaintingStrategy(PaintingStrategy.LINE);
stoch7.HideBubble();
AddLabel(ShowOverlay, " HealthCare ", CreateColor(180, 80, 180));
AddChartBubble("time condition" = ShowOverlay and IsNaN(close[-1]) and !IsNaN(close), "price location" = if stoch7 < 0.15 then 0 else if stoch7 > 0.85 then 1 else stoch7, text = "HealthCare", color = CreateColor(180, 80, 180), stoch7 > 0.5);

plot stoch8 = calcStoch(
                        data = EhlersESSfilter(
                               calcBeta(secondSymbol = Utilities,
                               betaLength = BetaLength)),
                                     stochLength = StochLength);
stoch8.SetDefaultColor(Color.ORANGE);
stoch8.SetLineWeight(2);
stoch8.SetPaintingStrategy(PaintingStrategy.LINE);
stoch8.HideBubble();
AddLabel(ShowOverlay, " Utilities ", Color.ORANGE);
AddChartBubble(ShowOverlay and IsNaN(close[-1]) and !IsNaN(close[0]), if stoch8 < 0.15 then 0 else if stoch8 > 0.85 then 1 else stoch8, "Utilities", Color.ORANGE, stoch8 > 0.5);

plot stoch9 = calcStoch(
                        data = EhlersESSfilter(
                               calcBeta(secondSymbol = Financials,
                               betaLength = BetaLength)),
                                     stochLength = StochLength);
stoch9.SetDefaultColor(Color.PINK);
stoch9.SetLineWeight(2);
stoch9.SetPaintingStrategy(PaintingStrategy.LINE_VS_POINTS);
stoch9.HideBubble();
AddLabel(ShowOverlay, " Financials ", Color.PINK);
AddChartBubble(ShowOverlay and IsNaN(close[-1]) and !IsNaN(close), if stoch9 < 0.15 then 0 else if stoch9 > 0.85 then 1 else stoch9, "Financials", Color.PINK, stoch9 > 0.5);

#----------------------------------------------
def barNumber = BarNumber();
def endBar = if !IsNaN(close) and IsNaN(close[-1]) then barNumber else endBar[1];
def lastBar = HighestAll(endBar);
input flowLabelStep = 40;
addLabel(1,"Last Bar = " + lastBar, color.Light_Gray);
DefineGlobalColor("YellowGreen", CreateColor(90, 140, 5));
AddChartBubble(barNumber == (lastBar - flowLabelStep), 1.01,
"M O N E Y   F L O W S   I N", globalColor("YellowGreen"), 1);
AddChartBubble(barNumber == (lastBar - 2*flowLabelStep), 1.01,
"M O N E Y   F L O W S   I N", globalColor("YellowGreen"), 1);
#mAddChartBubble(barNumber == (lastBar - 3*flowLabelStep), 1.01,
#"M O N E Y   F L O W S   I N", globalColor("YellowGreen"), 1);

DefineGlobalColor("Cinamon", CreateColor(200, 10, 40));
AddChartBubble(barNumber == (lastBar - flowLabelStep), -0.01,
"M O N E Y   F L O W S   O U T", globalColor("Cinamon"), 0);
AddChartBubble(barNumber == (lastBar - 2*flowLabelStep), -0.01,
"M O N E Y   F L O W S   O U T", globalColor("Cinamon"), 0);
#mAddChartBubble(barNumber == (lastBar - 3*flowLabelStep), -0.01,
#m"M O N E Y   F L O W S   O U T", globalColor("Cinamon"), 0);

#plot zero = if isNaN(close) then double.nan else 0;
plot zero = if barNumber > (lastBar + 7) then double.nan else 0;
zero.SetDefaultColor(createColor(90, 20, 20));
zero.SetStyle(Curve.Long_Dash);
zero.SetLineWeight(5);
zero.HideBubble();
plot one = if barNumber > (lastBar + 7) then double.nan else 1;
one.SetDefaultColor(createColor(20, 70, 20));
one.SetStyle(Curve.Long_Dash);
one.SetLineWeight(5);
one.HideBubble();
#EOC

SectorRotate_ED_NN

 
markos

markos

Well-known member
VIP
Ultimately, It would be good to have it in this format but I believe that Market Scholars (Former Investools folks) do this in Excel. For ±$3000/year!!
 
D

diazlaz

Well-known member
2019 Donor
VIP
Thanks all! I have a few ideas, going to work up an experiment over the weekend and look at the studies you all have provided to see if we can create something here and build upon all of this.

Thanks All!
 
J007RMC

J007RMC

Well-known member
2019 Donor
VIP
Thanks BEN, added this to my watchlist and will be using this
 
D

diazlaz

Well-known member
2019 Donor
VIP
Hi Everyone, I wanted to pick this up and connect some of the dots. So the first criteria i'm using is taking the SP100, list of stocks and industries, then mapping it to the Hull Bull or Bear Category, and also added a Bull (New) or Bear (New) if the state of the symbol changed in the last 24 hours and is new, then pivoted it by industry, and then group it to the NetChange %52WksChange (IBD) formula to identify the hottest stock in the sector, then lastly crossed reference it with Ben's Blast Off.

In the SP100 there are 32 stocks that triggered the Blast Off condition on Friday. Quick Bullish outcome.








What can we all do with this? Any further enhancements or feedback to this system/approach? I will share it but expect in return community collaboration to enhance it further in return.

Top 5 Stocks that are ready to blast off - Week ending October 18th 2019.



If anyone is willing to start putting together a trading system around this and perhaps all can test, backtest and benchmark, i will start a separate thread and see if we can build a weekly trading system with entries and exits. anyone willing to take a first step at it?
 
Last edited:
D

diazlaz

Well-known member
2019 Donor
VIP
@markos this is amazing work. all that is remaining is to capture the net change of the previous value (add it to the label) to see the net change easily in the label. then track the net change daily.
 
H

hanimusa

New member
Hi @diazlaz

how can I make the candle caller like this
it just give me the note ( bear or blue)
 
R

RPrado

Member
Lifetime
@markos thanks for sharing such indicator. Is this to be used on Daily timeframe only? Thanks,
 
R

RPrado

Member
Lifetime
@BenTen I setup the watchlist, but it keeps showing me "customer expression". I am pretty sure I must have done something wrong, just do not know what. Can you please assist? thanks,
 
R

RPrado

Member
Lifetime
@BenTen I changed to this persist version, and I now I see the BEAR and BULL signals in the watchlist. Thank you.
 
markos

markos

Well-known member
VIP
@markos this is amazing work. all that is remaining is to capture the net change of the previous value (add it to the label) to see the net change easily in the label. then track the net change daily.
Right now I am strapped for time, at least for the next week it will be hit and run. I was thinking of sector rotation for the 1wk, 2wk, and 4 wk periods, to attempt to catch the turn early. I just pulled those numbers out of thin air....
The SPY, IF it is in the code should be at 50 so that we can see if a certain sector is outperforming the overall SP500. Just a thought, might be a bad one. ?? What ever happens, this would need to go back to it's original creator, ED_nn.
 
markos

markos

Well-known member
VIP
@markos thanks for sharing such indicator. Is this to be used on Daily timeframe only? Thanks,
A Hull can be used on almost any time frame. You would have to play with it and let us know your thoughts. 20 day for weekly, 10 day for daily is where I would start. Run it on several charts and post them so that all can see how they behave.
 

Similar threads

Top