SuperTrend Backtesting Strategy for ThinkorSwim

RConner7

Member
Hello All - I've been working on a strategy that incorporates a 3 SuperTrend (yahoo finance version) (fast, medium, slow) + previous Support and Resistance levels. Essentially what the strategy does is lookback to find the previous high and low. If price close breaks the previous high and all 3 supertrends are green, it will indicate a buy signal. opposite for short trades.

I'm looking for some feedback on this strategy to see what can be done to make it better and more dynamic based on the stock you are trading. - or really... if it ****s... tell me why.

I've been testing this with the below settings on BA (Boeing) from a 2 minute time frame for the past 30 days and seeing very decent results with 100 share trade lots. [see below] I have found that the strategy will work for different stocks as well but has varying results. Results will vary based upon the atr lengths and lookbacks for each supertrend. (would be looking for help figuring out a way to make this dynamic if possible. - Finding a way to calculate and set these based on a variable from the selected stock)

--code still includes some things i was playing around with but unused stuff is commented out--

Code:
#3-SuperTrend & HighLow Strategy by RConner7
#includes Backtesting utility results from eddielee394
#2 min time frame but could 3 ST ATRs and High/Low lookbackPeriod can be adjusted.
#----------------------------
#def atr1 = atr();
#def atr2 = atr() * 2;
#def atr3 = atr() * 3;

input AlertOn  = yes;
input AtrMult = .70;

input nATR = 4;

input AvgType = AverageType.HULL;

input PaintBars = yes;

input BubbleOn = yes;

input ShowLabel = yes;

#def beginDay = if barNumber() < nATR then barNumber() else nATR;

def h = high;

def l = low;

def c = close;

def v = volume;

def bar = BarNumber();

def CloseAllCondition = SecondstillTime(1558) == 0;

def EOD = if SecondsTillTime(1558) == 0 and

             SecondsFromTime(1558) == 0

          then 1

          else 0;

def NotActive = if SecondsFromTime(1550) > 0

                then 1

                else 0;

def Active1 = if SecondsFromTime(0930) > 0 then 1 else 0;

def notrades = if SecondstillTime(1500) > 0 then 1 else 0;

def ATR = MovingAverage(AvgType, TrueRange(h, c, l), nAtr);
def UP_Band_Basic = HL2 + (AtrMult * ATR);

def LW_Band_Basic = HL2 + (-AtrMult * ATR);

def UP_Band = if Active1 and ((UP_Band_Basic < UP_Band[1]) or (close[1] > UP_Band[1])) then UP_Band_Basic else UP_Band[1];

def LW_Band = if Active1 and ((LW_Band_Basic > LW_Band[1]) or (close[1] < LW_Band[1])) then LW_Band_Basic else LW_Band[1];

def ST = if Active1 and ((ST[1] == UP_Band[1]) and (close < UP_Band)) then UP_Band else if ((ST[1] == UP_Band[1]) and (close > Up_Band)) then LW_Band else if ((ST[1] == LW_Band[1]) and (close > LW_Band)) then LW_Band else if ((ST[1] == LW_Band) and (close < LW_Band)) then UP_Band else LW_Band;

plot SuperTrend = ST;

SuperTrend.AssignValueColor(if c < ST then Color.RED else Color.GREEN);

SuperTrend.SetPaintingStrategy(PaintingStrategy.LINE);

AssignPriceColor(if PaintBars and c < ST

                 then Color.RED

                 else if PaintBars and c > ST

                      then Color.GREEN

                      else Color.CURRENT);

#ST2

input AtrMult_2 = 1.5;

input nATR_2 = 3;

input AvgType_2 = AverageType.HULL;

input PaintBars_2 = no;

input BubbleOn_2 = no;

input ShowLabel_2 = no;

def beginDay_2 = if barNumber() < nATR_2 then barNumber() else nATR_2;


def Active_2 = if SecondsFromTime(0930) > 0  then 1 else 0;

def ATR_2 = MovingAverage(AvgType_2, TrueRange(h, c, l), nAtr_2);
def UP_Band_Basic_2 = HL2 + (AtrMult_2 * ATR_2);

def LW_Band_Basic_2 = HL2 + (-AtrMult_2 * ATR_2);

