/ES Futures Quasi-Algo 1 Hour Out Prediction for ThinkorSwim

mashume

Expert
VIP
Lifetime

EDIT 2021-December

There are many updated versions of this indicator using more recent data. Please start your search at the END of this thread and work your way toward page 1 to find the most recent for whichever instrument you want. If you don't see it, post a request and I'll do my best to fill it in reasonable order.

So, from the data described here:
https://usethinkscript.com/threads/es-futures-probability-at-time-market-timing-differently.6250/
I decided to build an indicator to see what would happen. This indicator is the result of that.

It may or may not be mathematically correct. If you'd like to audit my statistics, shifts, and so forth, please do.

Remember, the bounding boxes are being drawn a minimum of 1 hour before the candles are drawn. They are real predictions, based on probable movements of the market as described in the link above. These use 1st and 3rd quartile deviances from median for the range shown (for those who care).

lkyaxgz.png

Overnight projections.

pzcwUfa.png

Showing regular trading day projections.

T2w8wfw.png

This one shows the predictions in the expansion area on the right.

These are not overly accurate, but an interesting direction in indicators.

I have written a python script to "regenerate" the indicator code so I can run it weekly to update the coefficients if there is interest.

Here's the code for the indicator:
Code:
#########################################################
#
#   Next Hour ES Trading Range
#     Algorithmic Prediction
#   Values Derived on Data from
#          2021-01-12 to
#          2021-04-08
#
#   @mashume at usethinkscript.com
#
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#
#  This Version /ES (and maybe /MES) only
#  Functional on 1, 5, 10, 15, 20, 30, 60 minute charts
#
#########################################################

declare upper;

def Y = 31556926;
def M = 2629743;
def D = 86400;
def H = 3600;
def HalfHour = 1800;
def epoch = (getTime() / 1000);
def YMD = (epoch % Y) - (epoch / Y);
def month = (Floor(YMD / M) + 1);
def GMT = Floor((epoch % D) / H);
def HOUR = if GMT > 4 then GMT - 4 else if GMT < 4 then (GMT + 24) - 4 else 0;

def tf = getAggregationPeriod();

def barsPerHour = if tf == AggregationPeriod.HOUR then 1
    else if tf == AggregationPeriod.THIRTY_MIN then 2
    else if tf == AggregationPeriod.TWENTY_MIN then 3
    else if tf == AggregationPeriod.FIFTEEN_MIN then 4
    else if tf == AggregationPeriod.TEN_MIN then 6
    else if tf == AggregationPeriod.FIVE_MIN then 12
    else if tf == AggregationPeriod.MIN then 60
    else double.nan;

def q1 =
    if HOUR == 0 then -2.25
    else if HOUR == 1 then -3.5
    else if HOUR == 2 then -3.25
    else if HOUR == 3 then -3.5
    else if HOUR == 4 then -2.0
    else if HOUR == 5 then -2.5
    else if HOUR == 6 then -2.0
    else if HOUR == 7 then -4.0
    else if HOUR == 8 then -3.75
    else if HOUR == 9 then -6.25
    else if HOUR == 10 then -4.5
    else if HOUR == 11 then -3.0
    else if HOUR == 12 then -2.812
    else if HOUR == 13 then -3.75
    else if HOUR == 14 then -6.75
    else if HOUR == 15 then -5.75
    else if HOUR == 16 then -1.75
    else if HOUR == 17 then 1.0
    else if HOUR == 18 then -3.5
    else if HOUR == 19 then -3.25
    else if HOUR == 20 then -3.5
    else if HOUR == 21 then -3.5
    else if HOUR == 22 then -2.0
    else -1.25;
def q3 =
    if HOUR == 0 then 2.25
    else if HOUR == 1 then 3.0
    else if HOUR == 2 then 3.75
    else if HOUR == 3 then 4.25
    else if HOUR == 4 then 2.75
    else if HOUR == 5 then 3.25
    else if HOUR == 6 then 3.75
    else if HOUR == 7 then 3.0
    else if HOUR == 8 then 5.312
    else if HOUR == 9 then 8.75
    else if HOUR == 10 then 7.75
    else if HOUR == 11 then 7.0
    else if HOUR == 12 then 5.5
    else if HOUR == 13 then 5.25
    else if HOUR == 14 then 6.562
    else if HOUR == 15 then 6.75
    else if HOUR == 16 then 4.0
    else if HOUR == 17 then 6.25
    else if HOUR == 18 then 3.25
    else if HOUR == 19 then 3.5
    else if HOUR == 20 then 3.75
    else if HOUR == 21 then 2.5
    else if HOUR == 22 then 2.25
    else 2.5;
