RTH High Low (Murrey Math / Donchian ) Strategy

RickK

Active member
Here's a promising looking strategy that I found on thinkScript_Cloud. (I hope I'm allowed to post it here. ) It seems to be quite profitable with very manageable losses on small timeframes. Futures trading mostly, I think. There was no discussion where I found it, so I was hoping to get some going here. Apparently it has to do with Murrey Math / Donchian .... the former of which I know absolutely nothing about; the latter of which has not been kind to me in the past.

If you like it, can explain it, and/or find potential, please post back how you've used it. Specifically, with what other non-correlated confirming indicators have you used it, thoughts for improvements and possibly any rules you may come up with. I have not tested it in real-time yet, but I suspect that there might have some repainting as there is a higher time frame aggregation component.

BTW, apparently it has had the name "RSI_MultiAggregationStrat_DMonkey" in the past.

Oh, I made one small edit. I added an input for tradesize, since the original script limited it to 1 in the AddOrder command. After doing so, I tried it on $UPRO and $AAPL, modifying the tradesize input to 200...but it didn't really like that much.

qMQntrh.png


Code:
#StudyName: RTH // High // Low
#Description: Plots developing intraday high and low
#Author: DMonkey
#Requested By:  ActiveTrader
# Ver   2  Up:Date 12/20/2017   : updated bubbles
# TOS.mx Link:
# Trading Notes:
# Added an input for tradesize, since the AddOrder had previously fixed it at 1.  @Rick_Kennedy, member, usethinkscript.com


input bubbleson = yes;
input market_open = 0930;
input Duration_In_Hours = 6.5;
input Fraction = .3;
input range_picker =yes;
input Paint_Bars = yes;
input tradesize = 1;

def   h = high;
def   l = low;
def   na = double.nan;
def   Market_Duration = Duration_In_Hours * 60 * 60;
def   Go_Time = secondsFromTime(market_open);
def   openhigh = if Go_Time ==0
                 then h
                 else if h > openhigh[1]
                 then h
                 else openhigh[1];

plot   data =  
                 if Go_Time >= 0
                 && go_Time < Market_Duration
                 then openhigh
                 else na
                 ;
data.setpaintingStrategy(PaintingStrategy.DASHES);
data.setdefaultColor(Color.YELLOW);
data.setlineWeight(3);

def openlow = if Go_Time == 0
              then l
              else if l < openlow[1]
              then l
              else openlow[1];

plot data2 =   
                 if Go_Time >= 0
                 && go_Time < Market_Duration
                 then openlow
                 else na
               
                ;
data2.setpaintingStrategy(PaintingStrategy.DASHES);
data2.setdefaultColor(Color.MAGENTA);
data2.setlineWeight(3);

def RTH_High_bubble =
                 if Go_Time >= 0
                 then highestall(data)
                 else na;
def RTH_Low_bubble =
                 if Go_Time >= 0
                 then lowestall(data2)
                 else na;               
AddChartBubble("time condition" = bubbleson == yes
                && if isnan(close[-1]) && !isnan(close)
                then (RTH_High_bubble)
                else na ,
               "price location" = (RTH_High_bubble),
                text = "RTH High : " + asdollars(round((RTH_High_bubble)/ ticksize(),0)* ticksize()),
                color = Color.BLUE);
AddChartBubble("time condition" = bubbleson == yes
                && if isnan(close[-1]) && !isnan(close)
                then RTH_Low_bubble
                else na ,
               "price location" = RTH_Low_bubble,
                text = "RTH Low : " + asdollars(round((RTH_Low_bubble)/ ticksize(),0)* ticksize()),
                color = Color.GRAY,
                up = No);
#   End Code

def range = Fraction *(data - data2);
plot se = data - range;
plot le = data2 + range;

def expansion_direction = if se > se[1] then 1 else if se < se[1] then 2 else expansion_direction[1];
addlabel(1,"Market is expanding " + if expansion_direction == 1 then "up." else if expansion_direction == 2 then "down." else "flat.",
       if expansion_direction == 1 then color.green else if expansion_direction == 2 then color.red else color.orange);