def UP_Band_2 = if Active_2 and ((UP_Band_Basic_2 < UP_Band_2[1]) or (close[1] > UP_Band_2[1])) then UP_Band_Basic_2 else UP_Band_2[1];

def LW_Band_2 = if Active_2 and ((LW_Band_Basic_2 > LW_Band_2[1]) or (close[1] < LW_Band_2[1])) then LW_Band_Basic_2 else LW_Band_2[1];

def ST_2= if Active_2 and ((ST_2[1] == UP_Band_2[1]) and (close < UP_Band_2)) then UP_Band_2 else if ((ST_2[1] == UP_Band_2[1]) and (close > Up_Band_2)) then LW_Band_2 else if ((ST_2[1] == LW_Band_2[1]) and (close > LW_Band_2)) then LW_Band_2 else if ((ST_2[1] == LW_Band_2) and (close < LW_Band_2)) then UP_Band_2 else LW_Band_2;


plot SuperTrend_2 = ST_2;

SuperTrend_2.AssignValueColor(if c < ST_2 then Color.RED else Color.GREEN);

SuperTrend_2.SetPaintingStrategy(PaintingStrategy.LINE);

AssignPriceColor(if PaintBars_2 and c < ST_2

                 then Color.RED

                 else if PaintBars_2 and c > ST_2

                      then Color.GREEN

                      else Color.CURRENT);

#ST3

input AtrMult_3 = 3.0;

input nATR_3 = 5;

input AvgType_3 = AverageType.HULL;

input PaintBars_3 = no;

input BubbleOn_3 = no;

input ShowLabel_3 = no;

#def beginDay_3 = if barNumber() < nATR_3 then barNumber() else nATR_3;


def Active_3 = if SecondsFromTime(0930) > 0  then 1 else 0;

def ATR_3 = MovingAverage(AvgType_3, TrueRange(h, c, l), nAtr_3);
def UP_Band_Basic_3 = HL2 + (AtrMult_3 * ATR_3);

def LW_Band_Basic_3 = HL2 + (-AtrMult_3 * ATR_3);

def UP_Band_3 = if Active_3 and ((UP_Band_Basic_3 < UP_Band_3[1]) or (close[1] > UP_Band_3[1])) then UP_Band_Basic_3 else UP_Band_3[1];

def LW_Band_3 = if Active_3 and ((LW_Band_Basic_3 > LW_Band_3[1]) or (close[1] < LW_Band_3[1])) then LW_Band_Basic_3 else LW_Band_3[1];

def ST_3= if Active_3 and ((ST_3[1] == UP_Band_3[1]) and (close < UP_Band_3)) then UP_Band_3 else if ((ST_3[1] == UP_Band_3[1]) and (close > Up_Band_3)) then LW_Band_3 else if ((ST_3[1] == LW_Band_3[1]) and (close > LW_Band_3)) then LW_Band_3 else if ((ST_3[1] == LW_Band_3) and (close < LW_Band_3)) then UP_Band_3 else LW_Band_3;

plot SuperTrend_3 = ST_3;

SuperTrend_3.AssignValueColor(if c < ST_3 then Color.RED else Color.GREEN);

SuperTrend_3.SetPaintingStrategy(PaintingStrategy.LINE);

AssignPriceColor(if PaintBars_3 and c < ST_3

                 then Color.RED

                 else if PaintBars_3 and c > ST_3

                      then Color.GREEN

                      else Color.CURRENT);

#VWAP
def VWAP = if open > reference VWAP()."VWAP" then 1 else 0;

#Money Flow Index
#input MFI_length = 10;
#input MFI_movingAvgLength = 2;

#def MFI = Average(moneyflow(high, close, low, volume, MFI_length), #MFI_movingAvgLength);


#ADX
#input ADXlength = 14;
#input ADXaverageType = AverageType.WILDERS;

#def ADX = DMI(ADXlength, ADXaverageType).ADX;
#def ADX_Trend = if ADX >= 25 then 1 else 0;

#swing high low
input LookbackPeriod = 2;
input HideCurrentTF = no;

def FirstBar = BarNumber();
def Highest = fold i = 1
             to LookbackPeriod + 1
             with p = 1
             while p
             do high > GetValue(high, -i);