def m2 =
    if HOUR == 0 then 0.0
    else if HOUR == 1 then -0.5
    else if HOUR == 2 then 0.25
    else if HOUR == 3 then 0.25
    else if HOUR == 4 then 0.25
    else if HOUR == 5 then 0.5
    else if HOUR == 6 then 0.5
    else if HOUR == 7 then -0.25
    else if HOUR == 8 then 0.5
    else if HOUR == 9 then 2.0
    else if HOUR == 10 then 2.75
    else if HOUR == 11 then 2.5
    else if HOUR == 12 then 1.5
    else if HOUR == 13 then 1.0
    else if HOUR == 14 then -0.5
    else if HOUR == 15 then 0.75
    else if HOUR == 16 then 1.0
    else if HOUR == 17 then 2.5
    else if HOUR == 18 then -0.25
    else if HOUR == 19 then 0.5
    else if HOUR == 20 then 0.25
    else if HOUR == 21 then -0.75
    else if HOUR == 22 then 0.5
    else 0.25;

def midline = hl2(period = AggregationPeriod.HOUR)[1];
def median = hl2(period = AggregationPeriod.HOUR)[1] + m2;
def upper = median + (q3);
def lower = median + (q1);

plot c = midline;
c.setStyle(CURve.SHORT_DASH);
c.setDefaultColor(getColor(7));

plot median_line = median[barsPerHour];
median_line.SetPaintingStrategy(PaintingStrategy.DASHES);
median_line.SetDefaultColor(getColor(3));
plot expected_upper = upper[barsPerHour];
expected_upper.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
expected_upper.SetDefaultColor(getColor(1));
plot expected_lower = lower[barsPerHour];
expected_lower.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
expected_lower.SetDefaultColor(getColor(5));

addcloud(expected_upper, expected_lower, color.white, color.white);
def upside = (expected_upper[(-1 * barsPerHour)] - close);
def downside = (close - expected_lower[(-1 * barsPerHour)]);
addLabel(yes, "current upside: " + upside + "  current downside: " + downside, if upside > downside then color.dark_green else if downside > upside then color.dark_red else color.dark_gray);

If you find this useful, let me know. This could, potentially, be applied to any ticker, though it would need to be for a single ticker. If you trade exclusively one symbol, it could be an interesting exercise.

REMEMBER This is just probabilities applied to prices. It's not magic, and it's not always going to be correct.

Happy Trading,
mashume
 
Last edited:

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

Looks very interesting to me ... Lets load it up and spin it ... great contribution to the community ... thank you
 
@mashume Thank you for the script, looks interesting.

Would it work correctly on /RTY, 15 minutes?
It will not, not the version above at any rate... the coefficients are derived from a statistical analysis of /es data.

This one is for RTY:
Code:
#########################################################
#
#   Next Hour RTY Trading Range
#     Algorithmic Prediction
#   Values Derived on Data from
#          2021-02-02 to
#          2021-04-14
#
#   @mashume at usethinkscript.com
#
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#
#  This Version RTY only
#  Functional on 1, 5, 10, 15, 20, 30, 60 minute charts
#
#########################################################

declare upper;

def Y = 31556926;
def M = 2629743;
def D = 86400;
def H = 3600;
def HalfHour = 1800;
def epoch = (getTime() / 1000);
def YMD = (epoch % Y) - (epoch / Y);
def month = (Floor(YMD / M) + 1);
def GMT = Floor((epoch % D) / H);
def HOUR = if GMT > 4 then GMT - 4 else if GMT < 4 then (GMT + 24) - 4 else 0;

def tf = getAggregationPeriod();

def barsPerHour = if tf == AggregationPeriod.HOUR then 1
    else if tf == AggregationPeriod.THIRTY_MIN then 2
    else if tf == AggregationPeriod.TWENTY_MIN then 3
    else if tf == AggregationPeriod.FIFTEEN_MIN then 4
    else if tf == AggregationPeriod.TEN_MIN then 6
    else if tf == AggregationPeriod.FIVE_MIN then 12
    else if tf == AggregationPeriod.MIN then 60
    else double.nan;
 

def q1 =
    if HOUR == 0 then -1.7
    else if HOUR == 1 then -2.425
    else if HOUR == 2 then -2.025
    else if HOUR == 3 then -3.4
    else if HOUR == 4 then -1.7
    else if HOUR == 5 then -2.9
    else if HOUR == 6 then -2.0
    else if HOUR == 7 then -3.5
    else if HOUR == 8 then -4.525
    else if HOUR == 9 then -11.825
    else if HOUR == 10 then -6.8
    else if HOUR == 11 then -4.625
    else if HOUR == 12 then -4.9
    else if HOUR == 13 then -4.9
    else if HOUR == 14 then -5.125
    else if HOUR == 15 then -4.025
    else if HOUR == 16 then -2.0
    else if HOUR == 17 then 0.0
    else if HOUR == 18 then -2.9
    else if HOUR == 19 then -2.8
    else if HOUR == 20 then -3.2
    else if HOUR == 21 then -3.6
    else if HOUR == 22 then -1.9
    else -1.6;
def q3 =
    if HOUR == 0 then 1.8
    else if HOUR == 1 then 2.3
    else if HOUR == 2 then 3.4
    else if HOUR == 3 then 2.8
    else if HOUR == 4 then 2.7
    else if HOUR == 5 then 2.4
    else if HOUR == 6 then 4.8
    else if HOUR == 7 then 3.6
    else if HOUR == 8 then 5.65
    else if HOUR == 9 then 9.0
    else if HOUR == 10 then 10.6
    else if HOUR == 11 then 6.9
    else if HOUR == 12 then 5.425
    else if HOUR == 13 then 4.525
    else if HOUR == 14 then 6.425
    else if HOUR == 15 then 7.5
    else if HOUR == 16 then 3.725
    else if HOUR == 17 then 0.0
    else if HOUR == 18 then 2.45
    else if HOUR == 19 then 2.3
    else if HOUR == 20 then 2.25
    else if HOUR == 21 then 2.2
    else if HOUR == 22 then 2.0
    else 2.0;