input agg = aggregationPeriod.FOUR_MIN;
#input length = 100; # minval = 10
input mult1 = 0.125; # title = "Mutiplier; Only Supports 0.125 = 1/8");
input lines = 1;    # true  title= "Show Murrey Math Fractals");
input bc = 1;       # (true, title = "Show Bar Colors Based On Oscillator");

# Donchanin Channel

def hi = data;

def lo = data2;

def range2 = hi - lo;
def multiplier = (range2) * mult1;
def midline = lo + multiplier * 4;

plot oscillator = ExpAverage((close(period = agg) - midline) / (if range_picker then range2 / 2 else range / 2), 1);
oscillator.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);

def a = oscillator > 0 and oscillator < mult1 * 2;
def b = oscillator > 0 and oscillator < mult1 * 4;
def c = oscillator > 0 and oscillator < mult1 * 6;
def d = oscillator > 0 and oscillator < mult1 * 8;

def z = oscillator < 0 and oscillator > -mult1 * 2;
def y = oscillator < 0 and oscillator > -mult1 * 4;
def x = oscillator < 0 and oscillator > -mult1 * 6;
def w = oscillator < 0 and oscillator > -mult1 * 8;

oscillator.AssignValueColor( if a == 1
     then Color.ORANGE
     else if b == 1 then Color.ORANGE
     else if c == 1 then Color.ORANGE
     else if d == 1 then Color.GREEN
     else if z == 1 then Color.ORANGE
     else if y == 1 then Color.ORANGE
     else if x == 1 then Color.ORANGE
     else if w == 1 then Color.RED
     else Color.BLUE);

plot L0 = 0;
L0.AssignValueColor(Color.CYAN);

plot PositiveQuadrant1 = if lines == 1 then mult1 * 2 else Double.NaN;
plot PositiveQuadrant2 = if lines == 1 then mult1 * 4 else Double.NaN;
plot PositiveQuadrant3 = if lines == 1 then mult1 * 6 else Double.NaN;
plot PositiveQuadrant4 = if lines == 1 then mult1 * 8 else Double.NaN;
plot NegativeQuadrant1 = if lines == 1 then -mult1 * 2 else Double.NaN;
plot NegativeQuadrant2 = if lines == 1 then -mult1 * 4 else Double.NaN;
plot NegativeQuadrant3 = if lines == 1 then -mult1 * 6 else Double.NaN;
plot NegativeQuadrant4 = if lines == 1 then -mult1 * 8 else Double.NaN;

PositiveQuadrant1.AssignValueColor(Color.LIGHT_GRAY);
PositiveQuadrant2.AssignValueColor(Color.LIGHT_GRAY);
PositiveQuadrant3.AssignValueColor(Color.LIGHT_GRAY);
PositiveQuadrant4.AssignValueColor(Color.LIGHT_GRAY);
NegativeQuadrant1.AssignValueColor(Color.LIGHT_GRAY);
NegativeQuadrant2.AssignValueColor(Color.LIGHT_GRAY);
NegativeQuadrant3.AssignValueColor(Color.LIGHT_GRAY);
NegativeQuadrant4.AssignValueColor(Color.LIGHT_GRAY);

assignPriceColor(if Paint_Bars
                 then if oscillator > 0 then color.green else color.red
                 else color.current);

input offset = -1;
def buy_condition =  oscillator crosses above 0 or oscillator crosses above w or oscillator crosses above d;
def sell_condition = oscillator crosses below 0 or oscillator crosses below d or oscillator crosses below w;
input trade_time_Start = 0906;
input trade_time_end = 1410;
input Use_RTH = yes;
def active2 = if SecondsFromTime(trade_time_Start) >= 0 && SecondsTillTime(trade_time_end) >= 0 then 1 else 0;
def buy_at_open = oscillator > 0;
def sell_at_open =oscillator < 0;