def A = if (Firstbar > LookbackPeriod
            and high == Highest(high, LookbackPeriod)
            and Highest)
            then high
            else Double.NaN;
def Lowest = fold j = 1
            to LookbackPeriod + 1
            with q = 1
            while q
            do low < GetValue(low, -j);
def B = if (Firstbar > LookbackPeriod
            and low == Lowest(low, LookbackPeriod)
            and Lowest)
            then low
            else Double.NaN;

#--------------------------------------------------------------
def _highInPeriod1 = Highest(high, LookbackPeriod);
def _lowInPeriod1 = Lowest(low, LookbackPeriod);
#--------------------------------------------------------------
def marketLow1 = if _lowInPeriod1 < _lowInPeriod1[-LookbackPeriod] then _lowInPeriod1 else _lowInPeriod1[-LookbackPeriod];
def _markedLow1 = low == marketLow1;

rec _lastMarkedLow1 = CompoundValue(1, if IsNaN(_markedLow1) then _lastMarkedLow1[1] else if _markedLow1 then low else _lastMarkedLow1[1], low);
#--------------------------------------------------------------
def marketHigh1 = if _highInPeriod1 > _highInPeriod1[-LookbackPeriod] then _highInPeriod1 else _highInPeriod1[-LookbackPeriod];
def _markedHigh1 = high == marketHigh1;

rec _lastMarkedHigh1 = CompoundValue(1, if IsNaN(_markedHigh1) then _lastMarkedHigh1[1] else if _markedHigh1 then high else _lastMarkedHigh1[1], high);
#--------------------------------------------------------------

plot Resistance1 = _lastMarkedHigh1;
plot Support1 = _lastMarkedLow1;

#---------------------------------------
plot ph = Round(A, 2);
ph.SetPaintingStrategy(PaintingStrategy.VALUES_ABOVE);
plot pl = Round(B, 2);
pl.SetPaintingStrategy(PaintingStrategy.VALUES_BELOW);
#--------------------------------------------------------------
Resistance1.SetPaintingStrategy(PaintingStrategy.DASHES);
Resistance1.SetDefaultColor(Color.GREEN);
Resistance1.SetHiding(HideCurrentTF);
#--------------------------------------------------------------
Support1.SetPaintingStrategy(PaintingStrategy.DASHES);
Support1.SetDefaultColor(Color.RED);
Support1.SetHiding(HideCurrentTF);

#Bull
def fast_ST_UP = if HL2 > ST then 1 else 0;
def slow_ST_UP = if HL2 > ST_2 then 1 else 0;
def slower_ST_UP = if HL2 > ST_3 then 1 else 0;
def Trend_UP = if HL2 > ST then 1 else 0;
def Trend_UP_2 = if HL2 > ST_2 then 1 else 0;
def Trend_UP_3 = if HL2 > ST_3 then 1 else 0;
def higher_close = if close crosses above Resistance1[1] then 1 else 0;

#Bear
def fast_ST_DN = if HL2 < ST then 1 else 0;
def slow_ST_DN = if HL2 < ST_2 then 1 else 0;
def slower_ST_DN = if HL2 < ST_3 then 1 else 0;
def Trend_DN = if HL2 < ST then 1 else 0;
def Trend_DN_2 = if HL2 < ST_2 then 1 else 0;
def Trend_DN_3 = if HL2 < ST_3 then 1 else 0;
def lower_close = if close crosses below support1[1] then 1 else 0;

AddOrder(OrderType.BUY_AUTO, (fast_sT_UP or slow_ST_UP or slower_ST_UP) and Trend_Up and Trend_Up_2 and Trend_UP_3 and Active1 and higher_close and notrades, price = close, tickcolor = Color.ORANGE, arrowcolor = Color.ORANGE, name = "BUY");

AddOrder(OrderType.Sell_To_Close, HL2 crosses below ST, price = open[-1], tickcolor = Color.ORANGE, arrowcolor = Color.ORANGE, name = "Sell To Close");


AddOrder(OrderType.Sell_TO_CLOSE, EOD or closeAllCondition, price = close, tickcolor = Color.ORANGE, arrowcolor = Color.ORANGE, name = "SELL EOD");

