John Carter's Reversal

easleyjr96

New member
EDIT: I have fixed the code and it now correctly generates entry signals. I'm still working on displaying stops. Working code can be found in post #3 for anybody looking to try.

I want to create an indicator that is based off of one of the trading strategies from John Carter’s book “Mastering the Trade”. The basic premise of the strategy is that you buy when the current bar closes above the high of the bar that has the lowest low over the last 20 bars. The reverse can also be done where it generates a sell signal when the current bar closes below the low of the bar that has the highest high within the last 20 bars. After purchasing at the buy signal, your initial stop loss would be the low of the low bar. After 3 bars, your stop loss becomes a trailing stop loss that is based on the low of the previous 2 bars.

The main appeal of this system is having something that can help generate reversal signals. This is easily doable by just looking at the chart and doing it mentally, but I think it would be really nice to create an indicator that helps you visualize these key levels on the chart.

I’ve never done any other coding or taken classes but feel like I have a basic understanding of thinkscript, so took a shot at creating something and quickly realized I didn’t have the knowledge to pull this off. This is what I started coming up with:

Code:
input length = 20;

#Finds and indexes the position of the high bar over the last 20 bars
def prevhighbarindex = GetMaxValueOffset(high, length);

#Returns the value of the high of the high bar
def prevhighbar = GetValue(high, prevhighbarindex);

#Returns the value of the low of the high bar
def prevhighbarlow = GetValue(low, prevhighbarindex);

#Logic that determines when the current bar breaks below the high bar
def sellsignal = close() < prevhighbarlow;

#Logic that hides the line drawn at the high bar's low after the current bar breaks below it
def showprevhighbarlow = close() > prevhighbarlow;
plot plotprevhighbarlow = if showprevhighbarlow then prevhighbarlow else Double.NaN;

#Prints a down arrow when a sell signal is generated
plot pDown = sellsignal;
pDown.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
pDown.SetDefaultColor(Color.RED);

Problems I quickly realized I would run into is I wouldn’t have any way of resetting the prevhighbarlow after the sell signal was generated. Also, I wouldn’t have any way of switching between buy entries and sell entries. I’m guessing what needs to be done is something similar to this DarvasBox Code:

Code:
# ************************************
#
# Simpler Trading Darvas Box
# By Eric Purdy
# Revision Date: 09/20/17
# (c) 2017 Simpler Trading, LLC
#
# ************************************

input plotBackwardsExtensions = yes;

DefineGlobalColor("HighFirstBox", color.yellow);
DefineGlobalColor("LowFirstBox", color.plum);

def state = {default init, one, two, three, four, five};

def boxHigh;
def boxLow;
def breakoutLong;
def breakoutShort;
def highFirst;
def lowFirst;