def m2 =
    if HOUR == 0 then -0.2
    else if HOUR == 1 then -0.25
    else if HOUR == 2 then 0.6
    else if HOUR == 3 then 0.2
    else if HOUR == 4 then 0.55
    else if HOUR == 5 then -0.1
    else if HOUR == 6 then 1.5
    else if HOUR == 7 then 0.3
    else if HOUR == 8 then 1.2
    else if HOUR == 9 then -1.7
    else if HOUR == 10 then 2.6
    else if HOUR == 11 then 1.4
    else if HOUR == 12 then 0.1
    else if HOUR == 13 then 0.3
    else if HOUR == 14 then 1.0
    else if HOUR == 15 then 1.95
    else if HOUR == 16 then 0.7
    else if HOUR == 17 then 0.0
    else if HOUR == 18 then -0.4
    else if HOUR == 19 then -0.2
    else if HOUR == 20 then -0.4
    else if HOUR == 21 then -0.8
    else if HOUR == 22 then 0.2
    else 0.1;

def midline = hl2(period = AggregationPeriod.HOUR)[1];
def median = hl2(period = AggregationPeriod.HOUR)[1] + m2;
def upper = median + (q3);
def lower = median + (q1);

plot c = midline;
c.setStyle(CURve.SHORT_DASH);
c.setDefaultColor(getColor(7));

plot median_line = median[barsPerHour];
median_line.SetPaintingStrategy(PaintingStrategy.DASHES);
median_line.SetDefaultColor(getColor(3));
plot expected_upper = upper[barsPerHour];
expected_upper.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
expected_upper.SetDefaultColor(getColor(1));
plot expected_lower = lower[barsPerHour];
expected_lower.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
expected_lower.SetDefaultColor(getColor(5));

addcloud(expected_upper, expected_lower, color.white, color.white);
def upside = (expected_upper[(-1 * barsPerHour)] - close);
def downside = (close - expected_lower[(-1 * barsPerHour)]);
addLabel(yes, "current upside: " + upside + "  current downside: " + downside, if upside > downside then color.dark_green else if downside > upside then color.dark_red else color.dark_gray);

Let me know how it works out for you,

Happy Trading,
mashume
 
Last edited:
Hehehehe, @mashume, editing my professors was one of my favorite past times. I seldom caught a mistake but it is fun, trying.
I look forward to checking this out. I am in the process of sorting through a lifetime of 'stuff' and moving a couple of thousand miles.
Once I have my trading station up, I will take it for a spin. Thank you for all your contributions.
Good luck with the move!
 
@mashume Thank you.

Question: Just to double-check, does it adjust automatically and correctly if I switch to a different time frame, say, 30 minutes?
In the original post, you've mentioned a weekly update if there's interest...does it mean that the values in the code are not dynamically updated and are hardcoded?
 
@john3 You're quite welcome.

Answer: This does automatically correct if you switch to any of the listed time frames (1, 5, 10, 15, 20, 30, 60 minutes). It requires a secondary aggregation of 1 hour, and so won't work above 1 hour I believe. It is not, currently, able to work on 2, 3, or 4 minute charts, or on custom times, nor on tick charts (it is time based after all)

As for updates. The coefficient values are hard coded into the indicator. I have not come up with any way to aggregate the same way in ToS that I can in python (where I look at 1 hour p/l and then take statistics based on those p/l numbers aggregated by hour-of-day over the last 60 days.

I did however, write a python script that takes a ticker in and gives back a fully functional cut-and-paste indicator so I don't really do much work when / if people would like custom tickers (or custom p/l time projections for that matter... this is based on 1 hour, but could as easily be based on 2 hours, 30 minutes, or whatever I suppose -- my original post on statistics and time p/l probabilities is linked somewhere above).

Hope that answers some of your questions. If this made you think of more questions, just ask. :)

happy trading,
mashume
 
Haven't downloaded yet - but - would this apply to SPY too?! or need seperate code? (knowing I can look at the two and compare, at worst)
 
Haven't downloaded yet - but - would this apply to SPY too?! or need seperate code? (knowing I can look at the two and compare, at worst)
SPY does not trade around the clock so the data may be different, certainly the prices would be different and ES trades in 1/4 point ticks while SPY is 1/100 I think and then there's the fact that the prices are about an order of magnitude apart :) You can compare the two, but I can look into creating a version of this for SPY if you can't run ES and SPY side by side.

-mashume
 
SPY does not trade around the clock so the data may be different, certainly the prices would be different and ES trades in 1/4 point ticks while SPY is 1/100 I think and then there's the fact that the prices are about an order of magnitude apart :) You can compare the two, but I can look into creating a version of this for SPY if you can't run ES and SPY side by side.