AddOrder(OrderType.SELL_AUTO, (fast_sT_DN or slow_ST_DN or slower_ST_DN) and Trend_DN and Trend_DN_2 and Trend_DN_3  and Active1 and lower_close and notrades , price = close, tickcolor = Color.YELLOW, arrowcolor = Color.YELLOW, name = "SELL");

AddOrder(OrderType.Buy_To_Close, HL2 crosses above ST, price = open[-1], tickcolor = Color.ORANGE, arrowcolor = Color.ORANGE, name = "Buy To Close");

AddOrder(OrderType.BUY_TO_CLOSE, EOD or closeAllCondition, price = close, tickcolor = Color.ORANGE, arrowcolor = Color.ORANGE, name = "BUY EOD");

alert((fast_sT_UP or slow_ST_UP or slower_ST_UP) and Trend_Up and Trend_Up_2 and Trend_UP_3 and Active1 and higher_close and notrades, "BUY BUY BUY", Alert.Bar, Sound.Bell);
alert((fast_sT_DN or slow_ST_DN or slower_ST_DN) and Trend_DN and Trend_DN_2 and Trend_DN_3  and Active1 and lower_close and notrades, "SELL SELL SELL", Alert.Bar, Sound.Ring);

############################
# FPL Extended
# Extended Floating P&L study.
# Author: Eddielee394
# Version: 1.2
# inspired by FPL Dashboard script developed by Mobius
#
############################

#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) and !IsNaN(close[1]) and !IsNaN(close[-1]) then BarNumber() else bn[1];

#Inputs
input fplBegin = 0000;
#hint fplBegin: start time: the time in which then dailyHighLow profit should consider the day start.  Recommended value is 0000.

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.

input fplShowEntryBubbles = no;
#hint fplShowEntryBubbles: display bubbles on the FPL showing the entry and exit P&L values

input fplEnableDebugging = no;
#hint fplEnableDebugging: displays various debugging labels and chart bubbles. \nIt's recommended to hide the price chart & set the fpl hide fpl setting to yes, when enabling.

#temp input var references
def begin = fplBegin;
def targetWinLoss = fplTargetWinLoss;
def targetWinRate = fplTargetWinRate;
def hidePrice = fplHidePrice;
def hideFPL = fplHideFPL;
def showEntryBubbles = fplShowEntryBubbles;
def enableDebugging = fplEnableDebugging;

#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)
                then nan
                else 0;
ZeroLine.SetDefaultColor(Color.GRAY);
ZeroLine.SetHiding(hideFPL);

#Global Scripts
script calculateDrawdown {
    input plLow = 1;
    input plHigh = 1;

    def _drawdown = if plHigh == 0
                   then 0 #handles the divide by zero error
                   else (plLow - plHigh) / plHigh;
    plot calculateDrawdown = _drawdown;
}

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;
}
;

script getDurationInMins {
    input gdimBarCount = 1;

    #get the aggregation period (MS per bar)
    def aggPeriod = GetAggregationPeriod();

    #multiply length of bars by aggPeriod to determine total milliseconds then convert to minutes
    def _getDurationInMins = Floor((gdimBarCount * aggPeriod) / 60000);
    plot getDurationInMins = _getDurationInMins;
}

script formatDuration {
    input fdBarCount = 1;
    def _fdDuration = getDurationInMins(fdBarCount);
    def _formatDuration = if _fdDuration >= 60 and _fdDuration < 1440 #hours but not days
                         then 1
                         else if _fdDuration >= 1440 #days
                         then 2
                         else 0;

    plot formatDuration = _formatDuration;
}

script calculateDuration {
    input cdBarCount = 1;
    def _cdDurationFormat = formatDuration(cdBarCount);
    def _cdDuration = getDurationInMins(cdBarCount);
   
    #if minutes > hour convert to hour, else if minutes > day, then convert to days
    def _calculateDuration = if _cdDurationFormat == 1
                             then _cdDuration / 60 #convert to hours if greater than 60min but less than a day (1440)
                             else if  _cdDurationFormat == 2
                             then Ceil(_cdDuration / 1440) #convert to days if greater than 1440mins
                             else _cdDuration; #fallback to minutes

    plot calculateDuration = _calculateDuration;
}