switch (state[1]) {

case init:

    boxHigh = high;
    boxLow = low;
    state = state.one;
    breakoutLong = no;
    breakoutShort = no;
    highFirst = yes;
    lowFirst = no;

case one:

    breakoutLong = no;
    breakoutShort = no;
    if highFirst[1]
    then {
        highFirst = highFirst[1];
        lowFirst = lowFirst[1];
        if (high > boxHigh[1])
        then {
            boxHigh = high;
            boxLow = boxLow[1];
            state = state.one;
        } else {
            state = state.two;
            boxHigh = boxHigh[1];
            boxLow = boxLow[1];
        }
    } else {
        highFirst = highFirst[1];
        lowFirst = lowFirst[1];
        if (low < boxLow[1])
        then {
            boxHigh = boxHigh[1];
            boxLow = low;
            state = state.one;
        } else {
            state = state.two;
            boxHigh = boxHigh[1];
            boxLow = boxLow[1];
        }
    }
case two:

    breakoutLong = no;
    breakoutShort = no;
    if highFirst[1]
    then {
        highFirst = highFirst[1];
        lowFirst = lowFirst[1];
        if (high > boxHigh[1])
        then {
            boxHigh = high;
            boxLow = boxLow[1];
            state = state.one;
        } else {
            state = state.three;
            boxHigh = boxHigh[1];
            boxLow = low;
        }
    } else {
        highFirst = highFirst[1];
        lowFirst = lowFirst[1];
        if (low < boxLow[1])
        then {
            boxHigh = boxHigh[1];
            boxLow = low;
            state = state.one;
        } else {
            state = state.three;
            boxHigh = high;
            boxLow = boxLow[1];
        }
    }

case three:

    breakoutLong = no;
    breakoutShort = no;
    if highFirst[1]
    then {
        highFirst = highFirst[1];
        lowFirst = lowFirst[1];
        if (high > boxHigh[1])
        then {
            boxHigh = high;
            boxLow = boxLow[1];
            state = state.one;
        } else if (low < boxLow[1]) {
            state = state.three;
            boxLow = low;
            boxHigh = boxHigh[1];
        } else {
            state = state.four;
            boxHigh = boxHigh[1];
            boxLow = boxLow[1];
        }
    } else {
        highFirst = highFirst[1];
        lowFirst = lowFirst[1];
        if (low < boxLow[1])
        then {
            boxHigh = boxHigh[1];
            boxLow = low;
            state = state.one;
        } else if (high > boxHigh[1]) {
            state = state.three;
            boxLow = boxLow[1];
            boxHigh = high;
        } else {
            state = state.four;
            boxHigh = boxHigh[1];
            boxLow = boxLow[1];
        }
    }
case four:

    breakoutLong = no;
    breakoutShort = no;
    if highFirst[1]
    then {
        highFirst = highFirst[1];
        lowFirst = lowFirst[1];
        if (high > boxHigh[1])
        then {
            boxHigh = high;
            boxLow = boxLow[1];
            state = state.one;
        } else if (low < boxLow[1]) {
            state = state.three;
            boxLow = low;
            boxHigh = boxHigh[1];
         } else {
            state = state.five;
            boxHigh = boxHigh[1];
            boxLow = boxLow[1];
        }
    } else {
        highFirst = highFirst[1];
        lowFirst = lowFirst[1];
        if (low < boxLow[1])
        then {
            boxHigh = boxHigh[1];
            boxLow = low;
            state = state.one;
        } else if (high > boxHigh[1]) {
            state = state.three;
            boxLow = boxLow[1];
            boxHigh = high;    
        } else {
            state = state.five;
            boxHigh = boxHigh[1];
            boxLow = boxLow[1];
        }
    }
case five:

if (high > boxHigh[1] or low < boxLow[1])
    then {
        state = state.one;
        breakoutLong = if (high > boxHigh[1]) then  yes else no;
        breakoutShort = if (low < boxLow[1]) then yes else no;
        boxHigh = high;
        boxLow = low;
        highFirst = if breakoutLong then yes else no;
        lowFirst = if breakoutShort then yes else no;
   } else {
        state = state.five;
        boxHigh = boxHigh[1];
        boxLow = boxLow[1];
        highFirst = highFirst[1];
        lowFirst = lowFirst[1];
        breakoutLong = no;
        breakoutShort = no;
   }
}

def boxNumber = if state==state.five and state[1] != state.five then boxNumber[1]+1 else boxNumber[1];

plot boxHighPlot = if state == state.five and !isNan(close) then boxHigh else if  ((breakoutLong or breakoutShort) and !isNan(close)) then boxHigh[1] else double.nan;
boxHighPlot.setLineWeight(3);
boxHighPlot.setPaintingStrategy(paintingStrategy.HORIZONTAL);
boxHighPlot.assignValueColor(if (highFirst and !(breakoutLong or breakoutShort)) or ((breakoutLong or breakOutShort) and highFirst[1]) then GlobalColor("HighFirstBox") else  GlobalColor("LowFirstBox"));

plot boxLowPlot = if state == state.five and !isNan(close) then boxLow else if ((breakoutLong or breakoutShort) and !isNan(close)) then boxLow[1] else double.nan;
boxLowPlot.setLineWeight(3);
boxLowPlot.setPaintingStrategy(paintingStrategy.HORIZONTAL);
boxLowPlot.assignValueColor(if (highFirst and !(breakoutLong or breakoutShort)) or ((breakoutLong or breakOutShort) and highFirst[1])  then GlobalColor("HighFirstBox") else GlobalColor("LowFirstBox"));

plot longBoxBreak = if breakoutLong then 1 else double.nan;
longBoxBreak.setPaintingStrategy(paintingStrategy.BOOLEAN_ARROW_UP);
longBoxBreak.setLineWeight(2);
longBoxBreak.setDefaultColor(color.green);

plot shortBoxBreak = if breakoutShort then 1 else double.nan;
shortBoxBreak.setPaintingStrategy(paintingStrategy.BOOLEAN_ARROW_DOWN);
shortBoxBreak.setLineWeight(2);
shortBoxBreak.setDefaultColor(color.red);