AddOrder(OrderType.BUY_TO_OPEN, if SecondsFromTime(trade_time_Start) == 0 then buy_at_open else Double.NaN, open(priceType = PriceType.ASK)[-1], tradeSize, name = "Buy To Open : $" +  open(priceType = PriceType.ASK)[-1] , tickColor = Color.GREEN, arrowColor = Color.ORANGE);
AddOrder(OrderType.SELL_TO_OPEN, if SecondsFromTime(trade_time_Start) == 0 then sell_at_open else Double.NaN, open(priceType = PriceType.BID)[0], tradeSize, name = "Sell To Open : $" +  open(priceType = PriceType.BID)[-1], tickColor = Color.RED, arrowColor = Color.ORANGE);

def EOD =  SecondsFromTime(trade_time_end) == 0;

AddOrder(type = OrderType.SELL_TO_CLOSE, condition = if Use_RTH && active2 then EOD else Double.NaN, price = close(priceType = PriceType.BID), tradeSize, name = "Sell To Close : $" + close(priceType = PriceType.BID), tickColor = Color.RED, arrowColor = Color.ORANGE);
AddOrder(type = OrderType.BUY_TO_CLOSE, condition = if Use_RTH && active2 then EOD else Double.NaN, price = close(priceType = PriceType.ASK), tradeSize, name = "Buy To Close : $" +  close(priceType = PriceType.ASK), tickColor = Color.GREEN, arrowColor = Color.ORANGE);
AddOrder(OrderType.BUY_AUTO, if Use_RTH
        then active2 && buy_condition
        else buy_condition,
        tradeSize = 1,
        price = open(priceType = PriceType.ASK)[offset],
        name = "Buy : $" + open(priceType = PriceType.ASK)[offset],
        tickColor = Color.GREEN,
        arrowColor = Color.ORANGE);
AddOrder(type = OrderType.SELL_AUTO, condition = if Use_RTH
                     then active2 && sell_condition
                     else sell_condition,
                     tradeSize = 1,
                     price = open(priceType = PriceType.BID)[offset],
                     name = "Sell : $" + open(priceType = PriceType.BID)[offset],
                     tickColor = Color.RED,
                     arrowColor = Color.ORANGE);

### end of code
 
Last edited:
I have a suspicion that this is repainting due to the order executions depending on the oscillator and oscillator is MTF to the aggregation period.
 
Here is a cleaned up version. Caution, it repaints.

Python:
# StudyName: RTH // High // Low
# Description: Plots developing intraday high and low
# Author: DMonkey
# Requested By: ActiveTrader
# Ver 2   12/20/2017: updated bubbles
# Ver 2.1 11/20/2020: Added an input for TradeSize, @Rick_Kennedy, member, usethinkscript.com
# Ver 3   11/30/2020: cleanup, Barbaros

input UseRTH = yes;
input MarketOpen = 0930;
input DurationInHours = 6.5;
input TradeTimeStart = 0906;
input TradeTimeEnd = 1410;
input Fraction = .3;
input RangePicker = yes;
input PaintBars = yes;
input ShowTimeConditions = yes;
input agg = aggregationPeriod.FOUR_MIN;
input mult1 = 0.125; # title = "Mutiplier; Only Supports 0.125 = 1/8");
input AutoTrade = yes;
input TradeSize = 1;

def MarketDuration = DurationInHours * 60 * 60;
def GoTime = secondsFromTime(MarketOpen);

def OpenHigh = if GoTime == 0 then high else if high > OpenHigh[1] then high else OpenHigh[1];
plot OpenHighLevel = if GoTime >= 0 && GoTime < MarketDuration then openhigh else Double.NaN;
OpenHighLevel.setpaintingStrategy(PaintingStrategy.DASHES);
OpenHighLevel.setdefaultColor(Color.YELLOW);
OpenHighLevel.setlineWeight(3);

def OpenLow = if GoTime == 0 then low else if low < OpenLow[1] then low else OpenLow[1];
plot OpenLowLevel = if GoTime >= 0 && GoTime < MarketDuration then openlow else Double.NaN;
OpenLowLevel.setpaintingStrategy(PaintingStrategy.DASHES);
OpenLowLevel.setdefaultColor(Color.MAGENTA);
OpenLowLevel.setlineWeight(3);