# 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 Active = if SecondsTillTime(begin) == 0 and
                SecondsFromTime(begin) == 0
             then 1
             else 0;

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;

#Drawdown
def lowestLowBarNumber = HighestAll(if FPL == lowFPL then bn else 0);
def highestHighBarNumber = HighestAll(if FPL == highFPL and FPL != FPL[1] then bn else 0);
def hasPrevLow = lowestLowBarNumber < highestHighBarNumber;

def isPeak = FPL > Highest(FPL[1], 12) and FPL > Highest(FPL[-12], 12);
def isTrough = FPL < Lowest(FPL[1], 12) and FPL < Lowest(FPL[-12], 12);
def _peak = if isPeak then FPL else nan;
def _trough = if isTrough then FPL else nan;
def peak = if !IsNaN(_peak) then FPL else peak[1];
def trough = if !IsNaN(_trough) then FPL else trough[1];
def peakBN = if isPeak then bn else peakBN[1];
def troughBN = if isTrough then bn else troughBN[1];

def ptvDrawdown = if !hasPrevLow then calculateDrawdown(lowFPL, highFPL) else ptvDrawdown[1];
def equityDrawdown = if isTrough and trough < peak then trough - peak else equityDrawdown[1];
def equityDrawdownPercent = if isTrough and trough < peak then calculateDrawdown(trough, peak) else equityDrawdownPercent[1];
def largestEquityDrawdown = LowestAll(equityDrawdown);
def largestEquityDrawdownPercent = LowestAll(equityDrawdownPercent);

def drawdown = if hasPrevLow
               then largestEquityDrawdownPercent
               else ptvDrawdown;

# Drawdown Durations
def equityDrawdownLength = if bn >= peakBN and bn <= troughBN
                           then troughBN - peakBN
                           else equityDrawdownLength[1];

def ptvDrawdownLength = if bn >= highestHighBarNumber and bn <= lowestLowBarNumber
                        then lowestLowBarNumber - highestHighBarNumber
                        else ptvDrawdownLength[1];

def equityDrawdownDuration = calculateDuration(HighestAll(equityDrawdownLength));
def equityDrawdownDurationFormat = formatDuration(HighestAll(equityDrawdownLength));
def ptvDrawdownDuration = calculateDuration(ptvDrawdownLength);

def ptvDrawdownDurationFormat = formatDuration(ptvDrawdownLength);

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

#Plots

AddChartBubble(!hideFPL and showEntryBubbles and isEntryBar, FPL, "Entry: " + entryBarPL + " | " + bn, Color.WHITE);
AddChartBubble(!hideFPL and showEntryBubbles and isExitBar, FPL, "Exit: " + exitBarPL,
               color = if isWin
                       then Color.LIGHT_GREEN
                       else if isLoss
                       then Color.DARK_RED
                       else Color.GRAY,
               up = no
              );

#Labels

AddLabel(yes,
         text = "LastEntry: " + AsPrice(entryPrice)
         );

AddLabel(hasEntry,
         text = "Current Trade % Return:  " + AsPercent(cumsum),
         color = if cumsum > 0
         then Color.GREEN
         else Color.RED
        );

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

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

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

AddLabel(yes,
        text = "HighestReturn: " +  AsDollars(highestReturn),
        color = if highestReturn > 0
                then Color.GREEN
                else Color.RED
        );

AddLabel(yes,
        text = "LowestReturn: " +  AsDollars(lowestReturn),
        color = if lowestReturn > 0
                then Color.GREEN
                else Color.RED
        );

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

AddLabel(yes,
        text = "PeakToValley DD: " +  AsPercent(drawdown) +
               " | Duration: " + ptvDrawdownDuration +
                if ptvDrawdownDurationFormat == 1
                then " hours"
                else if ptvDrawdownDurationFormat == 2
                then " days"
                else " mins" ,
        color = if drawdown > 0
                then Color.GREEN
                else Color.RED
        );


AddLabel(largestEquityDrawdown < 0,
        text = "Largest Equity DD: " +  AsDollars(largestEquityDrawdown) +
               " | Duration: " + equityDrawdownDuration +
                if equityDrawdownDurationFormat == 1
                then " hours"
                else if equityDrawdownDurationFormat == 2
                then " days"
                else " mins",
        color = if largestEquityDrawdown > 0
                then Color.GREEN
                else Color.RED
        );

