Multi Time Frame Multi Indicator Strategy v2 For ThinkOrSwim

Mightymorphinchris

Active member
Overview
This is v2 of V1.

A multi indicator, multi time frame strategy that repaints (beware). If used properly with other technical analysis (which I hope you'll suggest and contribute to this) then it can potentially produce good results. I wrote this with scalping in mind and have personally struggled with swing trading. That doesn't mean this won't work for you in swing trading but.... if it does please share your settings or additional indicators that improve upon swing trades.

Trading
I have spent a significant amount of time on this strategy. I typically trade the 1m time frame (which this strategy is looking at multiple time frames). The biggest problem with this strategy is repainting... and as a scalper that's usually the problem with most strategies.

I trade the 1m time frame but, this strategy is coded to look at multiple time frames no matter what time frame you're on.

Cry for help
If you can help improve upon what I have here that would be greatly appreciated.

Settings
The strategy has an automatic setting mode and a manual. The automatic is what I found produced the best results for SPY when back testing on various time frames Please, if you find better settings, contribute to the community and share what you've found.

Final thoughts
I feel like I'm sharing my life's work here so if you can bring your own contributions and improvements to it I'd love that.

Share link
http://tos.mx/Df9v5Kr

Code
Ruby:
###############################################################
##########            Initial Config                   #########
################################################################
input securityType = { default "stocks", "forex"};
input tradetype = { "long", "short", default "both" };
input mode = { default "superScalp", "normal"};
input configMode = { default "automatic", "manual"};
input timeMode = { default "shorter", "normal"};

def timeFrame = GetAggregationPeriod();
def lowestAggregation;
def middleAggregation;
def highestAggregation;
def extraHighAggregation;
def xxlAggregation;
def xxxlAggregation;
if timeFrame == AggregationPeriod.MIN and timeMode == timeMode.shorter {
    lowestAggregation = AggregationPeriod.MIN;
    middleAggregation = AggregationPeriod.TWO_MIN;
    highestAggregation = AggregationPeriod.FOUR_MIN;
    extraHighAggregation = AggregationPeriod.FIVE_MIN;
    xxlAggregation = AggregationPeriod.TEN_MIN;
    xxxlAggregation = AggregationPeriod.FIFTEEN_MIN;
} else if timeFrame == AggregationPeriod.MIN {
    lowestAggregation = AggregationPeriod.MIN;
    middleAggregation = AggregationPeriod.TWO_MIN;
    highestAggregation = AggregationPeriod.FOUR_MIN;
    extraHighAggregation = AggregationPeriod.FIVE_MIN;
    xxlAggregation = AggregationPeriod.FIFTEEN_MIN;
    xxxlAggregation = AggregationPeriod.TWENTY_MIN;
} else if timeFrame == AggregationPeriod.TWO_MIN and timeMode == timeMode.shorter {
    lowestAggregation = AggregationPeriod.TWO_MIN;
    middleAggregation = AggregationPeriod.FOUR_MIN;
    highestAggregation = AggregationPeriod.FIVE_MIN;
    extraHighAggregation = AggregationPeriod.TEN_MIN;
    xxlAggregation = AggregationPeriod.FIFTEEN_MIN;
    xxxlAggregation = AggregationPeriod.THIRTY_MIN;
} else if timeFrame == AggregationPeriod.TWO_MIN {
    lowestAggregation = AggregationPeriod.TWO_MIN;
    middleAggregation = AggregationPeriod.FIVE_MIN;
    highestAggregation = AggregationPeriod.TEN_MIN;
    extraHighAggregation = AggregationPeriod.FIFTEEN_MIN;
    xxlAggregation = AggregationPeriod.THIRTY_MIN;
    xxxlAggregation = AggregationPeriod.HOUR;
} else if timeFrame == AggregationPeriod.THREE_MIN and timeMode == timeMode.shorter {
    lowestAggregation = AggregationPeriod.THREE_MIN;
    middleAggregation = AggregationPeriod.FOUR_MIN;
    highestAggregation = AggregationPeriod.FIVE_MIN;
    extraHighAggregation = AggregationPeriod.TEN_MIN;
    xxlAggregation = AggregationPeriod.FIFTEEN_MIN;
    xxxlAggregation = AggregationPeriod.THIRTY_MIN;
} else if timeFrame == AggregationPeriod.THREE_MIN {
    lowestAggregation = AggregationPeriod.THREE_MIN;
    middleAggregation = AggregationPeriod.FIVE_MIN;
    highestAggregation = AggregationPeriod.TEN_MIN;
    extraHighAggregation = AggregationPeriod.FIFTEEN_MIN;
    xxlAggregation = AggregationPeriod.THIRTY_MIN;
    xxxlAggregation = AggregationPeriod.HOUR;
} else if timeFrame == AggregationPeriod.FOUR_MIN and timeMode == timeMode.shorter {
    lowestAggregation = AggregationPeriod.FOUR_MIN;
    middleAggregation = AggregationPeriod.FIVE_MIN;
    highestAggregation = AggregationPeriod.TEN_MIN;
    extraHighAggregation = AggregationPeriod.FIFTEEN_MIN;
    xxlAggregation = AggregationPeriod.TWENTY_MIN;
    xxxlAggregation = AggregationPeriod.THIRTY_MIN;
} else if timeFrame == AggregationPeriod.FOUR_MIN {
    lowestAggregation = AggregationPeriod.FOUR_MIN;
    middleAggregation = AggregationPeriod.FIVE_MIN;
    highestAggregation = AggregationPeriod.TEN_MIN;
    extraHighAggregation = AggregationPeriod.FIFTEEN_MIN;
    xxlAggregation = AggregationPeriod.THIRTY_MIN;
    xxxlAggregation = AggregationPeriod.HOUR;
} else if timeFrame == AggregationPeriod.FIVE_MIN {
    lowestAggregation = AggregationPeriod.FIVE_MIN;
    middleAggregation = AggregationPeriod.TEN_MIN;
    highestAggregation = AggregationPeriod.FIFTEEN_MIN;
    extraHighAggregation = AggregationPeriod.THIRTY_MIN;
    xxlAggregation = AggregationPeriod.HOUR;
    xxxlAggregation = AggregationPeriod.TWO_HOURS;
} else if timeFrame == AggregationPeriod.TEN_MIN {
    lowestAggregation = AggregationPeriod.TEN_MIN;
    middleAggregation = AggregationPeriod.FIFTEEN_MIN;
    highestAggregation = AggregationPeriod.THIRTY_MIN;
    extraHighAggregation = AggregationPeriod.HOUR;
    xxlAggregation = AggregationPeriod.TWO_HOURS;
    xxxlAggregation = AggregationPeriod.FOUR_HOURS;
} else if timeFrame == AggregationPeriod.FIFTEEN_MIN {
    lowestAggregation = AggregationPeriod.FIFTEEN_MIN;
    middleAggregation = AggregationPeriod.THIRTY_MIN;
    highestAggregation = AggregationPeriod.HOUR;
    extraHighAggregation = AggregationPeriod.TWO_HOURS;
    xxlAggregation = AggregationPeriod.FOUR_HOURS;
    xxxlAggregation = AggregationPeriod.DAY;
} else if timeFrame == AggregationPeriod.THIRTY_MIN {
    lowestAggregation = AggregationPeriod.THIRTY_MIN;
    middleAggregation = AggregationPeriod.HOUR;
    highestAggregation = AggregationPeriod.TWO_HOURS;
    extraHighAggregation = AggregationPeriod.FOUR_HOURS;
    xxlAggregation = AggregationPeriod.DAY;
    xxxlAggregation = AggregationPeriod.TWO_DAYS;
} else if timeFrame == AggregationPeriod.HOUR {
    lowestAggregation = AggregationPeriod.HOUR;
    middleAggregation = AggregationPeriod.TWO_HOURS;
    highestAggregation = AggregationPeriod.FOUR_HOURS;
    extraHighAggregation = AggregationPeriod.DAY;
    xxlAggregation = AggregationPeriod.TWO_DAYS;
    xxxlAggregation = AggregationPeriod.FOUR_DAYS;
} else if timeFrame == AggregationPeriod.TWO_HOURS {
    lowestAggregation = AggregationPeriod.TWO_HOURS;
    middleAggregation = AggregationPeriod.FOUR_HOURS;
    highestAggregation = AggregationPeriod.DAY;
    extraHighAggregation = AggregationPeriod.TWO_DAYS;
    xxlAggregation = AggregationPeriod.FOUR_DAYS;
    xxxlAggregation = AggregationPeriod.WEEK;
} else if timeFrame == AggregationPeriod.FOUR_HOURS {
    lowestAggregation = AggregationPeriod.FOUR_HOURS;
    middleAggregation = AggregationPeriod.DAY;
    highestAggregation = AggregationPeriod.TWO_DAYS;
    extraHighAggregation = AggregationPeriod.FOUR_DAYS;
    xxlAggregation = AggregationPeriod.WEEK;
    xxxlAggregation = AggregationPeriod.MONTH;
} else if timeFrame == AggregationPeriod.DAY {
    lowestAggregation = AggregationPeriod.DAY;
    middleAggregation = AggregationPeriod.TWO_DAYS;
    highestAggregation = AggregationPeriod.FOUR_DAYS;
    extraHighAggregation = AggregationPeriod.WEEK;
    xxlAggregation = AggregationPeriod.MONTH;
    xxxlAggregation = AggregationPeriod.QUARTER;
} else {
    lowestAggregation = AggregationPeriod.TWO_DAYS;
    middleAggregation = AggregationPeriod.FOUR_DAYS;
    highestAggregation = AggregationPeriod.WEEK;
    extraHighAggregation = AggregationPeriod.MONTH;
    xxlAggregation = AggregationPeriod.QUARTER;
    xxxlAggregation = AggregationPeriod.YEAR;
}

def testTimeFrames = if timeFrame == lowestAggregation and lowestAggregation < middleAggregation and middleAggregation < highestAggregation < extraHighAggregation then 1 else 0;
def CloseAllCondition = if timeFrame <= AggregationPeriod.FIFTEEN_MIN then 0 else if SecondsTillTime(1558) == 0 then 1 else 0;
def EOD = if timeFrame >= AggregationPeriod.FIFTEEN_MIN then 0 else if SecondsTillTime(1558) == 0 and SecondsFromTime(1558) == 0 then 1 else 0;
def Active;
if securityType == securityType.stocks {
    Active = if (SecondsFromTime(0930) > 0 and SecondsTillTime(1558) > 0) then 1 else 0;
} else {
    Active = 1;
    #Active = if ((SecondsFromTime(0500) > 0 and SecondsTillTime(0800) > 0)) or ((SecondsFromTime(1700) > 0 and SecondsTillTime(2100) > 0)) then 1 else 0;
}

################################################################
##########            Global Variables                 #########
################################################################

# TimePeriodChecks
input timePeriodsLong = { "One", "Two", "Three", default "Four", "Five", "Six" };
def timePeriodsNumLong = if timePeriodsLong == timePeriodsLong.Six then 6 else if timePeriodsLong == timePeriodsLong.Five then 5 else if timePeriodsLong == timePeriodsLong.Four then 4 else if timePeriodsLong == timePeriodsLong.Three then 3 else if timePeriodsLong == timePeriodsLong.Two then 2 else 1;
input timePeriodsShort = { "One", "Two", "Three", default "Four", "Five", "Six" };
def timePeriodsNumShort = if timePeriodsShort == timePeriodsShort.Six then 6 else if timePeriodsShort == timePeriodsShort.Five then 5 else if timePeriodsShort == timePeriodsShort.Four then 4 else if timePeriodsShort == timePeriodsShort.Three then 3 else if timePeriodsShort == timePeriodsShort.Two then 2 else 1;
input timePeriodsEMA = { "One", "Two", "Three", default "Four", "Five", "Six" };
def timePeriodsNumEMA = if timePeriodsEMA == timePeriodsEMA.Six then 6 else if timePeriodsEMA == timePeriodsEMA.Five then 5 else if timePeriodsEMA == timePeriodsEMA.Four then 4 else if timePeriodsEMA == timePeriodsEMA.Three then 3 else if timePeriodsEMA == timePeriodsEMA.Two then 2 else 1;
input timePeriodsMACD = { "One", "Two", "Three", "Four", "Five", default "Six" };
def timePeriodsNumMACD = if timePeriodsMACD == timePeriodsMACD.Six then 6 else if timePeriodsMACD == timePeriodsMACD.Five then 5 else if timePeriodsMACD == timePeriodsMACD.Four then 4 else if timePeriodsMACD == timePeriodsMACD.Three then 3 else if timePeriodsMACD == timePeriodsMACD.Two then 2 else 1;

# Config Mode
def tpLong;
def tpShort;
def tpEMA;
def tpMACD;
If configMode == configMode.automatic {
    if GetAggregationPeriod() == AggregationPeriod.MIN {
        if mode == mode.superScalp and timeMode == timeMode.shorter{
            tpLong = 6;
            tpShort = 6;
            tpEMA = 6;
            tpMACD = 6;
        } else if mode == mode.superScalp {
            tpLong = 6;
            tpShort = 4;
            tpEMA = 6;
            tpMACD = 6;
        } else {
            tpLong = 6;
            tpShort = 4;
            tpEMA = 5;
            tpMACD = 6;
        }
    } else if GetAggregationPeriod() == AggregationPeriod.TWO_MIN {
        if mode == mode.superScalp {
            tpLong = 6;
            tpShort = 4;
            tpEMA = 6;
            tpMACD = 6;
        } else {
            tpLong = 6;
            tpShort = 4;
            tpEMA = 6;
            tpMACD = 6;
        }
    } else if GetAggregationPeriod() == AggregationPeriod.THREE_MIN {
        if mode == mode.superScalp {
            tpLong = 6;
            tpShort = 4;
            tpEMA = 6;
            tpMACD = 6;
        } else {
            tpLong = 6;
            tpShort = 4;
            tpEMA = 6;
            tpMACD = 6;
        }
    } else if GetAggregationPeriod() == AggregationPeriod.FOUR_MIN {
        if mode == mode.superScalp {
            tpLong = 6;
            tpShort = 4;
            tpEMA = 6;
            tpMACD = 6;
        } else {
            tpLong = 6;
            tpShort = 5;
            tpEMA = 6;
            tpMACD = 6;
        }
    } else if GetAggregationPeriod() == AggregationPeriod.FIVE_MIN {
        if mode == mode.superScalp {
            tpLong = 5;
            tpShort = 6;
            tpEMA = 6;
            tpMACD = 6;
        } else {
            tpLong = 4;
            tpShort = 6;
            tpEMA = 5;
            tpMACD = 6;
        }
    } else if GetAggregationPeriod() == AggregationPeriod.TEN_MIN {
        if mode == mode.superScalp {
            tpLong = 5;
            tpShort = 6;
            tpEMA = 4;
            tpMACD = 6;
        } else {
            tpLong = 5;
            tpShort = 6;
            tpEMA = 6;
            tpMACD = 6;
        }
    } else {
        if mode == mode.superScalp {
            tpLong = 4;
            tpShort = 2;
            tpEMA = 6;
            tpMACD = 6;
        } else {
            tpLong = 3;
            tpShort = 4;
            tpEMA = 6;
            tpMACD = 5;
        }
    }
} else {
    tpLong = timePeriodsNumLong;
    tpShort = timePeriodsNumShort;
    tpEMA = timePeriodsNumEMA;
    tpMACD = timePeriodsNumMACD;
}

# Indicator Settings
# RSI
input rsiLength = 16;
input rsiOverBought = 68;
input rsiOverSold = 30;
input rsiAverageType = AverageType.WILDERS;

# Stochastic
input smiKPeriod = 4;
input smiDPeriod = 2;
input smiEnterBelow = 0;
input smiExitBelow = 0;

# CPMO
input cpmoLength1 = 14;
input cpmoLength2 = 9;
input cpmoSignalLength = 10;

# MACD
input MACDFastLength = 7;
input MACDSlowLength = 19;
input MACDLength = 5;
input MACDAverageType = AverageType.EXPONENTIAL;

# EMA
input ema = 200;

################################################################
##########                 EMA                       ###########
################################################################
def priceUp = if close > ExpAverage(close, ema) then 1 else 0;
def timeLong = if priceUp then tpLong else tpEMA;
def timeLongMACD = if priceUp then tpMACD else tpEMA;
def priceDown = if close < ExpAverage(close, ema) then 1 else 0;
def timeShort = if priceDown then tpShort else tpEMA;
def timeShortMACD = if priceDown then tpMACD else tpEMA;

################################################################
##########                 RSI                         #########
################################################################
# 4 Hour
def rsiClose = close(period = xxxlAggregation);

def NetChgAvg = MovingAverage(rsiAverageType, rsiClose - rsiClose[1], rsiLength);
def TotChgAvg = MovingAverage(rsiAverageType, AbsValue(rsiClose - rsiClose[1]), rsiLength);
def ChgRatio = if TotChgAvg != 0 then NetChgAvg / TotChgAvg else 0;
def RSI = 50 * (ChgRatio + 1);

################################################################
##########                 SMI                         #########
################################################################
# Stochastic Extra Extra High
def min_low_xxxl = Lowest(low(period = xxxlAggregation), smiKPeriod);
def max_high_xxxl = Highest(high(period = xxxlAggregation), smiKPeriod);
def rel_diff_xxxl = close(period = xxxlAggregation) - (max_high_xxxl + min_low_xxxl) / 2;
def diff_xxxl = max_high_xxxl - min_low_xxxl;

def avgrel_xxxl = ExpAverage(ExpAverage(rel_diff_xxxl, smiDPeriod), smiDPeriod);
def avgdiff_xxxl = ExpAverage(ExpAverage(diff_xxxl, smiDPeriod), smiDPeriod);

def SMI_xxxl = if avgdiff_xxxl != 0 then avgrel_xxxl / (avgdiff_xxxl / 2) * 100 else 0;
def AvgSMI_xxxl = ExpAverage(SMI_xxxl, smiDPeriod);

# Stochastic Extra Extra High
def min_low_xxl = Lowest(low(period = xxlAggregation), smiKPeriod);
def max_high_xxl = Highest(high(period = xxlAggregation), smiKPeriod);
def rel_diff_xxl = close(period = xxlAggregation) - (max_high_xxl + min_low_xxl) / 2;
def diff_xxl = max_high_xxl - min_low_xxl;

def avgrel_xxl = ExpAverage(ExpAverage(rel_diff_xxl, smiDPeriod), smiDPeriod);
def avgdiff_xxl = ExpAverage(ExpAverage(diff_xxl, smiDPeriod), smiDPeriod);

def SMI_xxl = if avgdiff_xxl != 0 then avgrel_xxl / (avgdiff_xxl / 2) * 100 else 0;
def AvgSMI_xxl = ExpAverage(SMI_xxl, smiDPeriod);

# Stochastic Extra High
def min_low_xh = Lowest(low(period = extraHighAggregation), smiKPeriod);
def max_high_xh = Highest(high(period = extraHighAggregation), smiKPeriod);
def rel_diff_xh = close(period = extraHighAggregation) - (max_high_xh + min_low_xh) / 2;
def diff_xh = max_high_xh - min_low_xh;

def avgrel_xh = ExpAverage(ExpAverage(rel_diff_xh, smiDPeriod), smiDPeriod);
def avgdiff_xh = ExpAverage(ExpAverage(diff_xh, smiDPeriod), smiDPeriod);

def SMI_xh = if avgdiff_xh != 0 then avgrel_xxl / (avgdiff_xhl / 2) * 100 else 0;
def AvgSMI_xh = ExpAverage(SMI_xh, smiDPeriod);

# Stochastic Highest
def min_low_h = Lowest(low(period = highestAggregation), smiKPeriod);
def max_high_h = Highest(high(period = highestAggregation), smiKPeriod);
def rel_diff_h = close(period = highestAggregation) - (max_high_h + min_low_h) / 2;
def diff_h = max_high_h - min_low_h;

def avgrel_h = ExpAverage(ExpAverage(rel_diff_h, smiDPeriod), smiDPeriod);
def avgdiff_h = ExpAverage(ExpAverage(diff_h, smiDPeriod), smiDPeriod);

def SMI_h = if avgdiff_h != 0 then avgrel_h / (avgdiff_h / 2) * 100 else 0;
def AvgSMI_h = ExpAverage(SMI_h, smiDPeriod);

# Stochastic Middle
def min_low_m = Lowest(low(period = middleAggregation), smiKPeriod);
def max_high_m = Highest(high(period = middleAggregation), smiKPeriod);
def rel_diff_m = close(period = middleAggregation) - (max_high_m + min_low_m) / 2;
def diff_m = max_high_m - min_low_m;

def avgrel_m = ExpAverage(ExpAverage(rel_diff_m, smiDPeriod), smiDPeriod);
def avgdiff_m = ExpAverage(ExpAverage(diff_m, smiDPeriod), smiDPeriod);

def SMI_m = if avgdiff_m != 0 then avgrel_m / (avgdiff_m / 2) * 100 else 0;
def AvgSMI_m = ExpAverage(SMI_m, smiDPeriod);

# Stochastic Lowest
def min_low_l = Lowest(low(period = lowestAggregation), smiKPeriod);
def max_high_l = Highest(high(period = lowestAggregation), smiKPeriod);
def rel_diff_l = close(period = lowestAggregation) - (max_high_l + min_low_l) / 2;
def diff_l = max_high_l - min_low_l;

def avgrel_l = ExpAverage(ExpAverage(rel_diff_l, smiDPeriod), smiDPeriod);
def avgdiff_l = ExpAverage(ExpAverage(diff_l, smiDPeriod), smiDPeriod);

def SMI_l = if avgdiff_l != 0 then avgrel_l / (avgdiff_l / 2) * 100 else 0;
def AvgSMI_l = ExpAverage(SMI_l, smiDPeriod);

def smiCrossBelowExit = if SMI_xh crosses below 40 then 1 else 0;
def smiCrossAboveExit = if SMI_xh crosses above 40 then 1 else 0;

################################################################
##########                 MACD                      ###########
################################################################
def price_l = close(period = lowestAggregation);
def price_m = close(period = middleAggregation);
def price_h = close(period = highestAggregation);
def price_xh = close(period = extraHighAggregation);
def price_xxl = close(period = xxlAggregation);
def price_xxxl = close(period = xxxlAggregation);

def macDValue_l = MovingAverage(MACDAverageType, price_l, MACDFastLength) - MovingAverage(MACDAverageType, price_xh, MACDSlowLength);
def macDAvg_l = MovingAverage(MACDAverageType, macDValue_l, MACDLength);
def macDValue_m = MovingAverage(MACDAverageType, price_m, MACDFastLength) - MovingAverage(MACDAverageType, price_xh, MACDSlowLength);
def macDAvg_m = MovingAverage(MACDAverageType, macDValue_m, MACDLength);
def macDValue_h = MovingAverage(MACDAverageType, price_h, MACDFastLength) - MovingAverage(MACDAverageType, price_xh, MACDSlowLength);
def macDAvg_h = MovingAverage(MACDAverageType, macDValue_h, MACDLength);
def macDValue_xh = MovingAverage(MACDAverageType, price_xh, MACDFastLength) - MovingAverage(MACDAverageType, price_xh, MACDSlowLength);
def macDAvg_xh = MovingAverage(MACDAverageType, macDValue_xh, MACDLength);
def macDValue_xxl = MovingAverage(MACDAverageType, price_xxl, MACDFastLength) - MovingAverage(MACDAverageType, price_xh, MACDSlowLength);
def macDAvg_xxl = MovingAverage(MACDAverageType, macDValue_xxl, MACDLength);
def macDValue_xxxl = MovingAverage(MACDAverageType, price_xxxl, MACDFastLength) - MovingAverage(MACDAverageType, price_xh, MACDSlowLength);
def macDAvg_xxxl = MovingAverage(MACDAverageType, macDValue_xxxl, MACDLength);

################################################################
##########                 CPMO                      ###########
################################################################
def PrimaryPMO_l = reference PMO(price = close(period = lowestAggregation), length1 = cpmoLength1, length2 = cpmoLength2);
def PrimarySignalLine_l = ExpAverage(PrimaryPMO_l, cpmoSignalLength);

################################################################
##########                 CALC                      ###########
################################################################
def smiEnter = if smiEnterBelow <= 0 then -40 else if smiEnterBelow >= 40 then 0 else smiEnterBelow - 40;
def smiExit = if smiExitBelow <= 0 then -40 else if smiEnterBelow >= 40 then 0 else smiEnterBelow - 40;
def smiEnterShort = smiEnter * (-1);
def smiExitShort = smiEnter * (-1);
def smiSafeGuard = if mode == mode.superScalp then 100 else 50;
def smiSafeGuardShort = if mode == mode.superScalp then -100 else -50;

def macDLong;
if timeLongMACD == 6 {
    macDLong = if macDValue_xxxl > macDAvg_xxxl and macDValue_xxl > macDAvg_xxl then 1 else 0;
} else if timeLongMACD == 5 {
    macDLong = if macDValue_xxl > macDAvg_xxl and macDValue_xh > macDAvg_xh then 1 else 0;
} else if timeLongMACD == 4 {
    macDLong = if macDValue_xh > macDAvg_xh and macDValue_h > macDAvg_h then 1 else 0;
} else if timeLongMACD == 3 {
    macDLong = if macDValue_h > macDAvg_h and macDValue_m > macDAvg_m then 1 else 0;
} else if timeLongMACD == 2 {
    macDLong = if macDValue_m > macDAvg_m and macDValue_l > macDAvg_l then 1 else 0;
} else {
    macDLong = if macDValue_l > macDAvg_l then 1 else 0;
}

def macDValueExit;
def macDAvgExit;
if priceUp {
    macDValueExit = if macDValue_xxxl < macDAvg_xxxl then macDValue_xh else macDValue_xxl;
    macDAvgExit = if macDValue_xxxl < macDAvg_xxxl then macDAvg_xh else macDAvg_xxl;
} else {
    macDValueExit = if macDValue_xxl < macDAvg_xxl then macDValue_h else macDValue_xh;
    macDAvgExit = if macDValue_xxl < macDAvg_xxl then macDAvg_h else macDAvg_xh;
}

def macDShort;
if timeLongMACD == 6 {
    macDShort = if macDValue_xxxl < macDAvg_xxxl and macDValue_xxl < macDAvg_xxl then 1 else 0;
} else if timeLongMACD == 5 {
    macDShort = if macDValue_xxl < macDAvg_xxl and macDValue_xh < macDAvg_xh then 1 else 0;
} else if timeLongMACD == 4 {
    macDShort = if macDValue_xh < macDAvg_xh and macDValue_h < macDAvg_h then 1 else 0;
} else if timeLongMACD == 3 {
    macDShort = if macDValue_h < macDAvg_h and macDValue_m < macDAvg_m then 1 else 0;
} else if timeLongMACD == 2 {
    macDShort = if macDValue_m < macDAvg_m and macDValue_l < macDAvg_l then 1 else 0;
} else {
    macDShort = if macDValue_l < macDAvg_l then 1 else 0;
}

def macDValueExitShort;
def macDAvgExitShort;
if priceDown {
    macDValueExitShort = if macDValue_xxxl < macDAvg_xxxl then macDValue_xh else macDValue_xxl;
    macDAvgExitShort = if macDValue_xxxl < macDAvg_xxxl then macDAvg_xh else macDAvg_xxl;
} else {
    macDValueExitShort = macDValue_xh;
    macDAvgExitShort = macDAvg_xh;
}

#################################################################
############          SCAN Variables                    #########
#################################################################
plot Uptrend;
plot DownTrend;

if tradetype == tradetype.long or tradetype == tradetype.both {
    if timeLong == 6 {
        if (SMI_xxxl > AvgSMI_xxxl or SMI_xxxl <= smiEnter) and (SMI_xxl > AvgSMI_xxl or SMI_xxl <= smiEnter) and (SMI_xh > AvgSMI_xh or SMI_xh <= smiEnter) and SMI_h > AvgSMI_h and SMI_h <= smiSafeGuard and SMI_m > AvgSMI_m and SMI_l > AvgSMI_l and macDLong {
            Uptrend = 1;
        } else {
            Uptrend = 0;
        }
    } else if timeLong == 5 {
        if (SMI_xxl > AvgSMI_xxl or SMI_xxl <= smiEnter) and (SMI_xh > AvgSMI_xh or SMI_xh <= smiEnter) and SMI_h > AvgSMI_h and SMI_h <= smiSafeGuard and SMI_m > AvgSMI_m and SMI_l > AvgSMI_l and macDLong {
            Uptrend = 1;
        } else {
            Uptrend = 0;
        }
    } else if timeLong == 4 {
        if (SMI_xh > AvgSMI_xh or SMI_xh <= smiEnter) and SMI_h > AvgSMI_h and SMI_h <= smiSafeGuard and SMI_m > AvgSMI_m and SMI_l > AvgSMI_l and macDLong  {
            Uptrend = 1;
        } else {
            Uptrend = 0;
        }
    } else if timeLong == 3 {
        if (SMI_h > AvgSMI_h or SMI_h <= smiEnter) and SMI_m > AvgSMI_m and SMI_l > AvgSMI_l and macDLong {
            Uptrend = 1;
        } else {
            Uptrend = 0;
        }
    } else if timeLong == 2 {
        if SMI_h <= 40 and SMI_m > AvgSMI_m and SMI_l > AvgSMI_l and macDLong {
            Uptrend = 1;
        } else {
            Uptrend = 0;
        }
    } else {
        if PrimaryPMO_l > PrimarySignalLine_l {
            Uptrend = 1;
        } else {
            Uptrend = 0;
        }
    }
} else {
    Uptrend = 0;
}

if tradetype == tradetype.short or tradetype == tradetype.both {
    if timeShort == 6 {
        if (SMI_xxxl < AvgSMI_xxxl or SMI_xxxl >= smiEnterShort) and (SMI_xxl < AvgSMI_xxl or SMI_xxl >= smiEnterShort) and (SMI_xh < AvgSMI_xh or SMI_xh >= smiEnterShort) and SMI_h < AvgSMI_h and SMI_h >= smiSafeGuardShort and SMI_m < AvgSMI_m and SMI_l < AvgSMI_l and macDShort {
            DownTrend = 1;
        } else {
            DownTrend = 0;
        }
    } else if timeShort == 5 {
        if (SMI_xxl < AvgSMI_xxl or SMI_xxl >= smiEnterShort) and (SMI_xh < AvgSMI_xh or SMI_xh >= smiEnterShort) and SMI_h < AvgSMI_h and SMI_h >= smiSafeGuardShort and SMI_m < AvgSMI_m and SMI_l < AvgSMI_l and macDShort {
            DownTrend = 1;
        } else {
            DownTrend = 0;
        }
    } else if timeShort == 4 {
        if (SMI_xh < AvgSMI_xh or SMI_xh >= smiEnterShort) and SMI_h < AvgSMI_h and SMI_m < AvgSMI_m and SMI_h >= smiSafeGuardShort and SMI_l < AvgSMI_l and macDShort {
            DownTrend = 1;
        } else {
            DownTrend = 0;
        }
    } else if timeShort == 3 {
        if (SMI_h < AvgSMI_h or SMI_h >= smiEnterShort) and SMI_h >= smiSafeGuardShort  and SMI_m < AvgSMI_m and SMI_l < AvgSMI_l and macDShort {
            DownTrend = 1;
        } else {
            DownTrend = 0;
        }
    } else if timeShort == 2 {
        if SMI_h >= -40 and SMI_m < AvgSMI_m and SMI_l < AvgSMI_l and macDShort {
            DownTrend = 1;
        } else {
            DownTrend = 0;
        }
    } else {
        if PrimaryPMO_l < PrimarySignalLine_l {
            DownTrend = 1;
        } else {
            DownTrend = 0;
        }
    }
} else {
    DownTrend = 0;
}

plot ExitUpTrend;
plot ExitDownTrend;

#Exit UpTrend
if RSI >= rsiOverBought {
    ExitUpTrend = 1;
} else if smiCrossBelowExit {
    ExitUpTrend = 1;
} else if (SMI_xxxl > AvgSMI_xxxl and SMI_xxl > AvgSMI_xxl) or (SMI_xxl < smiExit and SMI_xxl > AvgSMI_xxl) and priceUp{
    ExitUpTrend = if SMI_xh < AvgSMI_xh and SMI_h < AvgSMI_h and SMI_m < AvgSMI_m and SMI_l < AvgSMI_l or macDValueExit < macdAvgExit then 1 else 0;
} else if (SMI_xxl > AvgSMI_xxl and SMI_xh > AvgSMI_xh) or (SMI_xh < smiExit and SMI_xh > AvgSMI_xh) {
    ExitUpTrend = if SMI_h < AvgSMI_h and SMI_m < AvgSMI_m and SMI_l < AvgSMI_l or macDValueExit < macdAvgExit then 1 else 0;
} else if (SMI_xh > AvgSMI_xh and SMI_h > AvgSMI_h) or (SMI_h < smiExit and SMI_h > AvgSMI_h) {
    ExitUpTrend = if SMI_m < AvgSMI_m and SMI_l < AvgSMI_l or macDValueExit < macdAvgExit then 1 else 0;
} else if (SMI_h > AvgSMI_h and SMI_m > AvgSMI_m) or (SMI_m < smiExit and SMI_m > AvgSMI_m) {
    ExitUpTrend = if PrimaryPMO_l < PrimarySignalLine_l or macDValueExit < macdAvgExit then 1 else 0;
} else {
    ExitUpTrend = if SMI_l < AvgSMI_l then 1 else 0;
}

# Exit DownTrend
if RSI <= rsiOverSold {
    ExitDownTrend = 1;
} else if smiCrossAboveExit {
    ExitDownTrend = 1;
} else if (SMI_xxxl < AvgSMI_xxxl and SMI_xxl < AvgSMI_xxl) or (SMI_xxl > smiExitShort and SMI_xxl < AvgSMI_xxl) and priceDown {
    ExitDownTrend = if SMI_xh > AvgSMI_xh and SMI_h > AvgSMI_h and SMI_m > AvgSMI_m and SMI_l > AvgSMI_l or macDValueExitShort > macdAvgExitShort then 1 else 0;
} else if (SMI_xxl < AvgSMI_xxl and SMI_xh < AvgSMI_xh) or (SMI_xh > smiExitShort and SMI_xh < AvgSMI_xh) {
    ExitDownTrend = if SMI_h > AvgSMI_h and SMI_m > AvgSMI_m and SMI_l > AvgSMI_l or macDValueExitShort > macdAvgExitShort then 1 else 0;
} else if (SMI_xh < AvgSMI_xh and SMI_h < AvgSMI_h) or (SMI_h > smiExitShort and SMI_h < AvgSMI_h) {
    ExitDownTrend = if SMI_m > AvgSMI_m and SMI_l > AvgSMI_l or macDValueExitShort > macdAvgExitShort then 1 else 0;
} else if (SMI_h < AvgSMI_h and SMI_m < AvgSMI_m) or (SMI_m > smiExitShort and SMI_m < AvgSMI_m) {
    ExitDownTrend = if PrimaryPMO_l > PrimarySignalLine_l or macDValueExitShort > macdAvgExitShort then 1 else 0;
} else {
    ExitDownTrend = if SMI_l > AvgSMI_l then 1 else 0;
}

def LongBuy = if Uptrend == 1 and Uptrend[1] == 0 then 1 else 0;
def LongExit = if ExitUpTrend == 1 and ExitUpTrend[1] == 0 then 1 else 0;

def ShortSell = if DownTrend == 1 and DownTrend[1] == 0 then 1 else 0;
def ShortExit = if ExitDownTrend == 1 and ExitDownTrend[1] == 0 then 1 else 0;

Uptrend.Hide();
DownTrend.Hide();
ExitUpTrend.Hide();
ExitDownTrend.Hide();

################################################################
##########                 BUY                       ###########
################################################################

AddOrder(OrderType.BUY_AUTO, LongBuy == 1 and (tradetype == tradetype.long or tradetype == tradetype.both) and Active and testTimeFrames, price = close, tickcolor = Color.CYAN, arrowcolor = Color.CYAN, name = "BUY");
AddOrder(OrderType.SELL_TO_CLOSE, LongExit == 1 and (tradetype == tradetype.long or tradetype == tradetype.both) and Active and testTimeFrames, price = open[-1], tickcolor = Color.MAGENTA, arrowcolor = Color.MAGENTA, name = "Sell To Close");
AddOrder(OrderType.SELL_TO_CLOSE, EOD or CloseAllCondition and testTimeFrames, price = close, tickcolor = Color.MAGENTA, arrowcolor = Color.MAGENTA, name = "SELL EOD");

################################################################
##########                 SELL                      ###########
################################################################

AddOrder(OrderType.SELL_AUTO, ShortSell == 1 and (tradetype == tradetype.short or tradetype == tradetype.both) and Active and testTimeFrames, price = close, tickcolor = Color.MAGENTA, arrowcolor = Color.MAGENTA, name = "SELL");
AddOrder(OrderType.BUY_TO_CLOSE, ShortExit == 1 and (tradetype == tradetype.short or tradetype == tradetype.both) and Active and testTimeFrames, price = open[-1], tickcolor = Color.CYAN, arrowcolor = Color.CYAN, name = "Buy To Close");
AddOrder(OrderType.BUY_TO_CLOSE, EOD or CloseAllCondition and testTimeFrames, price = close, tickcolor = Color.CYAN, arrowcolor = Color.CYAN, name = "BUY EOD");

Screenshots
Last 30 days on 1m Time Frame (again, it repaints though)
gWJTKlE.png


Scans

--Shared by @Mogden16--
Long Scan - https://tos.mx/yCjar0k
Short Scan - https://tos.mx/RzpkMyK
 
Last edited:

Mightymorphinchris

Active member
Does the "auto" setting automate the trades? I didn't think TOS allowed that
No it auto configures the inputs on a per time frame basis. For example if you have it in auto mode it will configure settings for the 1m time frame. If you're in the 2m time frame those settings will automatically be configured differently for the 2m time frame so on and so forth.

In this screenshot the first rectangle effects the 2nd rectangle settings when in automatic mode. When in manual mode the 2nd rectangle can be adjusted to whatever settings work best for that ticker (I mainly trade SPY). If it's set to automatic mode then it doesn't matter what you select in the 2nd rectangle as the automatic configuration will override.

NOTE: There are different automatic settings for the 2 different time modes (basically looking at longer time frames when set to normal time mode or more condensed time frames when in shorter time mode. superScalp mode will produce more signals with less confirmation requirements which I've found that I prefer so I usually leave that on for SPY.

I did this because I like to look at multiple time frames and got tired of changing the configuration for that time frame and documenting what settings worked best for it.

LNBsi2j.png
 

Trader_Rich

Member
Thanks for the response
No it auto configures the inputs on a per time frame basis. For example if you have it in auto mode it will configure settings for the 1m time frame. If you're in the 2m time frame those settings will automatically be configured differently for the 2m time frame so on and so forth.

In this screenshot the first rectangle effects the 2nd rectangle settings when in automatic mode. When in manual mode the 2nd rectangle can be adjusted to whatever settings work best for that ticker (I mainly trade SPY). If it's set to automatic mode then it doesn't matter what you select in the 2nd rectangle as the automatic configuration will override.

NOTE: There are different automatic settings for the 2 different time modes (basically looking at longer time frames when set to normal time mode or more condensed time frames when in shorter time mode. superScalp mode will produce more signals with less confirmation requirements which I've found that I prefer so I usually leave that on for SPY.

I did this because I like to look at multiple time frames and got tired of changing the configuration for that time frame and documenting what settings worked best for it.

LNBsi2j.png
Thank you for the response. I'm going to look at this more in depth over the weekend as it looks promising, however I am curious to see if you incorporated the "unknown" indicator I shared in the other post, if you only took trades after wt1_1 and wt2_1 crossed and were above/below the zero line, would that have reduced your losers. I started incorporating that today and felt that my "heart attack" trades went away and got much cleaner runs.

Have a great weekend!
 

Mightymorphinchris

Active member
Thanks for the response

Thank you for the response. I'm going to look at this more in depth over the weekend as it looks promising, however I am curious to see if you incorporated the "unknown" indicator I shared in the other post, if you only took trades after wt1_1 and wt2_1 crossed and were above/below the zero line, would that have reduced your losers. I started incorporating that today and felt that my "heart attack" trades went away and got much cleaner runs.

Have a great weekend!
Let me know what you find, I’m planning on doing some backtesting tonight with the strategy you mentioned as well.
 

Drmoh1800

Member
as usually you are doing great work i thank you for sharing
its very difficult to get rid of repainting in another way it should be repainting is flag to sell
the only thing it i noticed this indicator should be apart of daily indicator and considering market condition
i saw some people use certain kind of daily indicator buying is more than selling they buy
if market is selling they sell something like that
like finz
if you want to stop repainting either to increase time interval 1to 5 to 15 30 i noticed most the time repainting happening at this times
personally i like to watch price crossing moving average
thank you again for sharing
5643 Advancing

Declining 2332





68.0%

28.1%​
167 New High

New Low 202





45.3%

54.7%​
3088 Above
SMA50
Below 5206





37.2%

62.8%​
4173 Above
SMA200
Below 412​
 

Drmoh1800

Member
If i want to play with time and change it to 1 5 10 or 15
Which part should i change

if timeFrame == AggregationPeriod.MIN and timeMode == timeMode.shorter {
lowestAggregation = AggregationPeriod.MIN;
middleAggregation = AggregationPeriod.FIVE_MIN;
highestAggregation = AggregationPeriod.TEN_MIN;
extraHighAggregation = AggregationPeriod.FIFTEEN_MIN;
Instead of repainting to say sell
Is this possible

So if i got the buy signal at 1 minute and and check again at 5 if it deosnt meet criteria to flag sell then check again at 10 and 15
What i do i susually watch brake out at 1m and wait and see 5 minute then wait and look at 15 minutes as long its not closing moving avrage 10 i stay in trad can we add that to this study

I will try to add another study or scan like this and look at the results
https://usethinkscript.com/threads/alert-for-when-price-crosses-above-or-below-50-ma.3538/
 
Last edited:

Mightymorphinchris

Active member
If i want to play with time and change it to 1 5 10 or 15
Which part should i change

if timeFrame == AggregationPeriod.MIN and timeMode == timeMode.shorter {
lowestAggregation = AggregationPeriod.MIN;
middleAggregation = AggregationPeriod.FIVE_MIN;
highestAggregation = AggregationPeriod.TEN_MIN;
extraHighAggregation = AggregationPeriod.FIFTEEN_MIN;
Instead of repainting to say sell
Is this possible

So if i got the buy signal at 1 minute and and check again at 5 if it deosnt meet criteria to flag sell then check again at 10 and 15
What i do i susually watch brake out at 1m and wait and see 5 minute then wait and look at 15 minutes as long its not closing moving avrage 10 i stay in trad can we add that to this study

I will try to add another study or scan like this and look at the results
https://usethinkscript.com/threads/alert-for-when-price-crosses-above-or-below-50-ma.3538/
If you're using the timemode shorter and want to adjust the times used then yes what you have posted above (code) is correct. If you're using the normal mode then go to the next set of time frames right below that and adjust those.
 

Trader_Rich

Member
I had a rough day trading /CL today, thus went back to the drawing board and incorporated the Ripster EMA Clouds with this study which would have kept me out of some bad trades. We all know that trading with the trend will eliminate a sizeable number of bad trades, and the EMA clouds will help identify trend as well as S/R
 

windowshopr

New member
Came across this randomly and looks wicked, great job! Just my 2 cents, but you should be able to eliminate repainting if you apply all of the technical indicators to the OPEN price instead of the CLOSE. I don't know how that affects your strategy, and it might alter the results, but that way, as soon as the next bar opens, if it meets all your criteria, the buy/sell signal won't change. It's because the close price is always changing for the current bar until it finally closes, which I'm sure you know already, but maybe give that a try?? Hope it helps. Would be cool to see that implemented and see how it performs.
 

windowshopr

New member
Was playing around with this a bit tonight, and tried converting everything to use the OPEN price, but that didn't work out so well with the results it produced, but that's likely because all I did was change everywhere it said close to open, so that likely screwed with the logic a bit, BUT, then I went through the code and changed everywhere it said close to close[-1], so basically just shifted all the closes to use the PREVIOUS close price. Then made other shift modifications as necessary, like the one open[-1] to open[-2], and some shifting in the NAN checking section, and it produced great results, on par if not better than the current version on the 1 min, 15 day SPY chart. I'm hoping that might help eliminate the repainting at least on the buy side to enter into a position, but I think the main issue is the repainting of sells, cuz I'm assuming the sell would still just keep repainting itself as the price chart kept creeping higher? If I'm understanding the issue correctly 0:) Otherwise, what I might think of is if a sell signal gets generated, just stop there and wait until the next bar to do anything else. If another buy signal gets generated right away, that's fine as it's already being used as a scalp strategy, but would make the reports a bit more static?
 

rama999

New member
Hi does this work after hrs? I did come across this accidentally and studying this.

I haven't changed any settings trying to check with as is.
 

Mightymorphinchris

Active member
Was playing around with this a bit tonight, and tried converting everything to use the OPEN price, but that didn't work out so well with the results it produced, but that's likely because all I did was change everywhere it said close to open, so that likely screwed with the logic a bit, BUT, then I went through the code and changed everywhere it said close to close[-1], so basically just shifted all the closes to use the PREVIOUS close price. Then made other shift modifications as necessary, like the one open[-1] to open[-2], and some shifting in the NAN checking section, and it produced great results, on par if not better than the current version on the 1 min, 15 day SPY chart. I'm hoping that might help eliminate the repainting at least on the buy side to enter into a position, but I think the main issue is the repainting of sells, cuz I'm assuming the sell would still just keep repainting itself as the price chart kept creeping higher? If I'm understanding the issue correctly 0:) Otherwise, what I might think of is if a sell signal gets generated, just stop there and wait until the next bar to do anything else. If another buy signal gets generated right away, that's fine as it's already being used as a scalp strategy, but would make the reports a bit more static?
Thanks a lot for checking it out and providing your feedback. Would you mind sharing with me the modified strategy and I can check it out?
 

Swamp_Gritz

New member
Thanks a lot for checking it out and providing your feedback. Would you mind sharing with me the modified strategy and I can check it out?

I'm really looking into this and the previous comment about repainting by switching to the close instead of the open of the bar. I have never seen such a perfect indicator on paper. This is absolutely mind-boggling, I would love to kill that repainting aspect somehow and will experiment. Is the perfection of this "on paper" based on repainting alone? So would it completely kill the strategy? I'm going to attempt to do what the previous comments mentioned about switching from OPEN to CLOSE. Will that edit alone make it more accurate when back testing?

*I must add: Maybe I just haven't seen an indicator that repaints yet but this is the best indicator I've ever backtested in the last 18-19 months learning about the markets.
 

Mightymorphinchris

Active member
I'm really looking into this and the previous comment about repainting by switching to the close instead of the open of the bar. I have never seen such a perfect indicator on paper. This is absolutely mind-boggling, I would love to kill that repainting aspect somehow and will experiment. Is the perfection of this "on paper" based on repainting alone? So would it completely kill the strategy? I'm going to attempt to do what the previous comments mentioned about switching from OPEN to CLOSE. Will that edit alone make it more accurate when back testing?

*I must add: Maybe I just haven't seen an indicator that repaints yet but this is the best indicator I've ever backtested in the last 18-19 months learning about the markets.
Thanks for the feedback. Unfortunately the repainting can be problematic in a few ways:
1. It can cause you to enter trades then the signal disappears and the trend reverses
2. It can cause you to enter trades late as the signal will appear a few bars back
3. It can cause you to exit early as the sell or buy to close signal will appear and then disappear
4. It can cause you to exit late as the sell of buy to close signal will appear a few bars back.
 

Swamp_Gritz

New member
Yes, that is quite the problem. Unfortunately there's no way to change it? I don't want to make too many mistakes in the code but I'm trying to follow his comment about switching from open to close / close to open calculations. Would that theoretically help? Windowshopr have the right idea? I would be doing this blindly though without too much experience customizing think script. So here we go I will make copy and start trying to figure out ANY way whatsoever to remove the repainting.


Thanks for the feedback. Unfortunately the repainting can be problematic in a few ways:
1. It can cause you to enter trades then the signal disappears and the trend reverses
2. It can cause you to enter trades late as the signal will appear a few bars back
3. It can cause you to exit early as the sell or buy to close signal will appear and then disappear
4. It can cause you to exit late as the sell of buy to close signal will appear a few bars back.
 

Mightymorphinchris

Active member
Yes, that is quite the problem. Unfortunately there's no way to change it? I don't want to make too many mistakes in the code but I'm trying to follow his comment about switching from open to close / close to open calculations. Would that theoretically help? Windowshopr have the right idea? I would be doing this blindly though without too much experience customizing think script. So here we go I will make copy and start trying to figure out ANY way whatsoever to remove the repainting.
I'd love to see what modifications @windowshopr has made as well and do some back testing with them.
 

windowshopr

New member
Of course, here is the updated code. Not sure if it's "correct" or not, but I'm trying to watch for order ENTRIES to see if they generate at an actionable price when they show up, or because of my shifting if they only show up at the correct price on the previous bar, just have to wait and see. Though this also shouldn't be the worst thing either as you may only miss out on a few cents of slippage from signal bar to the current bar.

The main issue now that I see is the repainting of the sell/close signals. I noticed that it generated a close signal, then a few minutes later it disappeared, the price kept moving higher, then it re-generated another close signal further up for the same order, so that's a problem. My solution doesn't fix that.

The best I can suggest here is, if a close signal gets generated, only look for open signals from then on. My guess is your trade count will go up, but that way once a sell signal gets generated, it won't dynamically disappear and re-appear further into the money. Instead, it may just signal another buy right away which is fine, but that way it won't be re-painting.

Code:
###############################################################
##########            Initial Config                   #########
################################################################
input securityType = { default "stocks", "forex"};
input tradetype = { "long", "short", default "both" };
input mode = { default "superScalp", "normal"};
input configMode = { default "automatic", "manual"};
input timeMode = { default "shorter", "normal"};


def timeFrame = GetAggregationPeriod();
def lowestAggregation;
def middleAggregation;
def highestAggregation;
def extraHighAggregation;
def xxlAggregation;
def xxxlAggregation;
if timeFrame == AggregationPeriod.MIN and timeMode == timeMode.shorter {
    lowestAggregation = AggregationPeriod.MIN;
    middleAggregation = AggregationPeriod.TWO_MIN;
    highestAggregation = AggregationPeriod.FOUR_MIN;
    extraHighAggregation = AggregationPeriod.FIVE_MIN;
    xxlAggregation = AggregationPeriod.TEN_MIN;
    xxxlAggregation = AggregationPeriod.FIFTEEN_MIN;
} else if timeFrame == AggregationPeriod.MIN {
    lowestAggregation = AggregationPeriod.MIN;
    middleAggregation = AggregationPeriod.TWO_MIN;
    highestAggregation = AggregationPeriod.FOUR_MIN;
    extraHighAggregation = AggregationPeriod.FIVE_MIN;
    xxlAggregation = AggregationPeriod.FIFTEEN_MIN;
    xxxlAggregation = AggregationPeriod.TWENTY_MIN;
} else if timeFrame == AggregationPeriod.TWO_MIN and timeMode == timeMode.shorter {
    lowestAggregation = AggregationPeriod.TWO_MIN;
    middleAggregation = AggregationPeriod.FOUR_MIN;
    highestAggregation = AggregationPeriod.FIVE_MIN;
    extraHighAggregation = AggregationPeriod.TEN_MIN;
    xxlAggregation = AggregationPeriod.FIFTEEN_MIN;
    xxxlAggregation = AggregationPeriod.THIRTY_MIN;
} else if timeFrame == AggregationPeriod.TWO_MIN {
    lowestAggregation = AggregationPeriod.TWO_MIN;
    middleAggregation = AggregationPeriod.FIVE_MIN;
    highestAggregation = AggregationPeriod.TEN_MIN;
    extraHighAggregation = AggregationPeriod.FIFTEEN_MIN;
    xxlAggregation = AggregationPeriod.THIRTY_MIN;
    xxxlAggregation = AggregationPeriod.HOUR;
} else if timeFrame == AggregationPeriod.THREE_MIN and timeMode == timeMode.shorter {
    lowestAggregation = AggregationPeriod.THREE_MIN;
    middleAggregation = AggregationPeriod.FOUR_MIN;
    highestAggregation = AggregationPeriod.FIVE_MIN;
    extraHighAggregation = AggregationPeriod.TEN_MIN;
    xxlAggregation = AggregationPeriod.FIFTEEN_MIN;
    xxxlAggregation = AggregationPeriod.THIRTY_MIN;
} else if timeFrame == AggregationPeriod.THREE_MIN {
    lowestAggregation = AggregationPeriod.THREE_MIN;
    middleAggregation = AggregationPeriod.FIVE_MIN;
    highestAggregation = AggregationPeriod.TEN_MIN;
    extraHighAggregation = AggregationPeriod.FIFTEEN_MIN;
    xxlAggregation = AggregationPeriod.THIRTY_MIN;
    xxxlAggregation = AggregationPeriod.HOUR;
} else if timeFrame == AggregationPeriod.FOUR_MIN and timeMode == timeMode.shorter {
    lowestAggregation = AggregationPeriod.FOUR_MIN;
    middleAggregation = AggregationPeriod.FIVE_MIN;
    highestAggregation = AggregationPeriod.TEN_MIN;
    extraHighAggregation = AggregationPeriod.FIFTEEN_MIN;
    xxlAggregation = AggregationPeriod.TWENTY_MIN;
    xxxlAggregation = AggregationPeriod.THIRTY_MIN;
} else if timeFrame == AggregationPeriod.FOUR_MIN {
    lowestAggregation = AggregationPeriod.FOUR_MIN;
    middleAggregation = AggregationPeriod.FIVE_MIN;
    highestAggregation = AggregationPeriod.TEN_MIN;
    extraHighAggregation = AggregationPeriod.FIFTEEN_MIN;
    xxlAggregation = AggregationPeriod.THIRTY_MIN;
    xxxlAggregation = AggregationPeriod.HOUR;
} else if timeFrame == AggregationPeriod.FIVE_MIN {
    lowestAggregation = AggregationPeriod.FIVE_MIN;
    middleAggregation = AggregationPeriod.TEN_MIN;
    highestAggregation = AggregationPeriod.FIFTEEN_MIN;
    extraHighAggregation = AggregationPeriod.THIRTY_MIN;
    xxlAggregation = AggregationPeriod.HOUR;
    xxxlAggregation = AggregationPeriod.TWO_HOURS;
} else if timeFrame == AggregationPeriod.TEN_MIN {
    lowestAggregation = AggregationPeriod.TEN_MIN;
    middleAggregation = AggregationPeriod.FIFTEEN_MIN;
    highestAggregation = AggregationPeriod.THIRTY_MIN;
    extraHighAggregation = AggregationPeriod.HOUR;
    xxlAggregation = AggregationPeriod.TWO_HOURS;
    xxxlAggregation = AggregationPeriod.FOUR_HOURS;
} else if timeFrame == AggregationPeriod.FIFTEEN_MIN {
    lowestAggregation = AggregationPeriod.FIFTEEN_MIN;
    middleAggregation = AggregationPeriod.THIRTY_MIN;
    highestAggregation = AggregationPeriod.HOUR;
    extraHighAggregation = AggregationPeriod.TWO_HOURS;
    xxlAggregation = AggregationPeriod.FOUR_HOURS;
    xxxlAggregation = AggregationPeriod.DAY;
} else if timeFrame == AggregationPeriod.THIRTY_MIN {
    lowestAggregation = AggregationPeriod.THIRTY_MIN;
    middleAggregation = AggregationPeriod.HOUR;
    highestAggregation = AggregationPeriod.TWO_HOURS;
    extraHighAggregation = AggregationPeriod.FOUR_HOURS;
    xxlAggregation = AggregationPeriod.DAY;
    xxxlAggregation = AggregationPeriod.TWO_DAYS;
} else if timeFrame == AggregationPeriod.HOUR {
    lowestAggregation = AggregationPeriod.HOUR;
    middleAggregation = AggregationPeriod.TWO_HOURS;
    highestAggregation = AggregationPeriod.FOUR_HOURS;
    extraHighAggregation = AggregationPeriod.DAY;
    xxlAggregation = AggregationPeriod.TWO_DAYS;
    xxxlAggregation = AggregationPeriod.FOUR_DAYS;
} else if timeFrame == AggregationPeriod.TWO_HOURS {
    lowestAggregation = AggregationPeriod.TWO_HOURS;
    middleAggregation = AggregationPeriod.FOUR_HOURS;
    highestAggregation = AggregationPeriod.DAY;
    extraHighAggregation = AggregationPeriod.TWO_DAYS;
    xxlAggregation = AggregationPeriod.FOUR_DAYS;
    xxxlAggregation = AggregationPeriod.WEEK;
} else if timeFrame == AggregationPeriod.FOUR_HOURS {
    lowestAggregation = AggregationPeriod.FOUR_HOURS;
    middleAggregation = AggregationPeriod.DAY;
    highestAggregation = AggregationPeriod.TWO_DAYS;
    extraHighAggregation = AggregationPeriod.FOUR_DAYS;
    xxlAggregation = AggregationPeriod.WEEK;
    xxxlAggregation = AggregationPeriod.MONTH;
} else if timeFrame == AggregationPeriod.DAY {
    lowestAggregation = AggregationPeriod.DAY;
    middleAggregation = AggregationPeriod.TWO_DAYS;
    highestAggregation = AggregationPeriod.FOUR_DAYS;
    extraHighAggregation = AggregationPeriod.WEEK;
    xxlAggregation = AggregationPeriod.MONTH;
    xxxlAggregation = AggregationPeriod.QUARTER;
} else {
    lowestAggregation = AggregationPeriod.TWO_DAYS;
    middleAggregation = AggregationPeriod.FOUR_DAYS;
    highestAggregation = AggregationPeriod.WEEK;
    extraHighAggregation = AggregationPeriod.MONTH;
    xxlAggregation = AggregationPeriod.QUARTER;
    xxxlAggregation = AggregationPeriod.YEAR;
}


def testTimeFrames = if timeFrame == lowestAggregation and lowestAggregation < middleAggregation and middleAggregation < highestAggregation < extraHighAggregation then 1 else 0;
def CloseAllCondition = if timeFrame <= AggregationPeriod.FIFTEEN_MIN then 0 else if SecondsTillTime(1558) == 0 then 1 else 0;
def EOD = if timeFrame >= AggregationPeriod.FIFTEEN_MIN then 0 else if SecondsTillTime(1558) == 0 and SecondsFromTime(1558) == 0 then 1 else 0;
def Active;
if securityType == securityType.stocks {
    Active = if (SecondsFromTime(0930) > 0 and SecondsTillTime(1558) > 0) then 1 else 0;
} else {
    Active = 1;   
    #Active = if ((SecondsFromTime(0500) > 0 and SecondsTillTime(0800) > 0)) or ((SecondsFromTime(1700) > 0 and SecondsTillTime(2100) > 0)) then 1 else 0;
}


################################################################
##########            Global Variables                 #########
################################################################


# TimePeriodChecks
input timePeriodsLong = { "One", "Two", "Three", default "Four", "Five", "Six" };
def timePeriodsNumLong = if timePeriodsLong == timePeriodsLong.Six then 6 else if timePeriodsLong == timePeriodsLong.Five then 5 else if timePeriodsLong == timePeriodsLong.Four then 4 else if timePeriodsLong == timePeriodsLong.Three then 3 else if timePeriodsLong == timePeriodsLong.Two then 2 else 1;
input timePeriodsShort = { "One", "Two", "Three", default "Four", "Five", "Six" };
def timePeriodsNumShort = if timePeriodsShort == timePeriodsShort.Six then 6 else if timePeriodsShort == timePeriodsShort.Five then 5 else if timePeriodsShort == timePeriodsShort.Four then 4 else if timePeriodsShort == timePeriodsShort.Three then 3 else if timePeriodsShort == timePeriodsShort.Two then 2 else 1;
input timePeriodsEMA = { "One", "Two", "Three", default "Four", "Five", "Six" };
def timePeriodsNumEMA = if timePeriodsEMA == timePeriodsEMA.Six then 6 else if timePeriodsEMA == timePeriodsEMA.Five then 5 else if timePeriodsEMA == timePeriodsEMA.Four then 4 else if timePeriodsEMA == timePeriodsEMA.Three then 3 else if timePeriodsEMA == timePeriodsEMA.Two then 2 else 1;
input timePeriodsMACD = { "One", "Two", "Three", "Four", "Five", default "Six" };
def timePeriodsNumMACD = if timePeriodsMACD == timePeriodsMACD.Six then 6 else if timePeriodsMACD == timePeriodsMACD.Five then 5 else if timePeriodsMACD == timePeriodsMACD.Four then 4 else if timePeriodsMACD == timePeriodsMACD.Three then 3 else if timePeriodsMACD == timePeriodsMACD.Two then 2 else 1;


# Config Mode
def tpLong;
def tpShort;
def tpEMA;
def tpMACD;
If configMode == configMode.automatic {
    if GetAggregationPeriod() == AggregationPeriod.MIN {
        if mode == mode.superScalp and timeMode == timeMode.shorter{
            tpLong = 6;
            tpShort = 6;
            tpEMA = 6;
            tpMACD = 6;
        } else if mode == mode.superScalp {
            tpLong = 6;
            tpShort = 4;
            tpEMA = 6;
            tpMACD = 6;
        } else {
            tpLong = 6;
            tpShort = 4;
            tpEMA = 5;
            tpMACD = 6;
        }
    } else if GetAggregationPeriod() == AggregationPeriod.TWO_MIN {
        if mode == mode.superScalp {
            tpLong = 6;
            tpShort = 4;
            tpEMA = 6;
            tpMACD = 6;
        } else {
            tpLong = 6;
            tpShort = 4;
            tpEMA = 6;
            tpMACD = 6;
        }
    } else if GetAggregationPeriod() == AggregationPeriod.THREE_MIN {
        if mode == mode.superScalp {
            tpLong = 6;
            tpShort = 4;
            tpEMA = 6;
            tpMACD = 6;
        } else {
            tpLong = 6;
            tpShort = 4;
            tpEMA = 6;
            tpMACD = 6;
        }
    } else if GetAggregationPeriod() == AggregationPeriod.FOUR_MIN {
        if mode == mode.superScalp {
            tpLong = 6;
            tpShort = 4;
            tpEMA = 6;
            tpMACD = 6;
        } else {
            tpLong = 6;
            tpShort = 5;
            tpEMA = 6;
            tpMACD = 6;
        }
    } else if GetAggregationPeriod() == AggregationPeriod.FIVE_MIN {
        if mode == mode.superScalp {
            tpLong = 5;
            tpShort = 6;
            tpEMA = 6;
            tpMACD = 6;
        } else {
            tpLong = 4;
            tpShort = 6;
            tpEMA = 5;
            tpMACD = 6;
        }
    } else if GetAggregationPeriod() == AggregationPeriod.TEN_MIN {
        if mode == mode.superScalp {
            tpLong = 5;
            tpShort = 6;
            tpEMA = 4;
            tpMACD = 6;
        } else {
            tpLong = 5;
            tpShort = 6;
            tpEMA = 6;
            tpMACD = 6;
        }
    } else {
        if mode == mode.superScalp {
            tpLong = 4;
            tpShort = 2;
            tpEMA = 6;
            tpMACD = 6;
        } else {
            tpLong = 3;
            tpShort = 4;
            tpEMA = 6;
            tpMACD = 5;
        }
    }
} else {
    tpLong = timePeriodsNumLong;
    tpShort = timePeriodsNumShort;
    tpEMA = timePeriodsNumEMA;
    tpMACD = timePeriodsNumMACD;
}


# Indicator Settings
# RSI
input rsiLength = 16;
input rsiOverBought = 68;
input rsiOverSold = 30;
input rsiAverageType = AverageType.WILDERS;


# Stochastic
input smiKPeriod = 4;
input smiDPeriod = 2;
input smiEnterBelow = 0;
input smiExitBelow = 0;


# CPMO
input cpmoLength1 = 14;
input cpmoLength2 = 9;
input cpmoSignalLength = 10;


# MACD
input MACDFastLength = 7;
input MACDSlowLength = 19;
input MACDLength = 5;
input MACDAverageType = AverageType.EXPONENTIAL;


# EMA
input ema = 200;


################################################################
##########                 EMA                       ###########
################################################################
def priceUp = if close[-1] > ExpAverage(close[-1], ema) then 1 else 0;
def timeLong = if priceUp then tpLong else tpEMA;
def timeLongMACD = if priceUp then tpMACD else tpEMA;
def priceDown = if close[-1] < ExpAverage(close[-1], ema) then 1 else 0;
def timeShort = if priceDown then tpShort else tpEMA;
def timeShortMACD = if priceDown then tpMACD else tpEMA;


################################################################
##########                 RSI                         #########
################################################################
# 4 Hour
def rsiClose = close(period = xxxlAggregation)[-1];


def NetChgAvg = MovingAverage(rsiAverageType, rsiClose - rsiClose[1], rsiLength);
def TotChgAvg = MovingAverage(rsiAverageType, AbsValue(rsiClose - rsiClose[1]), rsiLength);
def ChgRatio = if TotChgAvg != 0 then NetChgAvg / TotChgAvg else 0;
def RSI = 50 * (ChgRatio + 1);


################################################################
##########                 SMI                         #########
################################################################
# Stochastic Extra Extra High
def min_low_xxxl = Lowest(low(period = xxxlAggregation), smiKPeriod);
def max_high_xxxl = Highest(high(period = xxxlAggregation), smiKPeriod);
def rel_diff_xxxl = close(period = xxxlAggregation) - (max_high_xxxl + min_low_xxxl) / 2;
def diff_xxxl = max_high_xxxl - min_low_xxxl;


def avgrel_xxxl = ExpAverage(ExpAverage(rel_diff_xxxl, smiDPeriod), smiDPeriod);
def avgdiff_xxxl = ExpAverage(ExpAverage(diff_xxxl, smiDPeriod), smiDPeriod);


def SMI_xxxl = if avgdiff_xxxl != 0 then avgrel_xxxl / (avgdiff_xxxl / 2) * 100 else 0;
def AvgSMI_xxxl = ExpAverage(SMI_xxxl, smiDPeriod);


# Stochastic Extra Extra High
def min_low_xxl = Lowest(low(period = xxlAggregation)[-1], smiKPeriod);
def max_high_xxl = Highest(high(period = xxlAggregation)[-1], smiKPeriod);
def rel_diff_xxl = close(period = xxlAggregation)[-1] - (max_high_xxl + min_low_xxl) / 2;
def diff_xxl = max_high_xxl - min_low_xxl;


def avgrel_xxl = ExpAverage(ExpAverage(rel_diff_xxl, smiDPeriod), smiDPeriod);
def avgdiff_xxl = ExpAverage(ExpAverage(diff_xxl, smiDPeriod), smiDPeriod);


def SMI_xxl = if avgdiff_xxl != 0 then avgrel_xxl / (avgdiff_xxl / 2) * 100 else 0;
def AvgSMI_xxl = ExpAverage(SMI_xxl, smiDPeriod);


# Stochastic Extra High
def min_low_xh = Lowest(low(period = extraHighAggregation)[-1], smiKPeriod);
def max_high_xh = Highest(high(period = extraHighAggregation)[-1], smiKPeriod);
def rel_diff_xh = close(period = extraHighAggregation)[-1] - (max_high_xh + min_low_xh) / 2;
def diff_xh = max_high_xxl - min_low_xh;


def avgrel_xh = ExpAverage(ExpAverage(rel_diff_xh, smiDPeriod), smiDPeriod);
def avgdiff_xh = ExpAverage(ExpAverage(diff_xh, smiDPeriod), smiDPeriod);


def SMI_xh = if avgdiff_xxl != 0 then avgrel_xxl / (avgdiff_xxl / 2) * 100 else 0;
def AvgSMI_xh = ExpAverage(SMI_xxl, smiDPeriod);


# Stochastic Highest
def min_low_h = Lowest(low(period = highestAggregation)[-1], smiKPeriod);
def max_high_h = Highest(high(period = highestAggregation)[-1], smiKPeriod);
def rel_diff_h = close(period = highestAggregation)[-1] - (max_high_h + min_low_h) / 2;
def diff_h = max_high_h - min_low_h;


def avgrel_h = ExpAverage(ExpAverage(rel_diff_h, smiDPeriod), smiDPeriod);
def avgdiff_h = ExpAverage(ExpAverage(diff_h, smiDPeriod), smiDPeriod);


def SMI_h = if avgdiff_h != 0 then avgrel_h / (avgdiff_h / 2) * 100 else 0;
def AvgSMI_h = ExpAverage(SMI_h, smiDPeriod);


# Stochastic Middle
def min_low_m = Lowest(low(period = middleAggregation)[-1], smiKPeriod);
def max_high_m = Highest(high(period = middleAggregation)[-1], smiKPeriod);
def rel_diff_m = close(period = middleAggregation)[-1] - (max_high_m + min_low_m) / 2;
def diff_m = max_high_m - min_low_m;


def avgrel_m = ExpAverage(ExpAverage(rel_diff_m, smiDPeriod), smiDPeriod);
def avgdiff_m = ExpAverage(ExpAverage(diff_m, smiDPeriod), smiDPeriod);


def SMI_m = if avgdiff_m != 0 then avgrel_m / (avgdiff_m / 2) * 100 else 0;
def AvgSMI_m = ExpAverage(SMI_m, smiDPeriod);


# Stochastic Lowest
def min_low_l = Lowest(low(period = lowestAggregation)[-1], smiKPeriod);
def max_high_l = Highest(high(period = lowestAggregation)[-1], smiKPeriod);
def rel_diff_l = close(period = lowestAggregation)[-1] - (max_high_l + min_low_l) / 2;
def diff_l = max_high_l - min_low_l;


def avgrel_l = ExpAverage(ExpAverage(rel_diff_l, smiDPeriod), smiDPeriod);
def avgdiff_l = ExpAverage(ExpAverage(diff_l, smiDPeriod), smiDPeriod);


def SMI_l = if avgdiff_l != 0 then avgrel_l / (avgdiff_l / 2) * 100 else 0;
def AvgSMI_l = ExpAverage(SMI_l, smiDPeriod);


def smiCrossBelowExit = if SMI_xh crosses below 40 then 1 else 0;
def smiCrossAboveExit = if SMI_xh crosses above 40 then 1 else 0;


################################################################
##########                 MACD                      ###########
################################################################
def price_l = close(period = lowestAggregation)[-1];
def price_m = close(period = middleAggregation)[-1];
def price_h = close(period = highestAggregation)[-1];
def price_xh = close(period = extraHighAggregation)[-1];
def price_xxl = close(period = xxlAggregation)[-1];
def price_xxxl = close(period = xxxlAggregation)[-1];


def macDValue_l = MovingAverage(MACDAverageType, price_l, MACDFastLength) - MovingAverage(MACDAverageType, price_xh, MACDSlowLength);
def macDAvg_l = MovingAverage(MACDAverageType, macDValue_l, MACDLength);
def macDValue_m = MovingAverage(MACDAverageType, price_m, MACDFastLength) - MovingAverage(MACDAverageType, price_xh, MACDSlowLength);
def macDAvg_m = MovingAverage(MACDAverageType, macDValue_m, MACDLength);
def macDValue_h = MovingAverage(MACDAverageType, price_h, MACDFastLength) - MovingAverage(MACDAverageType, price_xh, MACDSlowLength);
def macDAvg_h = MovingAverage(MACDAverageType, macDValue_h, MACDLength);
def macDValue_xh = MovingAverage(MACDAverageType, price_xh, MACDFastLength) - MovingAverage(MACDAverageType, price_xh, MACDSlowLength);
def macDAvg_xh = MovingAverage(MACDAverageType, macDValue_xh, MACDLength);
def macDValue_xxl = MovingAverage(MACDAverageType, price_xxl, MACDFastLength) - MovingAverage(MACDAverageType, price_xh, MACDSlowLength);
def macDAvg_xxl = MovingAverage(MACDAverageType, macDValue_xxl, MACDLength);
def macDValue_xxxl = MovingAverage(MACDAverageType, price_xxxl, MACDFastLength) - MovingAverage(MACDAverageType, price_xh, MACDSlowLength);
def macDAvg_xxxl = MovingAverage(MACDAverageType, macDValue_xxxl, MACDLength);


################################################################
##########                 CPMO                      ###########
################################################################
def PrimaryPMO_l = reference PMO(price = close(period = lowestAggregation)[-1], length1 = cpmoLength1, length2 = cpmoLength2);
def PrimarySignalLine_l = ExpAverage(PrimaryPMO_l, cpmoSignalLength);


################################################################
##########                 CALC                      ###########
################################################################
def smiEnter = if smiEnterBelow <= 0 then -40 else if smiEnterBelow >= 40 then 0 else smiEnterBelow - 40;
def smiExit = if smiExitBelow <= 0 then -40 else if smiEnterBelow >= 40 then 0 else smiEnterBelow - 40;
def smiEnterShort = smiEnter * (-1);
def smiExitShort = smiEnter * (-1);
def smiSafeGuard = if mode == mode.superScalp then 100 else 50;
def smiSafeGuardShort = if mode == mode.superScalp then -100 else -50;


def macDLong;
if timeLongMACD == 6 {
    macDLong = if macDValue_xxxl > macDAvg_xxxl and macDValue_xxl > macDAvg_xxl then 1 else 0;
} else if timeLongMACD == 5 {
    macDLong = if macDValue_xxl > macDAvg_xxl and macDValue_xh > macDAvg_xh then 1 else 0;
} else if timeLongMACD == 4 {
    macDLong = if macDValue_xh > macDAvg_xh and macDValue_h > macDAvg_h then 1 else 0;
} else if timeLongMACD == 3 {
    macDLong = if macDValue_h > macDAvg_h and macDValue_m > macDAvg_m then 1 else 0;
} else if timeLongMACD == 2 {
    macDLong = if macDValue_m > macDAvg_m and macDValue_l > macDAvg_l then 1 else 0;
} else {
    macDLong = if macDValue_l > macDAvg_l then 1 else 0;
}


def macDValueExit;
def macDAvgExit;
if priceUp {
    macDValueExit = if macDValue_xxxl < macDAvg_xxxl then macDValue_xh else macDValue_xxl;
    macDAvgExit = if macDValue_xxxl < macDAvg_xxxl then macDAvg_xh else macDAvg_xxl;
} else {
    macDValueExit = if macDValue_xxl < macDAvg_xxl then macDValue_h else macDValue_xh;
    macDAvgExit = if macDValue_xxl < macDAvg_xxl then macDAvg_h else macDAvg_xh;
}


def macDShort;
if timeLongMACD == 6 {
    macDShort = if macDValue_xxxl < macDAvg_xxxl and macDValue_xxl < macDAvg_xxl then 1 else 0;
} else if timeLongMACD == 5 {
    macDShort = if macDValue_xxl < macDAvg_xxl and macDValue_xh < macDAvg_xh then 1 else 0;
} else if timeLongMACD == 4 {
    macDShort = if macDValue_xh < macDAvg_xh and macDValue_h < macDAvg_h then 1 else 0;
} else if timeLongMACD == 3 {
    macDShort = if macDValue_h < macDAvg_h and macDValue_m < macDAvg_m then 1 else 0;
} else if timeLongMACD == 2 {
    macDShort = if macDValue_m < macDAvg_m and macDValue_l < macDAvg_l then 1 else 0;
} else {
    macDShort = if macDValue_l < macDAvg_l then 1 else 0;
}


def macDValueExitShort;
def macDAvgExitShort;
if priceDown {
    macDValueExitShort = if macDValue_xxxl < macDAvg_xxxl then macDValue_xh else macDValue_xxl;
    macDAvgExitShort = if macDValue_xxxl < macDAvg_xxxl then macDAvg_xh else macDAvg_xxl;
} else {
    macDValueExitShort = macDValue_xh;
    macDAvgExitShort = macDAvg_xh;
}   


#################################################################
############          SCAN Variables                    #########
#################################################################
plot Uptrend;
plot DownTrend;


if tradetype == tradetype.long or tradetype == tradetype.both {
    if timeLong == 6 {
        if (SMI_xxxl > AvgSMI_xxxl or SMI_xxxl <= smiEnter) and (SMI_xxl > AvgSMI_xxl or SMI_xxl <= smiEnter) and (SMI_xh > AvgSMI_xh or SMI_xh <= smiEnter) and SMI_h > AvgSMI_h and SMI_h <= smiSafeGuard and SMI_m > AvgSMI_m and SMI_l > AvgSMI_l and macDLong {
            Uptrend = 1;
        } else {
            Uptrend = 0;
        }
    } else if timeLong == 5 {
        if (SMI_xxl > AvgSMI_xxl or SMI_xxl <= smiEnter) and (SMI_xh > AvgSMI_xh or SMI_xh <= smiEnter) and SMI_h > AvgSMI_h and SMI_h <= smiSafeGuard and SMI_m > AvgSMI_m and SMI_l > AvgSMI_l and macDLong {
            Uptrend = 1;
        } else {
            Uptrend = 0;
        }
    } else if timeLong == 4 {
        if (SMI_xh > AvgSMI_xh or SMI_xh <= smiEnter) and SMI_h > AvgSMI_h and SMI_h <= smiSafeGuard and SMI_m > AvgSMI_m and SMI_l > AvgSMI_l and macDLong  {
            Uptrend = 1;
        } else {
            Uptrend = 0;
        }
    } else if timeLong == 3 {
        if (SMI_h > AvgSMI_h or SMI_h <= smiEnter) and SMI_m > AvgSMI_m and SMI_l > AvgSMI_l and macDLong {
            Uptrend = 1;
        } else {
            Uptrend = 0;
        }
    } else if timeLong == 2 {
        if SMI_h <= 40 and SMI_m > AvgSMI_m and SMI_l > AvgSMI_l and macDLong {
            Uptrend = 1;
        } else {
            Uptrend = 0;
        }
    } else {
        if PrimaryPMO_l > PrimarySignalLine_l {
            Uptrend = 1;
        } else {
            Uptrend = 0;
        }
    }
} else {
    Uptrend = 0;
}


if tradetype == tradetype.short or tradetype == tradetype.both {
    if timeShort == 6 {
        if (SMI_xxxl < AvgSMI_xxxl or SMI_xxxl >= smiEnterShort) and (SMI_xxl < AvgSMI_xxl or SMI_xxl >= smiEnterShort) and (SMI_xh < AvgSMI_xh or SMI_xh >= smiEnterShort) and SMI_h < AvgSMI_h and SMI_h >= smiSafeGuardShort and SMI_m < AvgSMI_m and SMI_l < AvgSMI_l and macDShort {
            DownTrend = 1;
        } else {
            DownTrend = 0;
        }
    } else if timeShort == 5 {
        if (SMI_xxl < AvgSMI_xxl or SMI_xxl >= smiEnterShort) and (SMI_xh < AvgSMI_xh or SMI_xh >= smiEnterShort) and SMI_h < AvgSMI_h and SMI_h >= smiSafeGuardShort and SMI_m < AvgSMI_m and SMI_l < AvgSMI_l and macDShort {
            DownTrend = 1;
        } else {
            DownTrend = 0;
        }
    } else if timeShort == 4 {
        if (SMI_xh < AvgSMI_xh or SMI_xh >= smiEnterShort) and SMI_h < AvgSMI_h and SMI_m < AvgSMI_m and SMI_h >= smiSafeGuardShort and SMI_l < AvgSMI_l and macDShort {
            DownTrend = 1;
        } else {
            DownTrend = 0;
        }
    } else if timeShort == 3 {
        if (SMI_h < AvgSMI_h or SMI_h >= smiEnterShort) and SMI_h >= smiSafeGuardShort  and SMI_m < AvgSMI_m and SMI_l < AvgSMI_l and macDShort {
            DownTrend = 1;
        } else {
            DownTrend = 0;
        }
    } else if timeShort == 2 {
        if SMI_h >= -40 and SMI_m < AvgSMI_m and SMI_l < AvgSMI_l and macDShort {
            DownTrend = 1;
        } else {
            DownTrend = 0;
        }
    } else {
        if PrimaryPMO_l < PrimarySignalLine_l {
            DownTrend = 1;
        } else {
            DownTrend = 0;
        }
    }
} else {
    DownTrend = 0;
}


plot ExitUpTrend;
plot ExitDownTrend;


#Exit UpTrend
if RSI >= rsiOverBought {
    ExitUpTrend = 1;
} else if smiCrossBelowExit {
    ExitUpTrend = 1;
} else if (SMI_xxxl > AvgSMI_xxxl and SMI_xxl > AvgSMI_xxl) or (SMI_xxl < smiExit and SMI_xxl > AvgSMI_xxl) and priceUp{
    ExitUpTrend = if SMI_xh < AvgSMI_xh and SMI_h < AvgSMI_h and SMI_m < AvgSMI_m and SMI_l < AvgSMI_l or macDValueExit < macdAvgExit then 1 else 0;
} else if (SMI_xxl > AvgSMI_xxl and SMI_xh > AvgSMI_xh) or (SMI_xh < smiExit and SMI_xh > AvgSMI_xh) {
    ExitUpTrend = if SMI_h < AvgSMI_h and SMI_m < AvgSMI_m and SMI_l < AvgSMI_l or macDValueExit < macdAvgExit then 1 else 0;
} else if (SMI_xh > AvgSMI_xh and SMI_h > AvgSMI_h) or (SMI_h < smiExit and SMI_h > AvgSMI_h) {
    ExitUpTrend = if SMI_m < AvgSMI_m and SMI_l < AvgSMI_l or macDValueExit < macdAvgExit then 1 else 0;
} else if (SMI_h > AvgSMI_h and SMI_m > AvgSMI_m) or (SMI_m < smiExit and SMI_m > AvgSMI_m) {
    ExitUpTrend = if PrimaryPMO_l < PrimarySignalLine_l or macDValueExit < macdAvgExit then 1 else 0;
} else {
    ExitUpTrend = if SMI_l < AvgSMI_l then 1 else 0;
}


# Exit DownTrend
if RSI <= rsiOverSold {
    ExitDownTrend = 1;
} else if smiCrossAboveExit {
    ExitDownTrend = 1;
} else if (SMI_xxxl < AvgSMI_xxxl and SMI_xxl < AvgSMI_xxl) or (SMI_xxl > smiExitShort and SMI_xxl < AvgSMI_xxl) and priceDown {
    ExitDownTrend = if SMI_xh > AvgSMI_xh and SMI_h > AvgSMI_h and SMI_m > AvgSMI_m and SMI_l > AvgSMI_l or macDValueExitShort > macdAvgExitShort then 1 else 0;
} else if (SMI_xxl < AvgSMI_xxl and SMI_xh < AvgSMI_xh) or (SMI_xh > smiExitShort and SMI_xh < AvgSMI_xh) {
    ExitDownTrend = if SMI_h > AvgSMI_h and SMI_m > AvgSMI_m and SMI_l > AvgSMI_l or macDValueExitShort > macdAvgExitShort then 1 else 0;
} else if (SMI_xh < AvgSMI_xh and SMI_h < AvgSMI_h) or (SMI_h > smiExitShort and SMI_h < AvgSMI_h) {
    ExitDownTrend = if SMI_m > AvgSMI_m and SMI_l > AvgSMI_l or macDValueExitShort > macdAvgExitShort then 1 else 0;
} else if (SMI_h < AvgSMI_h and SMI_m < AvgSMI_m) or (SMI_m > smiExitShort and SMI_m < AvgSMI_m) {
    ExitDownTrend = if PrimaryPMO_l > PrimarySignalLine_l or macDValueExitShort > macdAvgExitShort then 1 else 0;
} else {
    ExitDownTrend = if SMI_l > AvgSMI_l then 1 else 0;
}


def LongBuy = if Uptrend == 1 and Uptrend[1] == 0 then 1 else 0;
def LongExit = if ExitUpTrend == 1 and ExitUpTrend[1] == 0 then 1 else 0;


def ShortSell = if DownTrend == 1 and DownTrend[1] == 0 then 1 else 0;
def ShortExit = if ExitDownTrend == 1 and ExitDownTrend[1] == 0 then 1 else 0;


Uptrend.Hide();
DownTrend.Hide();
ExitUpTrend.Hide();
ExitDownTrend.Hide();


#################################################################
############          NOTIFICATIONS                     #########
#################################################################
#AddLabel(yes, if Uptrend == 1 and ExitUpTrend == 0 then "::Go Long::" else if DownTrend == 1 and ExitDownTrend == 0 then "::Go Short::" else "::Do Nothing::", if Uptrend == 1 and ExitUpTrend == 0 then Color.CYAN else if DownTrend == 1 and ExitDownTrend == 0 then Color.MAGENTA else Color.GRAY);


def bar = BarNumber();


def longSignal = if Uptrend == 1 and ExitUpTrend == 0 then 1 else 0;


#Alert(longSignal == 1, "MTF Uptrend", Alert.BAR, Sound.Ring);


def shortSignal = if DownTrend == 1 and ExitDownTrend == 0 then 1 else 0;
#Alert(shortSignal == 1, "MTF Downtrend", Alert.BAR, Sound.Ding);


def longExitSignal = if Uptrend == 0 and ExitUpTrend == 1 then 1 else 0;
#Alert(longSignal == 1, "MTF Uptrend", Alert.BAR, Sound.Ding);


def shortExitSignal = if DownTrend == 0 and ExitDownTrend == 1 then 1 else 0;
#Alert(shortSignal == 1, "MTF Downtrend", Alert.BAR, Sound.Ring);


################################################################
##########                 BUY                       ###########
################################################################


AddOrder(OrderType.BUY_AUTO, LongBuy == 1 and (tradetype == tradetype.long or tradetype == tradetype.both) and Active and testTimeFrames, price = close[-1], tickcolor = Color.CYAN, arrowcolor = Color.CYAN, name = "BUY");
AddOrder(OrderType.SELL_TO_CLOSE, LongExit == 1 and (tradetype == tradetype.long or tradetype == tradetype.both) and Active and testTimeFrames, price = open[-2], tickcolor = Color.MAGENTA, arrowcolor = Color.MAGENTA, name = "Sell To Close");
AddOrder(OrderType.SELL_TO_CLOSE, EOD or CloseAllCondition and testTimeFrames, price = close[-1], tickcolor = Color.MAGENTA, arrowcolor = Color.MAGENTA, name = "SELL EOD");


################################################################
##########                 SELL                      ###########
################################################################


AddOrder(OrderType.SELL_AUTO, ShortSell == 1 and (tradetype == tradetype.short or tradetype == tradetype.both) and Active and testTimeFrames, price = close[-1], tickcolor = Color.MAGENTA, arrowcolor = Color.MAGENTA, name = "SELL");
AddOrder(OrderType.BUY_TO_CLOSE, ShortExit == 1 and (tradetype == tradetype.short or tradetype == tradetype.both) and Active and testTimeFrames, price = open[-2], tickcolor = Color.CYAN, arrowcolor = Color.CYAN, name = "Buy To Close");
AddOrder(OrderType.BUY_TO_CLOSE, EOD or CloseAllCondition and testTimeFrames, price = close[-1], tickcolor = Color.CYAN, arrowcolor = Color.CYAN, name = "BUY EOD");


#################################################################
############          FPL Extended                      #########
#################################################################


#Hint: An extended floating P&L study to be used alongside TOS strategies for measuring hypothetical strategy performance.\nThis is a work in progress.  And may contain some bugs or other programming issues.


############################
# Instructions
# - Due to limitations with the thinkscript public api, this specific script must be added to a "strategy" study.
#   Generally best practice is to append this script to the end of your custom strategy (ensuring it runs AFTER the
#   `AddOrder()` function is called from the strategy).  A better method would be to use as a lower study but unless
#    a workaround is implemented to handle the `Entry()` function in a lower study, it can only be applied to upper strategies.
#
# - the script uses the `HidePrice()` function which will hide the actual price candles within the upper study,
#   only displaying the FPL histogram.
#
############################




############################
#    Metrics             
#  - Active Trade return %
#  - Entry Count         
#  - Winning Entry Count 
#  - Win rate           
#  - Avg return         
#  - avg win             
#  - avg loss           
#  - peak to valley dd   
#  - largest equity dd   
#  - P&L low             
#  - P&L high           
#  - Highest return   
#  - Lowest return     
############################


############################
#     Todo:             
# - Sharpe Ratio   
# - Sortino Ratio   
# - Calmar Ratio   
# - Avg trade         
#   duration           
# -Buy/hold comparison   
############################




#Globals
def nan = Double.NaN;
def bn = if !IsNaN(close[-1]) and !IsNaN(close) and !IsNaN(close[-2]) then BarNumber() else bn[1];


#Inputs
input fplTargetWinLoss = .50;
#hint fplTargetWinLoss: sets the target winlossRatio (in percent) which determines display colors of the W/L label.


input fplTargetWinRate = 1;
#hint fplTargetWinRate: sets the target winRate (float) which determines display colors of the WinRate label;


input fplHidePrice = no;
#hint fplHidePrice: hide's the underlying price graph. \nDefault is no.


input fplHideFPL = yes;
#hint fplHideFPL: hide's the underlying P&L graph.\nDefault is yes.


#temp input var references
def targetWinLoss = fplTargetWinLoss;
def targetWinRate = fplTargetWinRate;
def hidePrice = fplHidePrice;
def hideFPL = fplHideFPL;


#hide chart candles
HidePricePlot(hidePrice);


#Plot default Floating P&L
plot FPL = FPL();
FPL.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
FPL.DefineColor("Positive and Up", Color.GREEN);
FPL.DefineColor("Positive and Down", Color.DARK_GREEN);
FPL.DefineColor("Negative and Down", Color.RED);
FPL.DefineColor("Negative and Up", Color.DARK_RED);
FPL.AssignValueColor(if FPL >= 0
                        then if FPL > FPL[1]
                        then FPL.Color("Positive and Up")
                        else FPL.Color("Positive and Down")
                        else if FPL < FPL[1]
                        then FPL.Color("Negative and Down")
                        else FPL.Color("Negative and Up"));
FPL.SetHiding(hideFPL);


plot ZeroLine = if IsNaN(close[-1])
            then nan
            else 0;
ZeroLine.SetDefaultColor(Color.GRAY);
ZeroLine.SetHiding(hideFPL);


#Global Scripts
script incrementValue {
    input condition = yes;
    input increment =  1;
    input startingValue = 0;


    def _value = CompoundValue(1,
                if condition
                then _value[1] + increment
                else _value[1], startingValue);


    plot incrementValue = _value;
}
;


# Entry Calculations.  Note: Only parses on a Strategy Chart
def entry = EntryPrice();


def entryPrice = if !IsNaN(entry)
                then entry
                else entryPrice[1];


def hasEntry = !IsNaN(entry);


def isNewEntry = entryPrice != entryPrice[1];


#is active trade
def highFPL = HighestAll(FPL);
def lowFPL = LowestAll(FPL);


def fplreturn = (FPL - FPL[1]) / FPL[1];
def cumsum = Sum(fplreturn);


def highBarNumber = CompoundValue(1, if FPL == highFPL
                                    then bn
                                    else highBarNumber[1], 0);


def lowBarNumber = CompoundValue(1, if FPL == lowFPL
                                then bn
                                else lowBarNumber[1], 0);


#Win/Loss ratios
def entryBarsTemp = if hasEntry
                then bn
                else nan;


def entryBarNum = if hasEntry and isNewEntry
                then bn
                else entryBarNum[1];


def isEntryBar = entryBarNum != entryBarNum[1];


def entryBarPL = if isEntryBar
                then FPL
                else entryBarPL[1];


def exitBarsTemp = if !hasEntry
                and bn > entryBarsTemp[1]
                then bn
                else nan;


def exitBarNum = if !hasEntry and !IsNaN(exitBarsTemp[1])
                then bn
                else exitBarNum[1];


def isExitBar = exitBarNum != exitBarNum[1];


def exitBarPL = if isExitBar
            then FPL
            else exitBarPL[1];


def entryReturn = if isExitBar then exitBarPL - exitBarPL[1] else entryReturn[1];
def isWin = if isExitBar and entryReturn >= 0 then 1 else 0;
def isLoss = if isExitBar and entryReturn < 0 then 1 else 0;
def entryReturnWin = if isWin then entryReturn else entryReturnWin[1];
def entryReturnLoss = if isLoss then entryReturn else entryReturnLoss[1];
def entryFPLWins = if isWin then entryReturn else 0;
def entryFPLLosses = if isLoss then entryReturn else 0;
def entryFPLAll = if isLoss or isWin then entryReturn else 0;


#Counts
def entryCount = incrementValue(entryFPLAll);
def winCount = incrementValue(isWin);
def lossCount = incrementValue(isLoss);


def highestReturn = if entryReturnWin[1] > highestReturn[1]
                then entryReturnWin[1]
                else highestReturn[1];


def lowestReturn = if entryReturnLoss[1] < lowestReturn[1]
                then entryReturnLoss[1]
                else lowestReturn[1];




def winRate = winCount / lossCount;
def winLossRatio = winCount / entryCount;
def avgReturn = TotalSum(entryFPLAll) / entryCount;
def avgWin = TotalSum(entryFPLWins) / winCount;
def avgLoss = TotalSum(entryFPLLosses) / lossCount;


#Daily profit
def Midnight = if Active then FPL else Midnight[1];
def DaysProfit = FPL - Midnight;


#Labels


AddLabel(yes,
        text = "Total Trades: " + entryCount,
        color = Color.WHITE
        );


AddLabel(yes,
        text = "WinCount: " + winCount +
            " | LossCount: " + lossCount +
            " | WinRate: " + winRate,
        color = if winRate >= targetWinRate
                then Color.CYAN
                else Color.MAGENTA
        );


AddLabel(yes,
        text = "W/L: " + AsPercent(winLossRatio),
        color = if winLossRatio > targetWinLoss
                then Color.CYAN
                else Color.MAGENTA
        );


AddLabel(yes,
        text = "AvgReturn: " + AsDollars(avgReturn) +
            " | AvgWin: " + AsDollars(avgWin) +
            " | AvgLoss: " + AsDollars(avgLoss),
        color = if avgReturn >= 0
                then Color.CYAN
                else Color.MAGENTA
        );


AddLabel(yes,
        text = "Total Profit: " + AsDollars(FPL),
        color = if FPL > 0
                then Color.CYAN
                else Color.MAGENTA
    );
 

Similar threads

Top