-mashume
that makes sense. I'm not futures approved, so I can only trade spy during the day - no rush. ill watch this for bit! Thanks for the fast reply!
 
that makes sense. I'm not futures approved, so I can only trade spy during the day - no rush. ill watch this for bit! Thanks for the fast reply!
@vro3,
Here ya go. No idea how this will look... I didn't throw it into thinkorswim tonight, just ran the generator and this is what it gave me. Let me know what works and what's broken. Thanks

Code:
#########################################################
#
#   Next Hour SPY Trading Range
#     Algorithmic Future Range Probability
#   Values Derived on Data from
#          2021-01-19 to
#          2021-04-14
#
#   @mashume at usethinkscript.com
#
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#
#  This Version SPY only
#  Functional on 1, 5, 10, 15, 20, 30, 60 minute charts
#
#########################################################

declare upper;

def Y = 31556926;
def M = 2629743;
def D = 86400;
def H = 3600;
def HalfHour = 1800;
def epoch = (getTime() / 1000);
def YMD = (epoch % Y) - (epoch / Y);
def month = (Floor(YMD / M) + 1);
def GMT = Floor((epoch % D) / H);
def HOUR = if GMT > 4 then GMT - 4 else if GMT < 4 then (GMT + 24) - 4 else 0;

def tf = getAggregationPeriod();

def barsPerHour = if tf == AggregationPeriod.HOUR then 1
    else if tf == AggregationPeriod.THIRTY_MIN then 2
    else if tf == AggregationPeriod.TWENTY_MIN then 3
    else if tf == AggregationPeriod.FIFTEEN_MIN then 4
    else if tf == AggregationPeriod.TEN_MIN then 6
    else if tf == AggregationPeriod.FIVE_MIN then 12
    else if tf == AggregationPeriod.MIN then 60
    else double.nan;
    

def q1 =
    if HOUR == 0 then 0.0
    else if HOUR == 1 then 0.0
    else if HOUR == 2 then 0.0
    else if HOUR == 3 then 0.0
    else if HOUR == 4 then -0.2
    else if HOUR == 5 then -0.23
    else if HOUR == 6 then -0.23
    else if HOUR == 7 then -0.37
    else if HOUR == 8 then -0.5
    else if HOUR == 9 then -0.51
    else if HOUR == 10 then -0.45
    else if HOUR == 11 then -0.23
    else if HOUR == 12 then -0.24
    else if HOUR == 13 then -0.381
    else if HOUR == 14 then -0.641
    else if HOUR == 15 then -0.706
    else if HOUR == 16 then -0.12
    else if HOUR == 17 then -0.17
    else if HOUR == 18 then -0.423
    else if HOUR == 19 then -0.675
    else if HOUR == 20 then 0.0
    else if HOUR == 21 then 0.0
    else if HOUR == 22 then 0.0
    else 0.0;
def q3 =
    if HOUR == 0 then 0.0
    else if HOUR == 1 then 0.0
    else if HOUR == 2 then 0.0
    else if HOUR == 3 then 0.0
    else if HOUR == 4 then 0.29
    else if HOUR == 5 then 0.3
    else if HOUR == 6 then 0.36
    else if HOUR == 7 then 0.3
    else if HOUR == 8 then 0.76
    else if HOUR == 9 then 0.92
    else if HOUR == 10 then 0.76
    else if HOUR == 11 then 0.74
    else if HOUR == 12 then 0.546
    else if HOUR == 13 then 0.49
    else if HOUR == 14 then 0.536
    else if HOUR == 15 then 0.529
    else if HOUR == 16 then 0.16
    else if HOUR == 17 then 0.25
    else if HOUR == 18 then 0.65
    else if HOUR == 19 then 0.517
    else if HOUR == 20 then 0.0
    else if HOUR == 21 then 0.0
    else if HOUR == 22 then 0.0
    else 0.0;
def m2 =
    if HOUR == 0 then 0.0
    else if HOUR == 1 then 0.0
    else if HOUR == 2 then 0.0
    else if HOUR == 3 then 0.0
    else if HOUR == 4 then 0.03
    else if HOUR == 5 then 0.05
    else if HOUR == 6 then 0.06
    else if HOUR == 7 then -0.01
    else if HOUR == 8 then 0.142
    else if HOUR == 9 then 0.19
    else if HOUR == 10 then 0.202
    else if HOUR == 11 then 0.29
    else if HOUR == 12 then 0.173
    else if HOUR == 13 then 0.07
    else if HOUR == 14 then -0.053
    else if HOUR == 15 then -0.08
    else if HOUR == 16 then 0.02
    else if HOUR == 17 then -0.005
    else if HOUR == 18 then 0.01
    else if HOUR == 19 then -0.14
    else if HOUR == 20 then 0.0
    else if HOUR == 21 then 0.0
    else if HOUR == 22 then 0.0
    else 0.0;

def midline = hl2(period = AggregationPeriod.HOUR)[1];
def median = hl2(period = AggregationPeriod.HOUR)[1] + m2;
def upper = median + (q3);
def lower = median + (q1);