AddLabel(yes,
         text = "P&L High" +
                (if enableDebugging
                then " at bar " + highBarNumber
                else "") +
                ":  " + AsDollars(highFPL),
        color = Color.GREEN
       );

AddLabel(yes,
         text = "P&L Low" +
                (if enableDebugging
                then " at bar " + lowBarNumber
                else "") +
                ":  " + AsDollars(lowFPL),
        color = Color.RED
       );

AddLabel(yes,
         text = "Days Profit: $" + DaysProfit,
         color = if DaysProfit > 0
                 then Color.GREEN
                 else Color.RED
        );

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

#debugging

#peaks & troughs
AddChartBubble(enableDebugging and isPeak, FPL,
               text = "FPL: " + FPL
                      + " | Peak: " + peak
                      + " | Trough: " + trough[-1]
                      + " | Drawdown: " + AsPercent(calculateDrawdown(trough, peak))
                      + " | PeakBN: " + peakBN
                      + " | BarNumber: " + bn,
               color = Color.LIME
              );

AddChartBubble(enableDebugging and isTrough, FPL,
               text = "FPL: " + FPL
                      + " | Peak: " + peak
                      + " | Trough: " + trough
                      + " | Drawdown: " + AsPercent(calculateDrawdown(trough, peak))
                      + " | TroughBN: " + troughBN
                      + " | BarNumber: " + bn,
              color = Color.LIGHT_RED,
              up = no
             );

AddVerticalLine(enableDebugging and isEntryBar,
                text = "EntryBarNum: " + entryBarNum
                       + " | ExitBarNum: " + exitBarNum[-1]
                       + " | BarNumber: " + bn,
                color = Color.WHITE
);

AddVerticalLine(enableDebugging and isExitBar,
                text =  "EntryBarNum: " + entryBarNum[1]
                        + " | ExitbarNum: " + exitBarNum
                        + " | BarNumber: " + bn
                        + " | EntryReturn: " + entryReturn,
                color = if isWin
                        then Color.LIGHT_GREEN
                        else if isLoss
                        then Color.LIGHT_RED
                        else Color.LIGHT_GREEN
);

st2.jpg


Here's another Supertrend strategy made by Mobius.

Code:
# Mobius
# SuperTrend - "Strategy"     A Very simple SuperTrend Strategy
# Chat Room Request
# V03.10.2015
#Hint:Supertrend Indicator: shows trend direction and gives buy or sell signals according to that.

input AtrMult = .70;
input nATR = 4;
input AvgType = AverageType.HULL;
input PaintBars = yes;
input BubbleOn = yes;
input ShowLabel = yes;

def h = high;
def l = low;
def c = close;
def v = volume;
def bar = barNumber();
def EOD = if SecondsTillTime(1545) == 0 and
             SecondsFromTime(1545) == 0
          then 1
          else 0;
def NotActive = if SecondsFromTime(1545) > 0
                then 1
                else 0;
def ATR = MovingAverage(AvgType, TrueRange(h, c, l), nATR);
def UP = HL2 + (AtrMult * ATR);
def DN = HL2 + (-AtrMult * ATR);
def ST = if c < ST[1]
         then UP
         else DN;
plot SuperTrend = ST;
SuperTrend.AssignValueColor(if c < ST then Color.RED else Color.GREEN);
SuperTrend.SetPaintingStrategy(PaintingStrategy.Line);
AssignPriceColor(if PaintBars and c < ST
                 then Color.RED
                 else if PaintBars and c > ST
                      then Color.GREEN
                      else Color.CURRENT);

AddOrder(OrderType.BUY_AUTO, HL2 crosses above ST, price = open[-1], tickcolor = Color.BLACK, arrowcolor = Color.BLACK, name = "");
AddOrder(OrderType.SELL_AUTO, HL2 crosses below ST, price = open[-1], tickcolor = Color.BLACK, arrowcolor = Color.BLACK, name = "");
 