def RTH_High_bubble = if GoTime >= 0 then highestall(OpenHighLevel) else Double.NaN;
def RTH_Low_bubble = if GoTime >= 0 then lowestall(OpenLowLevel) else Double.NaN;              
AddChartBubble("time condition" = ShowTimeConditions && if isNaN(close[-1]) && !isNaN(close) then (RTH_High_bubble) else Double.NaN,
               "price location" = (RTH_High_bubble),
                text = "RTH High : " + asDollars(round((RTH_High_bubble)/ticksize(), 0) * ticksize()),
                color = Color.BLUE);
AddChartBubble("time condition" = ShowTimeConditions && if isNaN(close[-1]) && !isNaN(close) then RTH_Low_bubble else Double.NaN ,
               "price location" = RTH_Low_bubble,
                text = "RTH Low : " + asdollars(round((RTH_Low_bubble)/ ticksize(),0)* ticksize()),
                color = Color.GRAY,
                up = No);

def range = Fraction * (OpenHighLevel - OpenLowLevel);

plot ShortExpansion = OpenHighLevel - range;
ShortExpansion.setdefaultColor(Color.LIGHT_GRAY);

plot LongExpansion = OpenLowLevel + range;
LongExpansion.setdefaultColor(Color.RED);

def ExpansionDirection = if ShortExpansion > ShortExpansion[1] then 1 else if ShortExpansion < ShortExpansion[1] then 2 else ExpansionDirection[1];
AddLabel(!IsNaN(ExpansionDirection), "Market is expanding " + if ExpansionDirection == 1 then "up" else if ExpansionDirection == 2 then "down" else "flat", if ExpansionDirection == 1 then color.green else if ExpansionDirection == 2 then color.red else color.orange);

def range2 = OpenHighLevel - OpenLowLevel;
def multiplier = range2 * mult1;
def midline = OpenLowLevel + multiplier * 4;

def oscillator = ExpAverage((close(period = agg) - midline) / (if RangePicker then range2 / 2 else range / 2), 1);

def a = oscillator > 0 and oscillator < mult1 * 2;
def b = oscillator > 0 and oscillator < mult1 * 4;
def c = oscillator > 0 and oscillator < mult1 * 6;
def d = oscillator > 0 and oscillator < mult1 * 8;

def z = oscillator < 0 and oscillator > -mult1 * 2;
def y = oscillator < 0 and oscillator > -mult1 * 4;
def x = oscillator < 0 and oscillator > -mult1 * 6;
def w = oscillator < 0 and oscillator > -mult1 * 8;

def buyCondition =  oscillator crosses above 0 or oscillator crosses above w or oscillator crosses above d;
def sellCondition = oscillator crosses below 0 or oscillator crosses below d or oscillator crosses below w;

def active = if SecondsFromTime(TradeTimeStart) >= 0 && SecondsTillTime(TradeTimeEnd) >= 0 then 1 else 0;
def buyAtOpen = oscillator > 0;
def sellAtOpen = oscillator < 0;

def EOD =  SecondsFromTime(TradeTimeEnd) == 0;
AddVerticalLine(EOD, "End of Trading", Color.WHITE);

assignPriceColor(if PaintBars then if oscillator > 0 then color.green else color.red else color.current);

plot buyAtOpenSignal = if SecondsFromTime(TradeTimeStart) == 0 then buyAtOpen else no;
buyAtOpenSignal.setDefaultColor(Color.MAGENTA);
buyAtOpenSignal.setPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);

plot buySignal = if UseRTH then active && buyCondition else buyCondition;
buySignal.setDefaultColor(Color.CYAN);
buySignal.setPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);

plot sellAtOpenSignal = if SecondsFromTime(TradeTimeStart) == 0 then sellAtOpen else no;
sellAtOpenSignal.setDefaultColor(Color.MAGENTA);
sellAtOpenSignal.setPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);

plot sellSignal = if UseRTH then active && sellCondition else sellCondition;
sellSignal.setDefaultColor(Color.CYAN);
sellSignal.setPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);