plot c = midline;
c.setStyle(CURve.SHORT_DASH);
c.setDefaultColor(getColor(7));

plot median_line = median[barsPerHour];
median_line.SetPaintingStrategy(PaintingStrategy.DASHES);
median_line.SetDefaultColor(getColor(3));
plot expected_upper = upper[barsPerHour];
expected_upper.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
expected_upper.SetDefaultColor(getColor(1));
plot expected_lower = lower[barsPerHour];
expected_lower.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
expected_lower.SetDefaultColor(getColor(5));

addcloud(expected_upper, expected_lower, color.white, color.white);
def upside = (expected_upper[(-1 * barsPerHour)] - close);
def downside = (close - expected_lower[(-1 * barsPerHour)]);
addLabel(yes, "current upside: " + upside + "  current downside: " + downside, if upside > downside then color.dark_green else if downside > upside then color.dark_red else color.dark_gray);

happy trading,

-mashume
 
@mashume can we use this on NQ?
Here's a fresh version for you for /NQ. Now also works on 3 minute charts.

Code:
#########################################################
#
#   Next Hour NQ Trading Range
#     Algorithmic Prediction
#   Values Derived on Data from
#          2021-02-03 to
#          2021-04-15
#
#   @mashume at usethinkscript.com
#
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#
#  This Version /NQ (and maybe /MNQ) only
#  Functional on 1, 3, 5, 10, 15, 20, 30, 60 minute charts
#
#########################################################

declare upper;

def Y = 31556926;
def M = 2629743;
def D = 86400;
def H = 3600;
def HalfHour = 1800;
def epoch = (getTime() / 1000);
def YMD = (epoch % Y) - (epoch / Y);
def month = (Floor(YMD / M) + 1);
def GMT = Floor((epoch % D) / H);
def HOUR = if GMT > 4 then GMT - 4 else if GMT < 4 then (GMT + 24) - 4 else 0;

def tf = getAggregationPeriod();

def barsPerHour = if tf == AggregationPeriod.HOUR then 1
    else if tf == AggregationPeriod.THIRTY_MIN then 2
    else if tf == AggregationPeriod.TWENTY_MIN then 3
    else if tf == AggregationPeriod.FIFTEEN_MIN then 4
    else if tf == AggregationPeriod.TEN_MIN then 6
    else if tf == AggregationPeriod.FIVE_MIN then 12
    else if tf == AggregationPeriod.THREE_MIN then 20
    else if tf == AggregationPeriod.MIN then 60
    else double.nan;
    

def q1 =
    if HOUR == 0 then -10.25
    else if HOUR == 1 then -12.75
    else if HOUR == 2 then -16.062
    else if HOUR == 3 then -17.5
    else if HOUR == 4 then -9.0
    else if HOUR == 5 then -13.25
    else if HOUR == 6 then -10.75
    else if HOUR == 7 then -17.75
    else if HOUR == 8 then -26.75
    else if HOUR == 9 then -41.0
    else if HOUR == 10 then -28.188
    else if HOUR == 11 then -20.25
    else if HOUR == 12 then -16.75
    else if HOUR == 13 then -24.625
    else if HOUR == 14 then -26.375
    else if HOUR == 15 then -21.5
    else if HOUR == 16 then -5.75
    else if HOUR == 17 then 0.0
    else if HOUR == 18 then -14.0
    else if HOUR == 19 then -11.25
    else if HOUR == 20 then -16.562
    else if HOUR == 21 then -15.75
    else if HOUR == 22 then -8.75
    else -8.375;
def q3 =
    if HOUR == 0 then 11.25
    else if HOUR == 1 then 18.625
    else if HOUR == 2 then 21.062
    else if HOUR == 3 then 18.25
    else if HOUR == 4 then 14.75
    else if HOUR == 5 then 15.0
    else if HOUR == 6 then 16.562
    else if HOUR == 7 then 16.75
    else if HOUR == 8 then 25.25
    else if HOUR == 9 then 42.0
    else if HOUR == 10 then 37.875
    else if HOUR == 11 then 33.5
    else if HOUR == 12 then 26.312
    else if HOUR == 13 then 21.062
    else if HOUR == 14 then 33.75
    else if HOUR == 15 then 27.812
    else if HOUR == 16 then 16.0
    else if HOUR == 17 then 0.0
    else if HOUR == 18 then 13.75
    else if HOUR == 19 then 16.5
    else if HOUR == 20 then 18.562
    else if HOUR == 21 then 12.938
    else if HOUR == 22 then 8.25
    else 8.75;
def m2 =
    if HOUR == 0 then 0.75
    else if HOUR == 1 then -1.25
    else if HOUR == 2 then 0.75
    else if HOUR == 3 then -1.375
    else if HOUR == 4 then 2.0
    else if HOUR == 5 then -0.625
    else if HOUR == 6 then 3.75
    else if HOUR == 7 then 0.5
    else if HOUR == 8 then 0.0
    else if HOUR == 9 then 2.25
    else if HOUR == 10 then 7.5
    else if HOUR == 11 then 8.25
    else if HOUR == 12 then 5.5
    else if HOUR == 13 then 0.25
    else if HOUR == 14 then 2.75
    else if HOUR == 15 then 3.75
    else if HOUR == 16 then 4.5
    else if HOUR == 17 then 0.0
    else if HOUR == 18 then -2.75
    else if HOUR == 19 then 0.625
    else if HOUR == 20 then 0.25
    else if HOUR == 21 then -2.375
    else if HOUR == 22 then 0.5
    else 2.5;