I can test this out as I am currently testing the Supertrend you made...By any chance do you have a scanner to accompany with the Supertrend? Would be easier to look for stocks pulled up by the scanner meeting the criteria...
 
I'm testing this out now. It seems to work well but only when there are volume surges. Stocks like ACB have made a good environment for this strat the last few weeks.
 
I'm testing this out now. It seems to work well but only when there are volume surges. Stocks like ACB have made a good environment for this strat the last few weeks.

thanks for that feedback. I was looking at some volume related tendencies the past couple days as well. I think I’m going to try to incorporate something volume related into the triggers.
 
thanks for that feedback. I was looking at some volume related tendencies the past couple days as well. I think I’m going to try to incorporate something volume related into the triggers.
Although there is some lookback advantage check out mfa. Insane returns. This support/resistance addition to supertrend makes this. Wonderful strategy. I'm going to try trading 1,000 shares of mfa with it on Monday. I'll report back. Realistically you could beat the strategy also if you run if instead of going off of close you place trades when you're certain the close will trigger the signal. This will get you a cent or two per share most trades, It adds up. This is the best coded strategy I've ever seen on here so far.
 
Last edited:
yung can you explain how this work also i can see the strategy its just does not show my moniker is in my signature
 
Hey can iget your help? i dont know how to set a strategy condition that says you can only go long as the next order after the previous trade closed Or to not trigger a sell signal until there’s at least been 1 buy signal before. no shortselling.
 
You may want to consider removing the middle ST (slowST). In my testing it does more harm then good. Using the fast and slower is the best. I got the best tune possible on ACB on the link above. I'm going to use it tomorrow. The chart is glitched in the link where orders don't show and neither do the statistics, to fix this just change the timeframe and it will refresh.

I overlooked that ACB isn't shortable. I'm going to tune it for a different stock today.

I'm going to find the best atr combos for 4 other stocks like it and trade all 5 tomorrow. Its insane how good val performs at 60% win with a average win 2 times higher then average loss. I'm going to exploit this while I can.
 
very nice. I wish there was a good way to dynamically set the atr settings per stock. It would be ideal to find the answer as to ‘why’ these stocks perform best at these settings. I’m sure the best settings constantly change with market conditions but if we could answer that question, we could have a really promising strategy. I’m sure that question of ‘why’ applies to most other strategies as well.

looks like you are even going as far as even changing the average type per SuperTrend. Interesting. Typically hull should respond quickest and be weighted towards current price action. If that is working for you keep going.

love seeing more eyes and thoughts on it; can only help improve it.
 
@RConner7 The dynamic moving per stock is pretty much exactly what Tradestops.com was developed for. That's pretty much all it does to my knowledge.
 
I have not dug into the code of this strategy yet, but I am trying to code something very similar based on a MTF TMO, @RConner7 or @YungTraderFromMontana did you have any issues with the higher timeframe repainting when looking at the lower timeframe chart affecting your buy/sell signals and if not, how to overcome this issue? I am running into this issue on mine.
 
I have not dug into the code of this strategy yet, but I am trying to code something very similar based on a MTF TMO, @RConner7 or @YungTraderFromMontana did you have any issues with the higher timeframe repainting when looking at the lower timeframe chart affecting your buy/sell signals and if not, how to overcome this issue? I am running into this issue on mine.
An mtf will inherently have that issue, no way around it.
 
This is really good work. I took a look at how this strategy has performed over the last 30 trading days using a 2m time interval for each of the 30 stocks in the DJIA. Boeing (BA) was the best performer by far. The worst was UnitedHealth Group (UNH). 18 stocks showed a profit using the strategy compared to 12 showing a loss. There is a strong correlation between profits and beta. The higher the beta, the higher the profit. Of the 9 stocks with betas >1.2, 7 showed a profit with an average of +$1,800. Of the 10 stocks with a beta <0.9 only 4 were profitable and the average was -$208. Boeing has the highest beta by far of any DJIA stock. Maybe something to consider when screening for other stocks to apply this strategy. When looking at the Boeing trades, the strategy made about the same amount of profit from long and short trades. Boeing stock during this time was -41%. So to turn such a profit from day trading Boeing would have been huge. No position was held for more than 54 minutes.
 

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

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
530 Online
Create Post

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top