Alert(if SecondsFromTime(TradeTimeStart) == 0 then buyAtOpen else no, "Buy at Open", Alert.BAR, Sound.DING);
Alert(if UseRTH then active && buyCondition else buyCondition, "Bullish", Alert.BAR, Sound.DING);
Alert(if SecondsFromTime(TradeTimeStart) == 0 then sellAtOpen else no, "Sell at Open", Alert.BAR, Sound.DING);
Alert(if UseRTH then active && sellCondition else sellCondition, "Bearish", Alert.BAR, Sound.DING);
Alert(if UseRTH && active then EOD else no, "Close All Positions", Alert.BAR, Sound.RING);

AddOrder(OrderType.BUY_TO_OPEN, if AutoTrade and SecondsFromTime(TradeTimeStart) == 0 then buyAtOpen else no, open(priceType = PriceType.ASK)[-1], TradeSize, name = "Buy To Open : $" +  open(priceType = PriceType.ASK)[-1] , tickColor = Color.GREEN, arrowColor = Color.ORANGE);
AddOrder(OrderType.SELL_TO_OPEN, if AutoTrade and SecondsFromTime(TradeTimeStart) == 0 then sellAtOpen else no, open(priceType = PriceType.BID)[0], TradeSize, name = "Sell To Open : $" +  open(priceType = PriceType.BID)[-1], tickColor = Color.RED, arrowColor = Color.ORANGE);

AddOrder(type = OrderType.SELL_TO_CLOSE, condition = if AutoTrade and UseRTH and active then EOD else no, price = close(priceType = PriceType.BID), TradeSize, name = "Sell To Close : $" + close(priceType = PriceType.BID), tickColor = Color.RED, arrowColor = Color.ORANGE);
AddOrder(type = OrderType.BUY_TO_CLOSE, condition = if AutoTrade and UseRTH and active then EOD else no, price = close(priceType = PriceType.ASK), TradeSize, name = "Buy To Close : $" +  close(priceType = PriceType.ASK), tickColor = Color.GREEN, arrowColor = Color.ORANGE);

AddOrder(type = OrderType.BUY_AUTO,
        condition = if AutoTrade then if UseRTH then active and buyCondition else buyCondition else no,
        TradeSize = 1,
        price = open(priceType = PriceType.ASK)[-1],
        name = "Buy : $" + open(priceType = PriceType.ASK)[-1],
        tickColor = Color.GREEN,
        arrowColor = Color.ORANGE);

AddOrder(type = OrderType.SELL_AUTO,
        condition = if AutoTrade then if UseRTH then active and sellCondition else sellCondition else no,
        TradeSize = 1,
        price = open(priceType = PriceType.BID)[-1],
        name = "Sell : $" + open(priceType = PriceType.BID)[-1],
        tickColor = Color.RED,
        arrowColor = Color.ORANGE);
 
Last edited:
Yep, it has a major repainting issue like I was mentioning. If someone figures out a solution, I'll be happy to code it.
 
@RickKennedy Price color depends on the oscillator which depends on an MTF close value. This should make the bar coloring repaint as well. Let me know if you find this useful in your trading. I have not watched it long enough.
 
First post, be gentle!

I'm trying to do something similar, but the opposite, of the strategy shared here.

In that strategy, for each bar, it tests if it is the highest high thus far in the day. If so, it plots it, if not it plots the highest. Vice versa for the low.

What I want is the opposite, for each bar it plots the maximal high between that bar and the end of RTH. Thus if it peaks in the morning, subsequent plots will be the highest between that bar and the close. Again, vice versa for the low.

Problem is that Highest() and Lowest() expect constants, so I can't pass a variable to it in this case what I'd like is:

Code:
def barsremain = -round((RegularTradingEnd(GetYyyyMmDd()) - GetTime()) / GetAggregationPeriod(), 0) ;
def forwardhigh = Highest(high(), -barsremain);
def forwardlow = Lowest(low(), -barsremain);
 

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

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
416 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