def midline = hl2(period = AggregationPeriod.HOUR)[1];
def median = hl2(period = AggregationPeriod.HOUR)[1] + m2;
def upper = median + (q3);
def lower = median + (q1);

plot c = midline;
c.setStyle(CURve.SHORT_DASH);
c.setDefaultColor(getColor(7));

plot median_line = median[barsPerHour];
median_line.SetPaintingStrategy(PaintingStrategy.DASHES);
median_line.SetDefaultColor(getColor(3));
plot expected_upper = upper[barsPerHour];
expected_upper.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
expected_upper.SetDefaultColor(getColor(1));
plot expected_lower = lower[barsPerHour];
expected_lower.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
expected_lower.SetDefaultColor(getColor(5));

addcloud(expected_upper, expected_lower, color.white, color.white);
def upside = (expected_upper[(-1 * barsPerHour)] - close);
def downside = (close - expected_lower[(-1 * barsPerHour)]);
addLabel(yes, "current upside: " + upside + "  current downside: " + downside, if upside > downside then color.dark_green else if downside > upside then color.dark_red else color.dark_gray);

As always, feedback is appreciated

Happy Trading,
-mashume
 
@mashume I'm not 100% clear on an update question. Can the RTY script be used going forward without any updates, or does it require an update after a certain period? The median plot, what exactly is it based on? Is it based on an hourly candle, 60 days or 60 hourly candles?

Appreciate your help.
 
@mashume I'm not 100% clear on an update question. Can the RTY script be used going forward without any updates, or does it require an update after a certain period? The median plot, what exactly is it based on? Is it based on an hourly candle, 60 days or 60 hourly candles?

Appreciate your help.
You can use it as long as you like, however, if the market changes behaviour drastically (seasonally, etc...) the probability will not match the coded values very well. Time drift.

The calculation goes like this:
From historical data (going back 60 days for now)
1. take the close for every time t (at 5 minute intervals), get the close price at t + 1 hour and calculate the difference.
2. aggregate that data for each integer hour of the day, so that all the differences for trades opened in the 9 o'clock hour are aggregated
3. run some statistics on that data and find:
- median
- 3rd quartile
- 1st quartile
4. take the average price for this hour (HL2, aggregated by hour)
5. create 3 lines by adding median, 3q, and 1q to the price in step 4
6. shift those lines 1 hour into the future.

Hope that helps.
-mashume
 
Updated the indicator to include a "distance to the median" line label. Compares the current close to the projected median. If you're below the median, the theory goes, the median may pull you up. if you're above the next median, the median may pull you down.

PS I did not update the first post with this script, as the coefficients have changed with time and new data. the version for any of these studies is to look at the date range in the header.

-mashume
Code:
#########################################################
#
#   Next Hour ES Trading Range
#     Algorithmic Prediction
#   Values Derived on Data from
#          2021-02-03 to
#          2021-04-15
#
#   @mashume at usethinkscript.com
#
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#
#  This Version /ES (and maybe /MES) only
#  Functional on 1, 3, 5, 10, 15, 20, 30, 60 minute charts
#
#########################################################

declare upper;

def Y = 31556926;
def M = 2629743;
def D = 86400;
def H = 3600;
def HalfHour = 1800;
def epoch = (getTime() / 1000);
def YMD = (epoch % Y) - (epoch / Y);
def month = (Floor(YMD / M) + 1);
def GMT = Floor((epoch % D) / H);
def HOUR = if GMT > 4 then GMT - 4 else if GMT < 4 then (GMT + 24) - 4 else 0;

def tf = getAggregationPeriod();

def barsPerHour = if tf == AggregationPeriod.HOUR then 1
    else if tf == AggregationPeriod.THIRTY_MIN then 2
    else if tf == AggregationPeriod.TWENTY_MIN then 3
    else if tf == AggregationPeriod.FIFTEEN_MIN then 4
    else if tf == AggregationPeriod.TEN_MIN then 6
    else if tf == AggregationPeriod.FIVE_MIN then 12
    else if tf == AggregationPeriod.THREE_MIN then 20
    else if tf == AggregationPeriod.MIN then 60
    else double.nan;
    

def q1 =
    if HOUR == 0 then -2.25
    else if HOUR == 1 then -3.25
    else if HOUR == 2 then -2.812
    else if HOUR == 3 then -3.5
    else if HOUR == 4 then -1.75
    else if HOUR == 5 then -2.5
    else if HOUR == 6 then -2.0
    else if HOUR == 7 then -3.5
    else if HOUR == 8 then -3.5
    else if HOUR == 9 then -5.688
    else if HOUR == 10 then -4.0
    else if HOUR == 11 then -2.25
    else if HOUR == 12 then -2.812
    else if HOUR == 13 then -4.25
    else if HOUR == 14 then -6.5
    else if HOUR == 15 then -4.5
    else if HOUR == 16 then -1.75
    else if HOUR == 17 then 1.0
    else if HOUR == 18 then -3.25
    else if HOUR == 19 then -3.0
    else if HOUR == 20 then -3.5
    else if HOUR == 21 then -3.5
    else if HOUR == 22 then -2.0
    else -1.5;