boxHighPlot.hideBubble();
boxLowPlot.hideBubble();
longBoxBreak.hideBubble();
shortBoxBreak.hideBubble();

def barNumber = BarNumber();
def barCount = HighestAll(If(IsNaN(close), 0, barNumber));
def boxNum;
def boxUpperIndex;

plot boxHighExtension;
plot boxLowExtension;

if (IsNaN(close)) {
    boxNum = boxNum[1] + 1;
    boxUpperIndex = 0;
    boxHighExtension = Double.NaN;
    boxLowExtension = Double.NaN;
} else {
    boxNum = TotalSum(breakoutLong or breakoutShort);
    boxUpperIndex = fold indx = 0 to barCount - barNumber + 2 with valInd = Double.NaN
        while IsNaN(valInd)
        do if (GetValue(boxNum, -indx) != boxNum)
            then indx
            else Double.NaN;
    boxHighExtension = if plotBackwardsExtensions and !(breakoutLong or breakoutShort) then GetValue(boxHighPlot, -boxUpperIndex + 1) else double.nan;
    boxLowExtension =  if plotBackwardsExtensions and !(breakoutLong or breakoutShort) then GetValue(boxLowPlot, -boxUpperIndex + 1) else double.nan;
}

boxHighExtension.assignValueColor(if highFirst then GlobalColor("HighFirstBox") else GlobalColor("LowFirstBox") );
boxHighExtension.setpaintingStrategy(paintingStrategy.HORIZONTAL);
boxHighExtension.hideBubble();
boxHighExtension.setLineWeight(2);
boxLowExtension.assignValueColor(if highFirst then GlobalColor("HighFirstBox") else GlobalColor("LowFirstBox") );
boxLowExtension.setpaintingStrategy(paintingStrategy.HORIZONTAL);
boxLowExtension.hideBubble();
boxLowExtension.setLineWeight(2);

It seems like this is generating states that the code can be in using the switch state function. I have no clue how to use this function and it’s going way over my head. Basically what I’m looking to do is create something that looks similar to this darvas box indicator but uses the logic of the trading strategy posted at the top.
 
Last edited:

easleyjr96

New member
So I finally had time to revisit the code and this is what I came up with so far. Ditched the idea of drawing the lines and the stops and just focused on generating the entry signals to begin with. This is what my code looks like so far:

Code:
input length = 20;

#Finds and indexes the position of the high and low bars over the last 20 bars
def prevhighbarindex = BarNumber() - GetMaxValueOffset(high, length);
def prevhighbardistance = GetMaxValueOffset(high, length);
def prevlowbarindex = BarNumber() - GetMinValueOffset(low, length);
def prevlowbardistance = GetMinValueOffset(low, length);

#Returns the value of the 20 period high and low
def prevhighbar = GetValue(high, prevhighbardistance);
def prevlowbar = GetValue(low, prevlowbardistance);

#Returns the value of the low of the high bar and high of the low bar
def prevhighbarlow = GetValue(low, prevhighbardistance);
def prevlowbarhigh = GetValue(high, prevlowbardistance);

#Logic that determines when the current bar breaks below the high bar
def sellopen = if close() < prevhighbarlow then 1 else double.nan;
def sellopenindex = if isNaN(sellopen) then sellopenindex[1] else barnumber();
def showsellopen = if sellopen and sellopenindex[1] < prevhighbarindex then  1 else double.nan;

def buyopen = if close() > prevlowbarhigh then 1 else double.nan;
def buyopenindex = if isNaN(buyopen) then sellopenindex[1] else barnumber();
def showbuyopen = if buyopen and buyopenindex[1] < prevlowbarindex then 1 else double.nan;

#Logic that hides the line drawn at the high bar's low after the current bar breaks below it
#def showprevhighbarlow = close() > prevhighbarlow;
#plot plotprevhighbarlow = if showprevhighbarlow then prevhighbarlow else Double.NaN;

#Prints a down arrow when a sell signal is generated
plot pDown = showsellopen;
pDown.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
pDown.SetDefaultColor(Color.RED);

#Prints an up arrow when a buy signal is generated
plot pUP = showbuyopen;
pUP.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
pUP.SetDefaultColor(Color.GREEN);

AddLabel(yes, prevhighbardistance);
AddLabel(yes, prevlowbardistance);
AddLabel(yes, sellopenindex);
AddLabel(yes, buyopenindex);

From what I can tell this is correctly generating the entry signals now. If anybody wants to load it up and let me know what they think and how they would improve it feel free!
 

Similar threads

Top