def q3 =
    if HOUR == 0 then 2.25
    else if HOUR == 1 then 3.0
    else if HOUR == 2 then 3.75
    else if HOUR == 3 then 3.75
    else if HOUR == 4 then 2.75
    else if HOUR == 5 then 2.75
    else if HOUR == 6 then 3.25
    else if HOUR == 7 then 3.062
    else if HOUR == 8 then 5.0
    else if HOUR == 9 then 8.25
    else if HOUR == 10 then 7.062
    else if HOUR == 11 then 6.75
    else if HOUR == 12 then 5.25
    else if HOUR == 13 then 5.0
    else if HOUR == 14 then 6.25
    else if HOUR == 15 then 6.938
    else if HOUR == 16 then 3.5
    else if HOUR == 17 then 6.25
    else if HOUR == 18 then 2.812
    else if HOUR == 19 then 3.0
    else if HOUR == 20 then 3.25
    else if HOUR == 21 then 2.25
    else if HOUR == 22 then 1.75
    else 2.0;
def m2 =
    if HOUR == 0 then -0.125
    else if HOUR == 1 then -0.25
    else if HOUR == 2 then 0.25
    else if HOUR == 3 then 0.25
    else if HOUR == 4 then 0.375
    else if HOUR == 5 then 0.0
    else if HOUR == 6 then 0.5
    else if HOUR == 7 then 0.0
    else if HOUR == 8 then 0.5
    else if HOUR == 9 then 2.0
    else if HOUR == 10 then 2.25
    else if HOUR == 11 then 2.5
    else if HOUR == 12 then 1.25
    else if HOUR == 13 then 0.75
    else if HOUR == 14 then -0.5
    else if HOUR == 15 then 1.25
    else if HOUR == 16 then 0.75
    else if HOUR == 17 then 2.5
    else if HOUR == 18 then -0.5
    else if HOUR == 19 then 0.25
    else if HOUR == 20 then 0.25
    else if HOUR == 21 then -0.5
    else if HOUR == 22 then 0.25
    else 0.25;

def midline = hl2(period = AggregationPeriod.HOUR)[1];
def median = hl2(period = AggregationPeriod.HOUR)[1] + m2;
def upper = median + (q3);
def lower = median + (q1);

plot c = midline;
c.setStyle(CURve.SHORT_DASH);
c.setDefaultColor(getColor(7));

plot median_line = median[barsPerHour];
median_line.SetPaintingStrategy(PaintingStrategy.DASHES);
median_line.SetDefaultColor(getColor(3));
plot expected_upper = upper[barsPerHour];
expected_upper.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
expected_upper.SetDefaultColor(getColor(1));
plot expected_lower = lower[barsPerHour];
expected_lower.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
expected_lower.SetDefaultColor(getColor(5));

addcloud(expected_upper, expected_lower, color.white, color.white);
def upside = (expected_upper[(-1 * barsPerHour)] - close);
def downside = (close - expected_lower[(-1 * barsPerHour)]);
addLabel(yes, "current upside: " + upside + "  current downside: " + downside, if upside > downside then color.dark_green else if downside > upside then color.dark_red else color.dark_gray);

def dist_to_median = (median_line[(-1 * barsPerHour)] - close);
addLabel(yes, "Distance to Median: " + dist_to_median, 
if dist_to_median > 5 then color.green 
else if dist_to_median > 1 then color.dark_green 
else if dist_to_median < -5 then color.red
else if dist_to_median < -1 then color.dark_red 
else color.gray);
 
Updated the indicator to include a "distance to the median" line label. Compares the current close to the projected median. If you're below the median, the theory goes, the median may pull you up. if you're above the next median, the median may pull you down.

PS I did not update the first post with this script, as the coefficients have changed with time and new data. the version for any of these studies is to look at the date range in the header.

-mashume
Code:
#########################################################
#
#   Next Hour ES Trading Range
#     Algorithmic Prediction
#   Values Derived on Data from
#          2021-02-03 to
#          2021-04-15
#
#   @mashume at usethinkscript.com
#
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#
#  This Version /ES (and maybe /MES) only
#  Functional on 1, 3, 5, 10, 15, 20, 30, 60 minute charts
#
#########################################################

declare upper;

def Y = 31556926;
def M = 2629743;
def D = 86400;
def H = 3600;
def HalfHour = 1800;
def epoch = (getTime() / 1000);
def YMD = (epoch % Y) - (epoch / Y);
def month = (Floor(YMD / M) + 1);
def GMT = Floor((epoch % D) / H);
def HOUR = if GMT > 4 then GMT - 4 else if GMT < 4 then (GMT + 24) - 4 else 0;

def tf = getAggregationPeriod();

def barsPerHour = if tf == AggregationPeriod.HOUR then 1
    else if tf == AggregationPeriod.THIRTY_MIN then 2
    else if tf == AggregationPeriod.TWENTY_MIN then 3
    else if tf == AggregationPeriod.FIFTEEN_MIN then 4
    else if tf == AggregationPeriod.TEN_MIN then 6
    else if tf == AggregationPeriod.FIVE_MIN then 12
    else if tf == AggregationPeriod.THREE_MIN then 20
    else if tf == AggregationPeriod.MIN then 60
    else double.nan;
   

def q1 =
    if HOUR == 0 then -2.25
    else if HOUR == 1 then -3.25
    else if HOUR == 2 then -2.812
    else if HOUR == 3 then -3.5
    else if HOUR == 4 then -1.75
    else if HOUR == 5 then -2.5
    else if HOUR == 6 then -2.0
    else if HOUR == 7 then -3.5
    else if HOUR == 8 then -3.5
    else if HOUR == 9 then -5.688
    else if HOUR == 10 then -4.0
    else if HOUR == 11 then -2.25
    else if HOUR == 12 then -2.812
    else if HOUR == 13 then -4.25
    else if HOUR == 14 then -6.5
    else if HOUR == 15 then -4.5
    else if HOUR == 16 then -1.75
    else if HOUR == 17 then 1.0
    else if HOUR == 18 then -3.25
    else if HOUR == 19 then -3.0
    else if HOUR == 20 then -3.5
    else if HOUR == 21 then -3.5
    else if HOUR == 22 then -2.0
    else -1.5;
def q3 =
    if HOUR == 0 then 2.25
    else if HOUR == 1 then 3.0
    else if HOUR == 2 then 3.75
    else if HOUR == 3 then 3.75
    else if HOUR == 4 then 2.75
    else if HOUR == 5 then 2.75
    else if HOUR == 6 then 3.25
    else if HOUR == 7 then 3.062
    else if HOUR == 8 then 5.0
    else if HOUR == 9 then 8.25
    else if HOUR == 10 then 7.062
    else if HOUR == 11 then 6.75
    else if HOUR == 12 then 5.25
    else if HOUR == 13 then 5.0
    else if HOUR == 14 then 6.25
    else if HOUR == 15 then 6.938
    else if HOUR == 16 then 3.5
    else if HOUR == 17 then 6.25
    else if HOUR == 18 then 2.812
    else if HOUR == 19 then 3.0
    else if HOUR == 20 then 3.25
    else if HOUR == 21 then 2.25
    else if HOUR == 22 then 1.75
    else 2.0;
def m2 =
    if HOUR == 0 then -0.125
    else if HOUR == 1 then -0.25
    else if HOUR == 2 then 0.25
    else if HOUR == 3 then 0.25
    else if HOUR == 4 then 0.375
    else if HOUR == 5 then 0.0
    else if HOUR == 6 then 0.5
    else if HOUR == 7 then 0.0
    else if HOUR == 8 then 0.5
    else if HOUR == 9 then 2.0
    else if HOUR == 10 then 2.25
    else if HOUR == 11 then 2.5
    else if HOUR == 12 then 1.25
    else if HOUR == 13 then 0.75
    else if HOUR == 14 then -0.5
    else if HOUR == 15 then 1.25
    else if HOUR == 16 then 0.75
    else if HOUR == 17 then 2.5
    else if HOUR == 18 then -0.5
    else if HOUR == 19 then 0.25
    else if HOUR == 20 then 0.25
    else if HOUR == 21 then -0.5
    else if HOUR == 22 then 0.25
    else 0.25;

def midline = hl2(period = AggregationPeriod.HOUR)[1];
def median = hl2(period = AggregationPeriod.HOUR)[1] + m2;
def upper = median + (q3);
def lower = median + (q1);

plot c = midline;
c.setStyle(CURve.SHORT_DASH);
c.setDefaultColor(getColor(7));

plot median_line = median[barsPerHour];
median_line.SetPaintingStrategy(PaintingStrategy.DASHES);
median_line.SetDefaultColor(getColor(3));
plot expected_upper = upper[barsPerHour];
expected_upper.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
expected_upper.SetDefaultColor(getColor(1));
plot expected_lower = lower[barsPerHour];
expected_lower.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
expected_lower.SetDefaultColor(getColor(5));

addcloud(expected_upper, expected_lower, color.white, color.white);
def upside = (expected_upper[(-1 * barsPerHour)] - close);
def downside = (close - expected_lower[(-1 * barsPerHour)]);
addLabel(yes, "current upside: " + upside + "  current downside: " + downside, if upside > downside then color.dark_green else if downside > upside then color.dark_red else color.dark_gray);

def dist_to_median = (median_line[(-1 * barsPerHour)] - close);
addLabel(yes, "Distance to Median: " + dist_to_median,
if dist_to_median > 5 then color.green
else if dist_to_median > 1 then color.dark_green
else if dist_to_median < -5 then color.red
else if dist_to_median < -1 then color.dark_red
else color.gray);
Works perfectly...Thank you
 

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
382 Online
Create Post

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