Smoothed Heikin-Ashi with ATR Trail For ThinkOrSwim

I'm trying to use HA smooth with atr and all I get is full page of buy and sells almost on every bar. Where as with stocks it's ok How to fix ?
thanks If you need a screen shot please advise or put in /cl Ive used minutes and ticks nothing matters. Tks Capt. Bob

It buys and sells on the same bar in oil even in the 5 minute version??? or longer Thanks for the help and fyi even on a day bar it trades a buy and sell on every bar Cheers.

It also is taking form 1 contract to over 670 contracts? I'm not that rich. lol

In reviewing the Shared_angle trend it does not like tick charts. Can a version be created to like tick charts? I got a version to work that does not show the trades as per my last email to you. Does the SAtrim repaint or is it live? thanks C. Bob
 
Another question for the OP or others with technical expertise with ToS code.
How do I get the HA indicator to plot behind the candles? TOS seems to place all indicators, including this custom HA version, on top of the candles. I'd like the indicators behind. Any code that I can add/modify to get there?
Thanks in advance.
 
Smoothed Heikin-Ashi with ATR Trail + P/L (Study)
I put this in Strategies since it's a study that has the P/L built in. It's a combination of things I've found on here over the years (so if you were the original author, just let me know and I'll give credit). It combines a smoothed Heikin-Ashi with an ATR Trail to come up with the buy/sell signals. Not saying it works well or not, just putting it here if someone wants to play around with it. I swing trade so have really only looked at it on a daily timeframe. I'm guessing it would be too slow for day-trading, though you might be able to tweak the settings to make it work.



Ruby:
#hint: Smoothed Heiken Ashi and ATR studies

input period = 20;
input hideCandles = no;
input candleSmoothing = {default Valcu, Vervoort};

input movingAverageType = {Simple, default Exponential, Weighted, Hull, Variable, TEMA};

def openMA;
def closeMA;
def highMA;
def lowMA;

switch (movingAverageType) {
case Simple:
    openMA = compoundValue(1, Average(open, period), open);
    closeMA = compoundValue(1, Average(close, period), close);
    highMA = compoundValue(1, Average(high, period), high);
    lowMA = compoundValue(1, Average(low, period), low);
case Exponential:
    openMA = compoundValue(1, ExpAverage(open, period), open);
    closeMA = compoundValue(1, ExpAverage(close, period), close);
    highMA = compoundValue(1, ExpAverage(high, period), high);
    lowMA = compoundValue(1, ExpAverage(low, period), low);
case Weighted:
    openMA = compoundValue(1, WMA(open, period), open);
    closeMA = compoundValue(1, WMA(close, period), close);
    highMA = compoundValue(1, WMA(high, period), high);
    lowMA = compoundValue(1, WMA(low, period), low);
Case Hull:
    openMA = compoundValue(1, HullMovingAvg(open, period), open);
    closeMA = compoundValue(1, HullMovingAvg(close, period), close);
    highMA = compoundValue(1, HullMovingAvg(high, period), high);
    lowMA = compoundValue(1, HullMovingAvg(low, period), low);
case variable:
    openMA = compoundValue(1, VariableMA(open, period), open);
    closeMA = compoundValue(1, VariableMA(close, period), close);
    highMA = compoundValue(1, VariableMA(high, period), high);
    lowMA = compoundValue(1, VariableMA(low, period), low);
case TEMA:
    openMA = compoundValue(1, TEMA(open, period), open);
    closeMA = compoundValue(1, TEMA(close, period), close);
    highMA = compoundValue(1, TEMA(high, period), high);
    lowMA = compoundValue(1, TEMA(low, period), low);
}

hidePricePlot(hideCandles);

def haOpen;
def haClose;

switch(candleSmoothing) {
case Valcu:
    haOpen = CompoundValue(1, ( (haOpen[1] + (openMA[1] + highMA[1] + lowMA[1] + closeMA[1]) /4.0)/2.0), open);
    haClose = ((OpenMA + HighMA + LowMA + CloseMA)/4.0) ;

case Vervoort:
    haOpen = CompoundValue(1, ( (haOpen[1] + (openMA[1] + highMA[1] + lowMA[1] + closeMA[1]) /4.0)/2.0), open);
    haClose = ((((OpenMA + HighMA + LowMA + CloseMA)/4.0) + haOpen + Max(HighMA, haOpen) + Min(LowMA, haOpen))/4.0);
}

plot o = haOpen + 0;
o.hide();

### Wicks and Shadows

def haLow = min(lowMA, haOpen);
def haHigh = max(highMA,haOpen);


#Red Candlesticks -----------------------------------------------------------------|

def haOpen_fall = if haOpen>haClose
              then haOpen
              else double.nan;
def haHigh_fall   = if haOpen>=haClose
              then haHigh
              else double.nan;
def haLow_fall    = if haOpen>=haClose
              then haLow
              else double.nan;
def haClose_fall    = if haOpen>=haClose
              then haClose
              else double.nan;

AddChart(growColor = Color.plum, fallColor = Color.blue, neutralColor = Color.current, high = haHigh_fall, low = haLow_fall, open = haOpen_fall, close = haClose_fall , type = ChartType.CANDLE);


def haOpen_rise = if haOpen<haClose
                then haClose
                else double.nan;
def haHigh_rise  = if haOpen<=haClose
              then haHigh
              else double.nan;
def haLow_rise   = if haOpen<=haClose
              then haLow
              else double.nan;
def haClose_rise   = if haOpen<=haClose
              then haOpen
              else double.nan;

AddChart(growColor = Color.blue, fallColor = Color.plum, neutralColor = Color.current, high = haHigh_rise, low = haLow_rise, open = haOpen_rise, close = HAclose_rise, type = ChartType.CANDLE);

#############################################################################

#############################################################
###   Determine a flat market
#############################################################


input TradeInFlatRange = Yes;
input BarsForFlatRange = 15;
input BarsReqToStayInRange = 13;

def HH = Highest(high[1], BarsForFlatRange);
def LL = Lowest(low[1], BarsForFlatRange);
def maxH = Highest(HH, BarsReqToStayInRange);
def maxL = Lowest(LL, BarsReqToStayInRange);
def HHn = if maxH == maxH[1] or maxL == maxL then maxH else HHn[1];
def LLn = if maxH == maxH[1] or maxL == maxL then maxL else LLn[1];
def Bh = if high <= HHn and HHn == HHn[1] then HHn else Double.NaN;
def Bl = if low >= LLn and LLn == LLn[1] then LLn else Double.NaN;
def CountH = if IsNaN(Bh) or IsNaN(Bl) then 2 else CountH[1] + 1;
def CountL = if IsNaN(Bh) or IsNaN(Bl) then 2 else CountL[1] + 1;
def ExpH = if BarNumber() == 1 then Double.NaN else
            if CountH[-BarsReqToStayInRange] >= BarsReqToStayInRange then HHn[-BarsReqToStayInRange] else
            if high <= ExpH[1] then ExpH[1] else Double.NaN;
def ExpL = if BarNumber() == 1 then Double.NaN else
            if CountL[-BarsReqToStayInRange] >= BarsReqToStayInRange then LLn[-BarsReqToStayInRange] else
            if low >= ExpL[1] then ExpL[1] else Double.NaN;

plot BoxHigh = if !isnan(expL) and !isnan(ExpH) then ExpH else double.nan;
plot BoxLow = if !isnan(expL) and !isnan(ExpH) then ExpL else double.nan;


addcloud( BoxHigh, BoxLow, color.gray, color.gray);


def Flat = if (!isNan(BoxHigh[1]) and !isNan(BoxLow[1])) AND !TradeInFlatRange then 1 else 0;

#addChartBubble(Flat==1 and isNan(Flat[1]),BoxHigh[1],"Flat Market",color.gray,yes);

input trailType = {default modified, unmodified};
input ATRPeriod = 5;
input ATRFactor = 3.0;
input firstTrade = {default long, short};
input averageType = AverageType.WILDERS;

Assert(ATRFactor > 0, "'atr factor' must be positive: " + ATRFactor);

def HiLo = Min(high - low, 1.5 * Average(high - low, ATRPeriod));
def HRef = if low <= high[1]
    then high - close[1]
    else (high - close[1]) - 0.5 * (low - high[1]);
def LRef = if high >= low[1]
    then close[1] - low
    else (close[1] - low) - 0.5 * (low[1] - high);

def trueRange;
switch (trailType) {
case modified:
    trueRange = Max(HiLo, Max(HRef, LRef));
case unmodified:
    trueRange = TrueRange(high, close, low);
}
def loss = ATRFactor * MovingAverage(averageType, trueRange, ATRPeriod);

def state = {default init, long, short};
def trail;
switch (state[1]) {
case init:
    if (!IsNaN(loss)) {
        switch (firstTrade) {
        case long:
            state = state.long;
            trail =  close - loss;
        case short:
            state = state.short;
            trail = close + loss;
        }
    } else {
        state = state.init;
        trail = Double.NaN;
    }
case long:
    if (close > trail[1]) {
        state = state.long;
        trail = Max(trail[1], close - loss);
    } else {
        state = state.short;
        trail = close + loss;
    }
case short:
    if (close < trail[1]) {
        state = state.short;
        trail = Min(trail[1], close + loss);
    } else {
        state = state.long;
        trail =  close - loss;
    }
}

#def BuySignal = Crosses(state == state.long, 0, CrossingDirection.ABOVE);
#def SellSignal = Crosses(state == state.short, 0, CrossingDirection.ABOVE);

plot TrailingStop = trail;

TrailingStop.SetPaintingStrategy(PaintingStrategy.line);
TrailingStop.DefineColor("Buy", color.blue);
TrailingStop.DefineColor("Sell", color.plum);
TrailingStop.AssignValueColor(if state == state.long
    then TrailingStop.Color("Buy")
    else TrailingStop.Color("Sell"));


############################################
##  Define BuySignal and SellSignal above
##  or uncomment them out below and set
##  them to your buy/sell conditions
##
##  If using stops, define them below
############################################

###------------------------------------------------------------------------------------------

input showSignals = yes;
input showLabels  = yes;
input showBubbles = yes;
input useStops = no;
input useAlerts = no;

###------------------------------------------------------------------------------------------

############################################
##  Create Signals -
##  FILL IN THIS SECTION IF NOT DEFINED ABOVE
##
############################################


def BuySignal = state == state.long AND (haOpen < haClose) and (haOpen[1] < haClose[1]) and !Flat ; # insert condition to create long position
def SellSignal = state == state.short AND (haOpen > haClose)  and (haOpen[1] > haClose[1]) and !Flat; # insert condition to create short position

def BuyStop  = if !useStops then 0 else if  state == state.long AND (haOpen > haClose) and Flat then 1 else 0  ; # insert condition to stop in place of the 0<0
def SellStop = if !useStops then 0 else if  state == state.short AND (haOpen < haClose) and Flat then 1 else 0  ; # insert condition to stop in place of the 0>0

#######################################
##  Maintain the position of trades
#######################################

def CurrentPosition;  # holds whether flat = 0 long = 1 short = -1

if (BarNumber()==1) OR isNaN(CurrentPosition[1]) {
    CurrentPosition = 0;
}else{
        if CurrentPosition[1] == 0 {            # FLAT
            if (BuySignal) {
                CurrentPosition = 1;
            } else if (SellSignal){
                CurrentPosition = -1;
            } else {
                CurrentPosition = CurrentPosition[1];
            }
       } else if CurrentPosition[1] == 1 {      # LONG
            if (SellSignal){
                CurrentPosition = -1;
            } else if (BuyStop and useStops){
                CurrentPosition = 0;
            } else {
                CurrentPosition = CurrentPosition[1];
            }
       } else if CurrentPosition[1] == -1 {     # SHORT
            if (BuySignal){
                CurrentPosition = 1;
            } else if (SellStop and useStops){
                CurrentPosition = 0;
            } else {
                CurrentPosition = CurrentPosition[1];
            }
       } else {
            CurrentPosition = CurrentPosition[1];
       }
}


def isLong  = if CurrentPosition == 1 then 1 else 0;
def isShort = if CurrentPosition == -1 then 1 else 0;
def isFlat  = if CurrentPosition == 0 then 1 else 0;

# If not already long and get a BuySignal
Plot BuySig = if (!isLong[1] and BuySignal and showSignals) then 1 else 0;
BuySig.AssignValueColor(color.cyan);
BuySig.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
BuySig.SetLineWeight(5);

Alert(BuySig and useAlerts, "Buy Signal",Alert.bar,sound.Ding);
Alert(BuySig and useAlerts, "Buy Signal",Alert.bar,sound.Ding);

# If not already short and get a SellSignal
Plot SellSig = if (!isShort[1] and SellSignal and showSignals) then 1 else 0;
SellSig.AssignValueColor(color.cyan);
SellSig.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
SellSig.SetLineWeight(5);

Alert(SellSig and useAlerts, "Sell Signal",Alert.bar,sound.Ding);
Alert(SellSig and useAlerts, "Sell Signal",Alert.bar,sound.Ding);

# If long and get a BuyStop
Plot BuyStpSig = if (BuyStop and isLong[1] and showSignals and useStops) then 1 else 0;
BuyStpSig.AssignValueColor(color.light_gray);
BuyStpSig.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
BuyStpSig.SetLineWeight(3);

# If short and get a SellStop
Plot SellStpSig = if (SellStop and isShort[1] and showSignals and useStops) then 1 else 0;
SellStpSig.AssignValueColor(color.light_gray);
SellStpSig.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
SellStpSig.SetLineWeight(3);


#######################################
##  Orders
#######################################

def isOrder = if CurrentPosition == CurrentPosition[1] then 0 else 1; # Position changed so it's a new order

# If there is an order, then the price is the next days close
def orderPrice = if (isOrder and (BuySignal or SellSignal)) then close else orderPrice[1];

#######################################
##  Price and Profit
#######################################

def profitLoss;


if (!isOrder or orderPRice[1]==0){
    profitLoss = 0;
} else if ((isOrder and isLong[1]) and (SellSig or BuyStpSig)){
    profitLoss = close - orderPrice[1];
} else if ((isOrder and isShort[1]) and (BuySig or SellStpSig)) {
    profitLoss = orderPrice[1] - close;
} else {
    profitLoss = 0;
}


# Total Profit or Loss
def profitLossSum = compoundValue(1, if isNaN(isOrder)  or barnumber()==1 then 0 else if isOrder then profitLossSum[1] + profitLoss else profitLossSum[1], 0);

# How many trades won or lost
def profitWinners = compoundValue(1, if isNaN(profitWinners[1]) or barnumber()==1 then 0 else if isOrder and profitLoss > 0 then profitWinners[1] + 1 else profitWinners[1], 0);
def profitLosers = compoundValue(1, if isNaN(profitLosers[1])  or barnumber()==1 then 0 else if isOrder and profitLoss < 0 then profitLosers[1] + 1 else profitLosers[1], 0);
def profitPush = compoundValue(1, if isNaN(profitPush[1])  or barnumber()==1 then 0 else if isOrder and profitLoss == 0 then profitPush[1] + 1 else profitPush[1], 0);

def orderCount = (profitWinners + profitLosers + profitPush) - 1;

# Current Open Trade Profit or Loss
def TradePL = If isLong then Round(((close - orderprice)/TickSize())*TickValue()) else if isShort then Round(((orderPrice - close)/TickSize())*TickValue()) else 0;

# Convert to actual dollars based on Tick Value for bubbles
def dollarProfitLoss = if orderPRice[1]==0 or isNaN(orderPrice[1]) then 0 else round((profitLoss/Ticksize())*Tickvalue());

# Closed Orders dollar P/L
def dollarPLSum = round((profitLossSum/Ticksize())*Tickvalue());


# Split profits or losses by long and short trades
def profitLong = compoundValue(1, if isNan(profitLong[1])  or barnumber()==1 then 0 else if isOrder and isLong[1] then profitLong[1]+dollarProfitLoss else profitLong[1],0);
def profitShort = compoundValue(1, if isNan(profitShort[1])  or barnumber()==1 then 0 else if isOrder and isShort[1] then profitShort[1]+dollarProfitLoss else profitShort[1],0);
def countLong = compoundValue(1, if isNaN(countLong[1])  or barnumber()==1 then 0 else if isOrder and isLong[1] then countLong[1]+1 else countLong[1],0);
def countShort = compoundValue(1, if isNaN(countShort[1])  or barnumber()==1 then 0 else if isOrder and isShort[1] then countShort[1]+1 else countShort[1],0);

# What was the biggest winning and losing trade
def biggestWin = compoundValue(1, if isNaN(biggestWin[1]) or barnumber()==1 then 0 else if isOrder and (dollarProfitLoss > 0) and (dollarProfitLoss > biggestWin[1]) then dollarProfitLoss else biggestWin[1], 0);
def biggestLoss = compoundValue(1, if isNaN(biggestLoss[1]) or barnumber()==1 then 0 else if isOrder and (dollarProfitLoss < 0) and (dollarProfitLoss < biggestLoss[1]) then dollarProfitLoss else biggestLoss[1], 0);

# What percent were winners
def PCTWin = round((profitWinners/orderCount)*100,2);


# Average trade
def avgTrade = round((dollarPLSum/orderCount),2);


#######################################
##  Create Labels
#######################################

AddLabel(showLabels, GetSymbol()+" Tick Size: "+TickSize()+" Value: "+TickValue(), color.white);
AddLabel(showLabels, "Closed Orders: " + orderCount + " P/L: " + AsDollars(dollarPLSum), if dollarPLSum > 0 then Color.GREEN else if dollarPLSum< 0 then Color.RED else Color.GRAY);
AddLabel(if !IsNan(orderPrice) and showLabels then 1 else 0, "Closed+Open P/L: "+ AsDollars(TradePL+dollarPLSum), if ((TradePL+dollarPLSum) > 0) then color.green else if ((TradePL+dollarPLSum) < 0) then color.red else color.gray);

AddLabel(showLabels, "Avg per Trade: "+ AsDollars(avgTrade), if avgTrade > 0 then Color.Green else if avgTrade < 0 then Color.RED else Color.GRAY);
AddLabel(showLabels, "Winners: "+ PCTWin +"%",if PCTWin > 50 then color.green else if PCTWin > 40 then color.yellow else color.gray);

AddLabel(showLabels, "MaxUp: "+ AsDollars(biggestWin) +" MaxDown: "+AsDollars(biggestLoss), color.white);
AddLabel(showLabels, "Long Profit: " +AsDollars(profitLong), if profitLong > 0 then color.green else if profitLong < 0 then color.red else color.gray);
AddLabel(showLabels, "Short Profit: " +AsDollars(profitShort), if profitShort > 0 then color.green else if profitShort < 0 then color.red else color.gray);
AddLabel(if !IsNan(CurrentPosition) and showLabels then 1 else 0, "Open: "+ (If isLong then "Bought" else "Sold") + " @ "+orderPrice, color.white);
AddLabel(if !IsNan(orderPrice) and showLabels then 1 else 0, "Open Trade P/L: "+ AsDollars(TradePL), if (TradePL > 0) then color.green else if (TradePl < 0) then color.red else color.gray);



#######################################
##  Chart Bubbles for Profit/Loss
#######################################


AddChartBubble(showSignals and showBubbles and isOrder and isLong[1], low, "$"+dollarProfitLoss, if dollarProfitLoss == 0 then Color.LIGHT_GRAY else if dollarProfitLoss > 0 then Color.GREEN else color.Red, 0);
AddChartBubble(showSignals and showBubbles and isOrder and isShort[1], high,  "$"+dollarProfitLoss, if dollarProfitLoss == 0 then Color.LIGHT_GRAY else if dollarProfitLoss > 0 then Color.GREEN else color.Red, 1);

#AssignPriceColor(if CurrentPosition == 1 then color.green else if CurrentPosition == -1 then color.red else color.gray);

Cy9VkMF.png



and yes, I picked one where it works really well on a daily 1yr. Some aren't so pretty. :)

Here's one that's not as pretty, but not awful either, also a 1yr daily

7xi35KW.png
Is there a scan script for this indicator?
 
For those primarily interested in the HeikenAshi change points, try this:

Code:
# Example of finding HeikenAshi Change Points

def up =
HeikinAshiDiff()[1] > 0 and HeikinAshiDiff() <= 0        # bottom of HeikenAshi moving up
;

def dn =
HeikinAshiDiff()[1] <= 0 and HeikinAshiDiff() > 0       # to of HeikenAshi moving down
;

AddOrder(OrderType.BUY_To_open, up, name = "HAup", tickColor = Color.DARK_RED, arrowColor = Color.DARK_RED);
AddOrder(OrderType.SELL_TO_CLOSE, dn, name = "HAdn", tickColor = Color.DARK_GREEN, arrowColor = Color.DARK_GREEN);
 
Last edited by a moderator:
For those primarily interested in the HeikenAshi change points, try this:

Code:
# Example of finding HeikenAshi Change Points

def up =
HeikinAshiDiff()[1] > 0 and HeikinAshiDiff() <= 0        # bottom of HeikenAshi moving up
;

def dn =
HeikinAshiDiff()[1] <= 0 and HeikinAshiDiff() > 0       # to of HeikenAshi moving down
;

AddOrder(OrderType.BUY_To_open, up, name = "HAup", tickColor = Color.DARK_RED, arrowColor = Color.DARK_RED);
AddOrder(OrderType.SELL_TO_CLOSE, dn, name = "HAdn", tickColor = Color.DARK_GREEN, arrowColor = Color.DARK_GREEN);
How do or where do you incorporate this little code into post #1?
 
So i have been using this indicator in conjunction with other indicators to trade NQ manually as soon as we cross the middle of the heiken ashi candle i jump in with an oco order

Working out pretty well for me

Really wish i can automate my strategy

So far working great on 1600 tick chart on nq with overnight charting on and
20 point take profit and -10 point stop loss

If i could somehow automatically add if im up 10 points, if i could bring up my stop loss to that point or a trailing 5 point stop would be great, and keep the 20 point take profit

Ive seen this on tradovate before but im in no way a genius at coding so enjoying this script fully with my current abilities
http://tos.mx/N4LRwjb
 
Last edited by a moderator:
So i have been using this indicator in conjunction with other indicators to trade NQ manually as soon as we cross the middle of the heiken ashi candle i jump in with an oco order

Working out pretty well for me

Really wish i can automate my strategy

So far working great on 1600 tick chart on nq with overnight charting on and
20 point take profit and -10 point stop loss

If i could somehow automatically add if im up 10 points, if i could bring up my stop loss to that point or a trailing 5 point stop would be great, and keep the 20 point take profit

Ive seen this on tradovate before but im in no way a genius at coding so enjoying this script fully with my current abilities
http://tos.mx/N4LRwjb
To understand this better, you enter when the current HA candle crosses half of the previous HA candle (same trend) ? What else are you looking at on the B4 and any other confirmations?
 
So i have been using this indicator in conjunction with other indicators to trade NQ manually as soon as we cross the middle of the heiken ashi candle i jump in with an oco order

Working out pretty well for me

Really wish i can automate my strategy

So far working great on 1600 tick chart on nq with overnight charting on and
20 point take profit and -10 point stop loss

If i could somehow automatically add if im up 10 points, if i could bring up my stop loss to that point or a trailing 5 point stop would be great, and keep the 20 point take profit

Ive seen this on tradovate before but im in no way a genius at coding so enjoying this script fully with my current abilities
http://tos.mx/N4LRwjb
I had this chart workings this afternoon. But now nothing is (upper and lower indicators).

Also, your upper indicator shows 242 bars to the right. Why such a high number?

ticks are not working, but when I switch to a 1m or 5 minute charts, works great.
 
Last edited:
I had this chart workings this afternoon. But now nothing is (upper and lower indicators).

Also, your upper indicator shows 242 bars to the right. Why such a high number?

ticks are not working, but when I switch to a 1m or 5 minute charts, works great.
Well, I think I have the answer, Change the 256 ticks on right to 25 and everything appears.
 
Fellow ThinkScripters... I am seeking assistance to develop a SCAN that locates stocks that have the light blue "down" arrow within one period. If you pull up the shared program you will see the light blue arrows for the Long & Short cross-overs. This was a shared program from this forum.
https://usethinkscript.com/threads/...th-atr-trail-for-thinkorswim.9992/#post-89555

Also this request will be for a SHORT scan.
http://tos.mx/ewn9sj0

Here is the LONG scan version which is super and shows the long buy points "light blue arrows up" but I'm having difficultly to reverse it correctly for locating down arrows. It might be rather simple but I have not been able to figure it out.
http://tos.mx/SdbwoLP
I attached a screen shot that shows the Light Blue cross-over arrows.
Any support is appreciated!:D

1688089336463.png

Ruby:
#hint: Smoothed Heiken Ashi and ATR studies

input period = 20;
input hideCandles = no;
input candleSmoothing = {default Valcu, Vervoort};

input movingAverageType = {Simple, default Exponential, Weighted, Hull, Variable, TEMA};

def openMA;
def closeMA;
def highMA;
def lowMA;

switch (movingAverageType) {
case Simple:
    openMA = CompoundValue(1, Average(open, period), open);
    closeMA = CompoundValue(1, Average(close, period), close);
    highMA = CompoundValue(1, Average(high, period), high);
    lowMA = CompoundValue(1, Average(low, period), low);
case Exponential:
    openMA = CompoundValue(1, ExpAverage(open, period), open);
    closeMA = CompoundValue(1, ExpAverage(close, period), close);
    highMA = CompoundValue(1, ExpAverage(high, period), high);
    lowMA = CompoundValue(1, ExpAverage(low, period), low);
case Weighted:
    openMA = CompoundValue(1, WMA(open, period), open);
    closeMA = CompoundValue(1, WMA(close, period), close);
    highMA = CompoundValue(1, WMA(high, period), high);
    lowMA = CompoundValue(1, WMA(low, period), low);
case Hull:
    openMA = CompoundValue(1, HullMovingAvg(open, period), open);
    closeMA = CompoundValue(1, HullMovingAvg(close, period), close);
    highMA = CompoundValue(1, HullMovingAvg(high, period), high);
    lowMA = CompoundValue(1, HullMovingAvg(low, period), low);
case Variable:
    openMA = CompoundValue(1, VariableMA(open, period), open);
    closeMA = CompoundValue(1, VariableMA(close, period), close);
    highMA = CompoundValue(1, VariableMA(high, period), high);
    lowMA = CompoundValue(1, VariableMA(low, period), low);
case TEMA:
    openMA = CompoundValue(1, TEMA(open, period), open);
    closeMA = CompoundValue(1, TEMA(close, period), close);
    highMA = CompoundValue(1, TEMA(high, period), high);
    lowMA = CompoundValue(1, TEMA(low, period), low);
}

HidePricePlot(hideCandles);

def haOpen;
def haClose;

switch (candleSmoothing) {
case Valcu:
    haOpen = CompoundValue(1, ( (haOpen[1] + (openMA[1] + highMA[1] + lowMA[1] + closeMA[1]) / 4.0) / 2.0), open);
    haClose = ((openMA + highMA + lowMA + closeMA) / 4.0) ;
case Vervoort:
    haOpen = CompoundValue(1, ( (haOpen[1] + (openMA[1] + highMA[1] + lowMA[1] + closeMA[1]) / 4.0) / 2.0), open);
    haClose = ((((openMA + highMA + lowMA + closeMA) / 4.0) + haOpen + Max(highMA, haOpen) + Min(lowMA, haOpen)) / 4.0);
}

plot o = haOpen + 0;
o.Hide();

### Wicks and Shadows

def haLow = Min(lowMA, haOpen);
def haHigh = Max(highMA, haOpen);


#Red Candlesticks -----------------------------------------------------------------|

def haOpen_fall = if haOpen > haClose
              then haOpen
              else Double.NaN;
def haHigh_fall   = if haOpen >= haClose
              then haHigh
              else Double.NaN;
def haLow_fall    = if haOpen >= haClose
              then haLow
              else Double.NaN;
def haClose_fall    = if haOpen >= haClose
              then haClose
              else Double.NaN;

AddChart(growColor = Color.PLUM, fallColor = Color.BLUE, neutralColor = Color.CURRENT, high = haHigh_fall, low = haLow_fall, open = haOpen_fall, close = haClose_fall , type = ChartType.CANDLE);


def haOpen_rise = if haOpen < haClose
                then haClose
                else Double.NaN;
def haHigh_rise  = if haOpen <= haClose
              then haHigh
              else Double.NaN;
def haLow_rise   = if haOpen <= haClose
              then haLow
              else Double.NaN;
def haClose_rise   = if haOpen <= haClose
              then haOpen
              else Double.NaN;

AddChart(growColor = Color.BLUE, fallColor = Color.PLUM, neutralColor = Color.CURRENT, high = haHigh_rise, low = haLow_rise, open = haOpen_rise, close = haClose_rise, type = ChartType.CANDLE);

#############################################################################

#############################################################
###   Determine a flat market
#############################################################


input TradeInFlatRange = Yes;
input BarsForFlatRange = 4;
input BarsReqToStayInRange = 8;

def HH = Highest(high[1], BarsForFlatRange);
def LL = Lowest(low[1], BarsForFlatRange);
def maxH = Highest(HH, BarsReqToStayInRange);
def maxL = Lowest(LL, BarsReqToStayInRange);
def HHn = if maxH == maxH[1] or maxL == maxL then maxH else HHn[1];
def LLn = if maxH == maxH[1] or maxL == maxL then maxL else LLn[1];
def Bh = if high <= HHn and HHn == HHn[1] then HHn else Double.NaN;
def Bl = if low >= LLn and LLn == LLn[1] then LLn else Double.NaN;
def CountH = if IsNaN(Bh) or IsNaN(Bl) then 2 else CountH[1] + 1;
def CountL = if IsNaN(Bh) or IsNaN(Bl) then 2 else CountL[1] + 1;
def ExpH = if BarNumber() == 1 then Double.NaN else
            if CountH[-BarsReqToStayInRange] >= BarsReqToStayInRange then HHn[-BarsReqToStayInRange] else
            if high <= ExpH[1] then ExpH[1] else Double.NaN;
def ExpL = if BarNumber() == 1 then Double.NaN else
            if CountL[-BarsReqToStayInRange] >= BarsReqToStayInRange then LLn[-BarsReqToStayInRange] else
            if low >= ExpL[1] then ExpL[1] else Double.NaN;

def BoxHigh = if !IsNaN(ExpL) and !IsNaN(ExpH) then ExpH else Double.NaN;
def BoxLow = if !IsNaN(ExpL) and !IsNaN(ExpH) then ExpL else Double.NaN;


AddCloud( BoxHigh, BoxLow, Color.GRAY, Color.GRAY);


def Flat = if (!IsNaN(BoxHigh[1]) and !IsNaN(BoxLow[1])) and !TradeInFlatRange then 1 else 0;

#addChartBubble(Flat==1 and isNan(Flat[1]),BoxHigh[1],"Flat Market",color.gray,yes);

input trailType = {default modified, unmodified};
input ATRPeriod = 7;
input ATRFactor = 2.5;
input firstTrade = {default long, short};
input averageType = AverageType.WILDERS;

Assert(ATRFactor > 0, "'atr factor' must be positive: " + ATRFactor);

def HiLo = Min(high - low, 1.5 * Average(high - low, ATRPeriod));
def HRef = if low <= high[1]
    then high - close[1]
    else (high - close[1]) - 0.5 * (low - high[1]);
def LRef = if high >= low[1]
    then close[1] - low
    else (close[1] - low) - 0.5 * (low[1] - high);

def trueRange;
switch (trailType) {
case modified:
    trueRange = Max(HiLo, Max(HRef, LRef));
case unmodified:
    trueRange = TrueRange(high, close, low);
}
def loss = ATRFactor * MovingAverage(averageType, trueRange, ATRPeriod);

def state = {default init, long, short};
def trail;
switch (state[1]) {
case init:
    if (!IsNaN(loss)) {
        switch (firstTrade) {
        case long:
            state = state.long;
            trail =  close - loss;
        case short:
            state = state.short;
            trail = close + loss;
    }
    } else {
        state = state.init;
        trail = Double.NaN;
    }
case long:
    if (close > trail[1]) {
        state = state.long;
        trail = Max(trail[1], close - loss);
    } else {
        state = state.short;
        trail = close + loss;
    }
case short:
    if (close < trail[1]) {
        state = state.short;
        trail = Min(trail[1], close + loss);
    } else {
        state = state.long;
        trail =  close - loss;
    }
}

#def BuySignal = Crosses(state == state.long, 0, CrossingDirection.ABOVE);
#def SellSignal = Crosses(state == state.short, 0, CrossingDirection.ABOVE);

plot TrailingStop = trail;

TrailingStop.SetPaintingStrategy(PaintingStrategy.LINE);
TrailingStop.DefineColor("Buy", Color.BLUE);
TrailingStop.DefineColor("Sell", Color.PLUM);
TrailingStop.AssignValueColor(if state == state.long
    then TrailingStop.Color("Buy")
    else TrailingStop.Color("Sell"));



#hint Add trade profit and loss to a study. Displayed as labels
###------------------------------------------------------------------------------------------
# Fill in the 0>0 in the Create Signals section below to match
# your buy and sell signal conditions
# When using large amounts of hisorical data, P/L may take time to calculate
###------------------------------------------------------------------------------------------
input showSignals = yes; #hint showSignals: show buy and sell arrows
input LongTrades = yes;
input ShortTrades = yes;
input showLabels  = yes; #hint showLabels: show PL labels at top
input showBubbles = yes; #hint showBubbles: show PL bubbles at close of trade
input useStops = no;     #hint useStops: use stop orders
input useAlerts = no;    #hint useAlerts: use alerts on signals
input tradeDaytimeOnly = no; #hint tradeDaytimeOnly: (IntraDay Only) Only perform trades during hours stated
input OpenTime = 0930; #hint OpenTime: Opening time of market
input CloseTime = 1600; #hint CloseTime: Closing time of market


def Begin = secondsfromTime(OpenTime);
def End = secondsTillTime(CloseTime);
# Only use market hours when using intraday timeframe
def isIntraDay = if getaggregationperiod() > 14400000 or getaggregationperiod()==0 then 0 else 1;
def MarketOpen = if !tradeDaytimeOnly or !isIntraDay then 1 else if tradeDaytimeOnly and isIntraDay and Begin > 0 and End > 0 then 1 else 0;
###------------------------------------------------------------------------------------------

######################################################
##  Create Signals -
##  FILL IN THIS SECTION
##      replace 0>0 with your conditions for signals
######################################################

def PLBuySignal = if  MarketOpen AND ( state == state.long and (haOpen < haClose) and (haOpen[1] < haClose[1]) and !Flat) then 1 else 0 ; # insert condition to create long position in place of the 0>0
def PLSellSignal =  if MarketOpen AND (state == state.short and (haOpen > haClose)  and (haOpen[1] > haClose[1]) and !Flat) then 1 else 0; # insert condition to create short position in place of the 0>0

def PLBuyStop  = if !useStops then 0 else if (state == state.long and (haOpen > haClose) and (haOpen[1] > haClose[1])) then 1 else 0  ; # insert condition to stop in place of the 0<0
def PLSellStop = if !useStops then 0 else if ( state == state.short and (haOpen < haClose))then 1 else 0  ; # insert condition to stop in place of the 0>0

def PLMktStop = if MarketOpen[-1] == 0 then 1 else 0; # If tradeDaytimeOnly is set, then stop at end of day

#######################################
##  Maintain the position of trades
#######################################

def CurrentPosition;  # holds whether flat = 0 long = 1 short = -1

if (BarNumber()==1) OR isNaN(CurrentPosition[1]) {
    CurrentPosition = 0;
}else{
        if CurrentPosition[1] == 0 {            # FLAT
            if (PLBuySignal AND LongTrades) {
                CurrentPosition = 1;
            } else if (PLSellSignal AND ShortTrades){
                CurrentPosition = -1;
            } else {
                CurrentPosition = CurrentPosition[1];
            }
       } else if CurrentPosition[1] == 1 {      # LONG
            if (PLSellSignal AND ShortTrades){
                CurrentPosition = -1;
            } else if ((PLBuyStop and useStops) or PLMktStop or (PLSellSignal AND ShortTrades==0)){
                CurrentPosition = 0;
            } else {
                CurrentPosition = CurrentPosition[1];
            }
       } else if CurrentPosition[1] == -1 {     # SHORT
            if (PLBuySignal AND LongTrades){
                CurrentPosition = 1;
            } else if ((PLSellStop and useStops) or PLMktStop or (PlBuySignal and LongTrades==0)){
                CurrentPosition = 0;
            } else {
                CurrentPosition = CurrentPosition[1];
            }
       } else {
            CurrentPosition = CurrentPosition[1];
       }
}


def isLong  = if CurrentPosition == 1 then 1 else 0;
def isShort = if CurrentPosition == -1 then 1 else 0;
def isFlat  = if CurrentPosition == 0 then 1 else 0;

# If not already long and get a PLBuySignal
#Plot BuySig = if (!isLong[1] and PLBuySignal and showSignals and LongTrades) then 1 else 0;
Plot BuySig = if (((isShort[1] and LongTrades) or (isFlat[1] and LongTrades)) and PLBuySignal and showSignals) then 1 else 0;
BuySig.AssignValueColor(color.cyan);
BuySig.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
BuySig.SetLineWeight(5);

Alert(BuySig and useAlerts, "Buy Signal",Alert.bar,sound.Ding);
Alert(BuySig and useAlerts, "Buy Signal",Alert.bar,sound.Ding);

# If not already short and get a PLSellSignal
Plot SellSig = if (((isLong[1] and ShortTrades) or (isFlat[1] and ShortTrades)) and PLSellSignal and showSignals) then 1 else 0;
SellSig.AssignValueColor(color.cyan);
SellSig.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
SellSig.SetLineWeight(5);

Alert(SellSig and useAlerts, "Sell Signal",Alert.bar,sound.Ding);
Alert(SellSig and useAlerts, "Sell Signal",Alert.bar,sound.Ding);

# If long and get a PLBuyStop
Plot BuyStpSig = if (PLBuyStop and isLong[1] and showSignals and useStops) or (isLong[1] and PLMktStop) or (isLong[1] and PLSellSignal and !ShortTrades) then 1 else 0;
BuyStpSig.AssignValueColor(color.light_gray);
BuyStpSig.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
BuyStpSig.SetLineWeight(3);

Alert(BuyStpSig and useAlerts, "Buy Stop Signal",Alert.bar,sound.Ding);
Alert(BuyStpSig and useAlerts, "Buy Stop Signal",Alert.bar,sound.Ding);


# If short and get a PLSellStop
Plot SellStpSig = if (PLSellStop and isShort[1] and showSignals and useStops) or (isShort[1] and PLMktStop) or (isShort[1] and PLBuySignal and !LongTrades) then 1 else 0;
SellStpSig.AssignValueColor(color.light_gray);
SellStpSig.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
SellStpSig.SetLineWeight(3);

Alert(SellStpSig and useAlerts, "Sell Stop Signal",Alert.bar,sound.Ding);
Alert(SellStpSig and useAlerts, "Sell Stop Signal",Alert.bar,sound.Ding);


#######################################
##  Orders
#######################################

def isOrder = if ((isFlat[1] and (BuySig and LongTrades) or (SellSig and ShortTrades)) or (isLong[1] and BuyStpSig or (SellSig and ShortTrades)) or (isShort[1] and SellStpSig or (BuySig and LongTrades))) then 1 else 0 ;
# If there is an order, then the price is the next days close
def orderPrice = if (isOrder and ((BuySig and LongTrades) or (SellSig and ShortTrades))) then close else orderPrice[1];

def orderCount = compoundValue(1,if isNan(isOrder) or barnumber()==1 then 0 else if (BuySig or SellSig) then orderCount[1]+1 else orderCount[1],0);


#######################################
##  Price and Profit
#######################################

def profitLoss;


if (!isOrder or orderPRice[1]==0){
    profitLoss = 0;
} else if ((isOrder and isLong[1]) and (SellSig or BuyStpSig)){
    profitLoss = close - orderPrice[1];
} else if ((isOrder and isShort[1]) and (BuySig or SellStpSig)) {
    profitLoss = orderPrice[1] - close;
} else {
    profitLoss = 0;
}


# Total Profit or Loss
def profitLossSum = compoundValue(1, if isNaN(isOrder)  or barnumber()==1 then 0 else if isOrder then profitLossSum[1] + profitLoss else profitLossSum[1], 0);

# How many trades won or lost
def profitWinners = compoundValue(1, if isNaN(profitWinners[1]) or barnumber()==1 then 0 else if isOrder and profitLoss > 0 then profitWinners[1] + 1 else profitWinners[1], 0);
def profitLosers = compoundValue(1, if isNaN(profitLosers[1])  or barnumber()==1 then 0 else if isOrder and profitLoss < 0 then profitLosers[1] + 1 else profitLosers[1], 0);
def profitPush = compoundValue(1, if isNaN(profitPush[1])  or barnumber()==1 then 0 else if isOrder and profitLoss == 0 then profitPush[1] + 1 else profitPush[1], 0);

# Current Open Trade Profit or Loss
def TradePL = If isLong then Round(((close - orderprice)/TickSize())*TickValue()) else if isShort then Round(((orderPrice - close)/TickSize())*TickValue()) else 0;

# Convert to actual dollars based on Tick Value for bubbles
def dollarProfitLoss = if orderPRice[1]==0 or isNaN(orderPrice[1]) then 0 else round((profitLoss/Ticksize())*Tickvalue());

# Closed Orders dollar P/L
def dollarPLSum = round((profitLossSum/Ticksize())*Tickvalue());


# Split profits or losses by long and short trades
def profitLong = compoundValue(1, if isNan(profitLong[1])  or barnumber()==1 then 0 else if isOrder and isLong[1] then profitLong[1]+dollarProfitLoss else profitLong[1],0);
def profitShort = compoundValue(1, if isNan(profitShort[1])  or barnumber()==1 then 0 else if isOrder and isShort[1] then profitShort[1]+dollarProfitLoss else profitShort[1],0);
def countLong = compoundValue(1, if isNaN(countLong[1])  or barnumber()==1 then 0 else if isOrder and isLong[1] then countLong[1]+1 else countLong[1],0);
def countShort = compoundValue(1, if isNaN(countShort[1])  or barnumber()==1 then 0 else if isOrder and isShort[1] then countShort[1]+1 else countShort[1],0);

# What was the biggest winning and losing trade
def biggestWin = compoundValue(1, if isNaN(biggestWin[1]) or barnumber()==1 then 0 else if isOrder and (dollarProfitLoss > 0) and (dollarProfitLoss > biggestWin[1]) then dollarProfitLoss else biggestWin[1], 0);
def biggestLoss = compoundValue(1, if isNaN(biggestLoss[1]) or barnumber()==1 then 0 else if isOrder and (dollarProfitLoss < 0) and (dollarProfitLoss < biggestLoss[1]) then dollarProfitLoss else biggestLoss[1], 0);

def ClosedTradeCount = if (isLong or isShort) then orderCount-1 else orderCount;
def OpenTrades = if (isLong or isShort) then 1 else 0;


# What percent were winners
def PCTWin = if (OpenTrades and (TradePL < 0)) then round((profitWinners/(ClosedTradeCount+1))*100,2)
else if (OpenTrades and (TradePL > 0)) then round(((profitWinners+1)/(ClosedTradeCount+1))*100,2) else round(((profitWinners)/(ClosedTradeCount))*100,2) ;


# Average trade
def avgTrade = if (OpenTrades and (TradePL < 0)) then round(((dollarPLSum - TradePL)/(ClosedTradeCount+1)),2)
else if (OpenTrades and (TradePL > 0)) then round(((dollarPLSum + TradePL)/(ClosedTradeCount+1)),2) else round(((dollarPLSum)/(ClosedTradeCount)),2) ;

#######################################
##  Create Labels
#######################################


AddLabel(showLabels and isIntraDay, if MarketOpen then "Market Open" else "Market Closed", color.gray);
AddLabel(showLabels, GetSymbol()+" Tick Size: "+TickSize()+" Value: "+TickValue(), color.gray);
AddLabel(showLabels and (LongTrades and ShortTrades), "Long+Short Trades", color.gray);
AddLabel(showLabels and (LongTrades and !ShortTrades),"Long Trades Only", color.gray);
AddLabel(showLabels and (!LongTrades and ShortTrades),"Short Trades Only", color.gray);
AddLabel(showLabels, "Closed Orders: " + ClosedTradeCount + " P/L: " + AsDollars(dollarPLSum), if dollarPLSum > 0 then Color.dark_GREEN else if dollarPLSum< 0 then Color.RED else Color.GRAY);
AddLabel(if !IsNan(orderPrice) and showLabels then 1 else 0, "Closed+Open P/L: "+ AsDollars(TradePL+dollarPLSum), if ((TradePL+dollarPLSum) > 0) then color.dark_GREEN else if ((TradePL+dollarPLSum) < 0) then color.red else color.gray);

AddLabel(showLabels, "Avg per Trade: "+ AsDollars(avgTrade), if avgTrade > 0 then Color.dark_Green else if avgTrade < 0 then Color.RED else Color.GRAY);
AddLabel(showLabels, "Winners: "+ PCTWin +"%",if PCTWin > 50 then color.dark_green else if PCTWin > 40 then color.plum else color.gray);

AddLabel(showLabels, "MaxUp: "+ AsDollars(biggestWin) +" MaxDown: "+AsDollars(biggestLoss), color.gray);
AddLabel(showLabels, "Long Profit: " +AsDollars(profitLong), if profitLong > 0 then color.dark_green else if profitLong < 0 then color.red else color.gray);
AddLabel(showLabels, "Short Profit: " +AsDollars(profitShort), if profitShort > 0 then color.dark_green else if profitShort < 0 then color.red else color.gray);
AddLabel(if !IsNan(CurrentPosition) and showLabels and OpenTrades then 1 else 0, "Open: "+ (If isLong then "Bought" else "Sold") + " @ "+orderPrice, color.gray);
AddLabel(if !IsNan(orderPrice) and showLabels and OpenTrades then 1 else 0, "Open Trade P/L: "+ AsDollars(TradePL), if (TradePL > 0) then color.dark_green else if (TradePl < 0) then color.red else color.gray);



#######################################
##  Chart Bubbles for Profit/Loss
#######################################


AddChartBubble(showSignals and showBubbles and isOrder and isLong[1], low, "$"+dollarProfitLoss, if dollarProfitLoss == 0 then Color.LIGHT_GRAY else if dollarProfitLoss > 0 then Color.GREEN else color.Red, 0);
AddChartBubble(showSignals and showBubbles and isOrder and isShort[1], high,  "$"+dollarProfitLoss, if dollarProfitLoss == 0 then Color.LIGHT_GRAY else if dollarProfitLoss > 0 then Color.GREEN else color.Red, 1);

#AssignPriceColor(if CurrentPosition == 1 then color.green else if CurrentPosition == -1 then color.red else color.gray);
 
Last edited by a moderator:
This is what I use, but I'm sure it can be modified and played around with to fit whatever your style is. http://tos.mx/btKEKXw
Hi Joe,

Can you share the code this scanner. This only Long Scanner but not modifiable due SHAScanner() not avaliable . Can you share the code please. I need to modify for long & Short with one bar range and ATR Values.. Thanks in advance.
 
Hi Joe,

Can you share the code this scanner. This only Long Scanner but not modifiable due SHAScanner() not avaliable . Can you share the code please. I need to modify for long & Short with one bar range and ATR Values.. Thanks in advance.
This is what I use, but I'm sure it can be modified and played around with to fit whatever your style is. http://tos.mx/btKEKXw
Hi Joe,
can you help to get long and shot scan for this indicator. unable to get SHAScanner
 
Smoothed Heikin-Ashi with ATR Trail + P/L (Study)
I put this in Strategies since it's a study that has the P/L built in. It's a combination of things I've found on here over the years (so if you were the original author, just let me know and I'll give credit). It combines a smoothed Heikin-Ashi with an ATR Trail to come up with the buy/sell signals. Not saying it works well or not, just putting it here if someone wants to play around with it. I swing trade so have really only looked at it on a daily timeframe. I'm guessing it would be too slow for day-trading, though you might be able to tweak the settings to make it work.



Ruby:
#hint: Smoothed Heiken Ashi and ATR studies

input period = 20;
input hideCandles = no;
input candleSmoothing = {default Valcu, Vervoort};

input movingAverageType = {Simple, default Exponential, Weighted, Hull, Variable, TEMA};

def openMA;
def closeMA;
def highMA;
def lowMA;

switch (movingAverageType) {
case Simple:
    openMA = compoundValue(1, Average(open, period), open);
    closeMA = compoundValue(1, Average(close, period), close);
    highMA = compoundValue(1, Average(high, period), high);
    lowMA = compoundValue(1, Average(low, period), low);
case Exponential:
    openMA = compoundValue(1, ExpAverage(open, period), open);
    closeMA = compoundValue(1, ExpAverage(close, period), close);
    highMA = compoundValue(1, ExpAverage(high, period), high);
    lowMA = compoundValue(1, ExpAverage(low, period), low);
case Weighted:
    openMA = compoundValue(1, WMA(open, period), open);
    closeMA = compoundValue(1, WMA(close, period), close);
    highMA = compoundValue(1, WMA(high, period), high);
    lowMA = compoundValue(1, WMA(low, period), low);
Case Hull:
    openMA = compoundValue(1, HullMovingAvg(open, period), open);
    closeMA = compoundValue(1, HullMovingAvg(close, period), close);
    highMA = compoundValue(1, HullMovingAvg(high, period), high);
    lowMA = compoundValue(1, HullMovingAvg(low, period), low);
case variable:
    openMA = compoundValue(1, VariableMA(open, period), open);
    closeMA = compoundValue(1, VariableMA(close, period), close);
    highMA = compoundValue(1, VariableMA(high, period), high);
    lowMA = compoundValue(1, VariableMA(low, period), low);
case TEMA:
    openMA = compoundValue(1, TEMA(open, period), open);
    closeMA = compoundValue(1, TEMA(close, period), close);
    highMA = compoundValue(1, TEMA(high, period), high);
    lowMA = compoundValue(1, TEMA(low, period), low);
}

hidePricePlot(hideCandles);

def haOpen;
def haClose;

switch(candleSmoothing) {
case Valcu:
    haOpen = CompoundValue(1, ( (haOpen[1] + (openMA[1] + highMA[1] + lowMA[1] + closeMA[1]) /4.0)/2.0), open);
    haClose = ((OpenMA + HighMA + LowMA + CloseMA)/4.0) ;

case Vervoort:
    haOpen = CompoundValue(1, ( (haOpen[1] + (openMA[1] + highMA[1] + lowMA[1] + closeMA[1]) /4.0)/2.0), open);
    haClose = ((((OpenMA + HighMA + LowMA + CloseMA)/4.0) + haOpen + Max(HighMA, haOpen) + Min(LowMA, haOpen))/4.0);
}

plot o = haOpen + 0;
o.hide();

### Wicks and Shadows

def haLow = min(lowMA, haOpen);
def haHigh = max(highMA,haOpen);


#Red Candlesticks -----------------------------------------------------------------|

def haOpen_fall = if haOpen>haClose
              then haOpen
              else double.nan;
def haHigh_fall   = if haOpen>=haClose
              then haHigh
              else double.nan;
def haLow_fall    = if haOpen>=haClose
              then haLow
              else double.nan;
def haClose_fall    = if haOpen>=haClose
              then haClose
              else double.nan;

AddChart(growColor = Color.plum, fallColor = Color.blue, neutralColor = Color.current, high = haHigh_fall, low = haLow_fall, open = haOpen_fall, close = haClose_fall , type = ChartType.CANDLE);


def haOpen_rise = if haOpen<haClose
                then haClose
                else double.nan;
def haHigh_rise  = if haOpen<=haClose
              then haHigh
              else double.nan;
def haLow_rise   = if haOpen<=haClose
              then haLow
              else double.nan;
def haClose_rise   = if haOpen<=haClose
              then haOpen
              else double.nan;

AddChart(growColor = Color.blue, fallColor = Color.plum, neutralColor = Color.current, high = haHigh_rise, low = haLow_rise, open = haOpen_rise, close = HAclose_rise, type = ChartType.CANDLE);

#############################################################################

#############################################################
###   Determine a flat market
#############################################################


input TradeInFlatRange = Yes;
input BarsForFlatRange = 15;
input BarsReqToStayInRange = 13;

def HH = Highest(high[1], BarsForFlatRange);
def LL = Lowest(low[1], BarsForFlatRange);
def maxH = Highest(HH, BarsReqToStayInRange);
def maxL = Lowest(LL, BarsReqToStayInRange);
def HHn = if maxH == maxH[1] or maxL == maxL then maxH else HHn[1];
def LLn = if maxH == maxH[1] or maxL == maxL then maxL else LLn[1];
def Bh = if high <= HHn and HHn == HHn[1] then HHn else Double.NaN;
def Bl = if low >= LLn and LLn == LLn[1] then LLn else Double.NaN;
def CountH = if IsNaN(Bh) or IsNaN(Bl) then 2 else CountH[1] + 1;
def CountL = if IsNaN(Bh) or IsNaN(Bl) then 2 else CountL[1] + 1;
def ExpH = if BarNumber() == 1 then Double.NaN else
            if CountH[-BarsReqToStayInRange] >= BarsReqToStayInRange then HHn[-BarsReqToStayInRange] else
            if high <= ExpH[1] then ExpH[1] else Double.NaN;
def ExpL = if BarNumber() == 1 then Double.NaN else
            if CountL[-BarsReqToStayInRange] >= BarsReqToStayInRange then LLn[-BarsReqToStayInRange] else
            if low >= ExpL[1] then ExpL[1] else Double.NaN;

plot BoxHigh = if !isnan(expL) and !isnan(ExpH) then ExpH else double.nan;
plot BoxLow = if !isnan(expL) and !isnan(ExpH) then ExpL else double.nan;


addcloud( BoxHigh, BoxLow, color.gray, color.gray);


def Flat = if (!isNan(BoxHigh[1]) and !isNan(BoxLow[1])) AND !TradeInFlatRange then 1 else 0;

#addChartBubble(Flat==1 and isNan(Flat[1]),BoxHigh[1],"Flat Market",color.gray,yes);

input trailType = {default modified, unmodified};
input ATRPeriod = 5;
input ATRFactor = 3.0;
input firstTrade = {default long, short};
input averageType = AverageType.WILDERS;

Assert(ATRFactor > 0, "'atr factor' must be positive: " + ATRFactor);

def HiLo = Min(high - low, 1.5 * Average(high - low, ATRPeriod));
def HRef = if low <= high[1]
    then high - close[1]
    else (high - close[1]) - 0.5 * (low - high[1]);
def LRef = if high >= low[1]
    then close[1] - low
    else (close[1] - low) - 0.5 * (low[1] - high);

def trueRange;
switch (trailType) {
case modified:
    trueRange = Max(HiLo, Max(HRef, LRef));
case unmodified:
    trueRange = TrueRange(high, close, low);
}
def loss = ATRFactor * MovingAverage(averageType, trueRange, ATRPeriod);

def state = {default init, long, short};
def trail;
switch (state[1]) {
case init:
    if (!IsNaN(loss)) {
        switch (firstTrade) {
        case long:
            state = state.long;
            trail =  close - loss;
        case short:
            state = state.short;
            trail = close + loss;
        }
    } else {
        state = state.init;
        trail = Double.NaN;
    }
case long:
    if (close > trail[1]) {
        state = state.long;
        trail = Max(trail[1], close - loss);
    } else {
        state = state.short;
        trail = close + loss;
    }
case short:
    if (close < trail[1]) {
        state = state.short;
        trail = Min(trail[1], close + loss);
    } else {
        state = state.long;
        trail =  close - loss;
    }
}

#def BuySignal = Crosses(state == state.long, 0, CrossingDirection.ABOVE);
#def SellSignal = Crosses(state == state.short, 0, CrossingDirection.ABOVE);

plot TrailingStop = trail;

TrailingStop.SetPaintingStrategy(PaintingStrategy.line);
TrailingStop.DefineColor("Buy", color.blue);
TrailingStop.DefineColor("Sell", color.plum);
TrailingStop.AssignValueColor(if state == state.long
    then TrailingStop.Color("Buy")
    else TrailingStop.Color("Sell"));


############################################
##  Define BuySignal and SellSignal above
##  or uncomment them out below and set
##  them to your buy/sell conditions
##
##  If using stops, define them below
############################################

###------------------------------------------------------------------------------------------

input showSignals = yes;
input showLabels  = yes;
input showBubbles = yes;
input useStops = no;
input useAlerts = no;

###------------------------------------------------------------------------------------------

############################################
##  Create Signals -
##  FILL IN THIS SECTION IF NOT DEFINED ABOVE
##
############################################


def BuySignal = state == state.long AND (haOpen < haClose) and (haOpen[1] < haClose[1]) and !Flat ; # insert condition to create long position
def SellSignal = state == state.short AND (haOpen > haClose)  and (haOpen[1] > haClose[1]) and !Flat; # insert condition to create short position

def BuyStop  = if !useStops then 0 else if  state == state.long AND (haOpen > haClose) and Flat then 1 else 0  ; # insert condition to stop in place of the 0<0
def SellStop = if !useStops then 0 else if  state == state.short AND (haOpen < haClose) and Flat then 1 else 0  ; # insert condition to stop in place of the 0>0

#######################################
##  Maintain the position of trades
#######################################

def CurrentPosition;  # holds whether flat = 0 long = 1 short = -1

if (BarNumber()==1) OR isNaN(CurrentPosition[1]) {
    CurrentPosition = 0;
}else{
        if CurrentPosition[1] == 0 {            # FLAT
            if (BuySignal) {
                CurrentPosition = 1;
            } else if (SellSignal){
                CurrentPosition = -1;
            } else {
                CurrentPosition = CurrentPosition[1];
            }
       } else if CurrentPosition[1] == 1 {      # LONG
            if (SellSignal){
                CurrentPosition = -1;
            } else if (BuyStop and useStops){
                CurrentPosition = 0;
            } else {
                CurrentPosition = CurrentPosition[1];
            }
       } else if CurrentPosition[1] == -1 {     # SHORT
            if (BuySignal){
                CurrentPosition = 1;
            } else if (SellStop and useStops){
                CurrentPosition = 0;
            } else {
                CurrentPosition = CurrentPosition[1];
            }
       } else {
            CurrentPosition = CurrentPosition[1];
       }
}


def isLong  = if CurrentPosition == 1 then 1 else 0;
def isShort = if CurrentPosition == -1 then 1 else 0;
def isFlat  = if CurrentPosition == 0 then 1 else 0;

# If not already long and get a BuySignal
Plot BuySig = if (!isLong[1] and BuySignal and showSignals) then 1 else 0;
BuySig.AssignValueColor(color.cyan);
BuySig.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
BuySig.SetLineWeight(5);

Alert(BuySig and useAlerts, "Buy Signal",Alert.bar,sound.Ding);
Alert(BuySig and useAlerts, "Buy Signal",Alert.bar,sound.Ding);

# If not already short and get a SellSignal
Plot SellSig = if (!isShort[1] and SellSignal and showSignals) then 1 else 0;
SellSig.AssignValueColor(color.cyan);
SellSig.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
SellSig.SetLineWeight(5);

Alert(SellSig and useAlerts, "Sell Signal",Alert.bar,sound.Ding);
Alert(SellSig and useAlerts, "Sell Signal",Alert.bar,sound.Ding);

# If long and get a BuyStop
Plot BuyStpSig = if (BuyStop and isLong[1] and showSignals and useStops) then 1 else 0;
BuyStpSig.AssignValueColor(color.light_gray);
BuyStpSig.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
BuyStpSig.SetLineWeight(3);

# If short and get a SellStop
Plot SellStpSig = if (SellStop and isShort[1] and showSignals and useStops) then 1 else 0;
SellStpSig.AssignValueColor(color.light_gray);
SellStpSig.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
SellStpSig.SetLineWeight(3);


#######################################
##  Orders
#######################################

def isOrder = if CurrentPosition == CurrentPosition[1] then 0 else 1; # Position changed so it's a new order

# If there is an order, then the price is the next days close
def orderPrice = if (isOrder and (BuySignal or SellSignal)) then close else orderPrice[1];

#######################################
##  Price and Profit
#######################################

def profitLoss;


if (!isOrder or orderPRice[1]==0){
    profitLoss = 0;
} else if ((isOrder and isLong[1]) and (SellSig or BuyStpSig)){
    profitLoss = close - orderPrice[1];
} else if ((isOrder and isShort[1]) and (BuySig or SellStpSig)) {
    profitLoss = orderPrice[1] - close;
} else {
    profitLoss = 0;
}


# Total Profit or Loss
def profitLossSum = compoundValue(1, if isNaN(isOrder)  or barnumber()==1 then 0 else if isOrder then profitLossSum[1] + profitLoss else profitLossSum[1], 0);

# How many trades won or lost
def profitWinners = compoundValue(1, if isNaN(profitWinners[1]) or barnumber()==1 then 0 else if isOrder and profitLoss > 0 then profitWinners[1] + 1 else profitWinners[1], 0);
def profitLosers = compoundValue(1, if isNaN(profitLosers[1])  or barnumber()==1 then 0 else if isOrder and profitLoss < 0 then profitLosers[1] + 1 else profitLosers[1], 0);
def profitPush = compoundValue(1, if isNaN(profitPush[1])  or barnumber()==1 then 0 else if isOrder and profitLoss == 0 then profitPush[1] + 1 else profitPush[1], 0);

def orderCount = (profitWinners + profitLosers + profitPush) - 1;

# Current Open Trade Profit or Loss
def TradePL = If isLong then Round(((close - orderprice)/TickSize())*TickValue()) else if isShort then Round(((orderPrice - close)/TickSize())*TickValue()) else 0;

# Convert to actual dollars based on Tick Value for bubbles
def dollarProfitLoss = if orderPRice[1]==0 or isNaN(orderPrice[1]) then 0 else round((profitLoss/Ticksize())*Tickvalue());

# Closed Orders dollar P/L
def dollarPLSum = round((profitLossSum/Ticksize())*Tickvalue());


# Split profits or losses by long and short trades
def profitLong = compoundValue(1, if isNan(profitLong[1])  or barnumber()==1 then 0 else if isOrder and isLong[1] then profitLong[1]+dollarProfitLoss else profitLong[1],0);
def profitShort = compoundValue(1, if isNan(profitShort[1])  or barnumber()==1 then 0 else if isOrder and isShort[1] then profitShort[1]+dollarProfitLoss else profitShort[1],0);
def countLong = compoundValue(1, if isNaN(countLong[1])  or barnumber()==1 then 0 else if isOrder and isLong[1] then countLong[1]+1 else countLong[1],0);
def countShort = compoundValue(1, if isNaN(countShort[1])  or barnumber()==1 then 0 else if isOrder and isShort[1] then countShort[1]+1 else countShort[1],0);

# What was the biggest winning and losing trade
def biggestWin = compoundValue(1, if isNaN(biggestWin[1]) or barnumber()==1 then 0 else if isOrder and (dollarProfitLoss > 0) and (dollarProfitLoss > biggestWin[1]) then dollarProfitLoss else biggestWin[1], 0);
def biggestLoss = compoundValue(1, if isNaN(biggestLoss[1]) or barnumber()==1 then 0 else if isOrder and (dollarProfitLoss < 0) and (dollarProfitLoss < biggestLoss[1]) then dollarProfitLoss else biggestLoss[1], 0);

# What percent were winners
def PCTWin = round((profitWinners/orderCount)*100,2);


# Average trade
def avgTrade = round((dollarPLSum/orderCount),2);


#######################################
##  Create Labels
#######################################

AddLabel(showLabels, GetSymbol()+" Tick Size: "+TickSize()+" Value: "+TickValue(), color.white);
AddLabel(showLabels, "Closed Orders: " + orderCount + " P/L: " + AsDollars(dollarPLSum), if dollarPLSum > 0 then Color.GREEN else if dollarPLSum< 0 then Color.RED else Color.GRAY);
AddLabel(if !IsNan(orderPrice) and showLabels then 1 else 0, "Closed+Open P/L: "+ AsDollars(TradePL+dollarPLSum), if ((TradePL+dollarPLSum) > 0) then color.green else if ((TradePL+dollarPLSum) < 0) then color.red else color.gray);

AddLabel(showLabels, "Avg per Trade: "+ AsDollars(avgTrade), if avgTrade > 0 then Color.Green else if avgTrade < 0 then Color.RED else Color.GRAY);
AddLabel(showLabels, "Winners: "+ PCTWin +"%",if PCTWin > 50 then color.green else if PCTWin > 40 then color.yellow else color.gray);

AddLabel(showLabels, "MaxUp: "+ AsDollars(biggestWin) +" MaxDown: "+AsDollars(biggestLoss), color.white);
AddLabel(showLabels, "Long Profit: " +AsDollars(profitLong), if profitLong > 0 then color.green else if profitLong < 0 then color.red else color.gray);
AddLabel(showLabels, "Short Profit: " +AsDollars(profitShort), if profitShort > 0 then color.green else if profitShort < 0 then color.red else color.gray);
AddLabel(if !IsNan(CurrentPosition) and showLabels then 1 else 0, "Open: "+ (If isLong then "Bought" else "Sold") + " @ "+orderPrice, color.white);
AddLabel(if !IsNan(orderPrice) and showLabels then 1 else 0, "Open Trade P/L: "+ AsDollars(TradePL), if (TradePL > 0) then color.green else if (TradePl < 0) then color.red else color.gray);



#######################################
##  Chart Bubbles for Profit/Loss
#######################################


AddChartBubble(showSignals and showBubbles and isOrder and isLong[1], low, "$"+dollarProfitLoss, if dollarProfitLoss == 0 then Color.LIGHT_GRAY else if dollarProfitLoss > 0 then Color.GREEN else color.Red, 0);
AddChartBubble(showSignals and showBubbles and isOrder and isShort[1], high,  "$"+dollarProfitLoss, if dollarProfitLoss == 0 then Color.LIGHT_GRAY else if dollarProfitLoss > 0 then Color.GREEN else color.Red, 1);

#AssignPriceColor(if CurrentPosition == 1 then color.green else if CurrentPosition == -1 then color.red else color.gray);

View attachment 13350


and yes, I picked one where it works really well on a daily 1yr. Some aren't so pretty. :)

Here's one that's not as pretty, but not awful either, also a 1yr daily

View attachment 13351
Hello, /

Great Work!! !

Can you help me code the following:

Just want the buy signal to be when Heiken Changes to Green and Sell signal when Changes back to Red... but leave the Backtest code.


Appreciate the help!!!
 
Smoothed Heikin-Ashi with ATR Trail + P/L (Study)
I put this in Strategies since it's a study that has the P/L built in. It's a combination of things I've found on here over the years (so if you were the original author, just let me know and I'll give credit). It combines a smoothed Heikin-Ashi with an ATR Trail to come up with the buy/sell signals. Not saying it works well or not, just putting it here if someone wants to play around with it. I swing trade so have really only looked at it on a daily timeframe. I'm guessing it would be too slow for day-trading, though you might be able to tweak the settings to make it work.



Ruby:
#hint: Smoothed Heiken Ashi and ATR studies

input period = 20;
input hideCandles = no;
input candleSmoothing = {default Valcu, Vervoort};

input movingAverageType = {Simple, default Exponential, Weighted, Hull, Variable, TEMA};

def openMA;
def closeMA;
def highMA;
def lowMA;

switch (movingAverageType) {
case Simple:
    openMA = compoundValue(1, Average(open, period), open);
    closeMA = compoundValue(1, Average(close, period), close);
    highMA = compoundValue(1, Average(high, period), high);
    lowMA = compoundValue(1, Average(low, period), low);
case Exponential:
    openMA = compoundValue(1, ExpAverage(open, period), open);
    closeMA = compoundValue(1, ExpAverage(close, period), close);
    highMA = compoundValue(1, ExpAverage(high, period), high);
    lowMA = compoundValue(1, ExpAverage(low, period), low);
case Weighted:
    openMA = compoundValue(1, WMA(open, period), open);
    closeMA = compoundValue(1, WMA(close, period), close);
    highMA = compoundValue(1, WMA(high, period), high);
    lowMA = compoundValue(1, WMA(low, period), low);
Case Hull:
    openMA = compoundValue(1, HullMovingAvg(open, period), open);
    closeMA = compoundValue(1, HullMovingAvg(close, period), close);
    highMA = compoundValue(1, HullMovingAvg(high, period), high);
    lowMA = compoundValue(1, HullMovingAvg(low, period), low);
case variable:
    openMA = compoundValue(1, VariableMA(open, period), open);
    closeMA = compoundValue(1, VariableMA(close, period), close);
    highMA = compoundValue(1, VariableMA(high, period), high);
    lowMA = compoundValue(1, VariableMA(low, period), low);
case TEMA:
    openMA = compoundValue(1, TEMA(open, period), open);
    closeMA = compoundValue(1, TEMA(close, period), close);
    highMA = compoundValue(1, TEMA(high, period), high);
    lowMA = compoundValue(1, TEMA(low, period), low);
}

hidePricePlot(hideCandles);

def haOpen;
def haClose;

switch(candleSmoothing) {
case Valcu:
    haOpen = CompoundValue(1, ( (haOpen[1] + (openMA[1] + highMA[1] + lowMA[1] + closeMA[1]) /4.0)/2.0), open);
    haClose = ((OpenMA + HighMA + LowMA + CloseMA)/4.0) ;

case Vervoort:
    haOpen = CompoundValue(1, ( (haOpen[1] + (openMA[1] + highMA[1] + lowMA[1] + closeMA[1]) /4.0)/2.0), open);
    haClose = ((((OpenMA + HighMA + LowMA + CloseMA)/4.0) + haOpen + Max(HighMA, haOpen) + Min(LowMA, haOpen))/4.0);
}

plot o = haOpen + 0;
o.hide();

### Wicks and Shadows

def haLow = min(lowMA, haOpen);
def haHigh = max(highMA,haOpen);


#Red Candlesticks -----------------------------------------------------------------|

def haOpen_fall = if haOpen>haClose
              then haOpen
              else double.nan;
def haHigh_fall   = if haOpen>=haClose
              then haHigh
              else double.nan;
def haLow_fall    = if haOpen>=haClose
              then haLow
              else double.nan;
def haClose_fall    = if haOpen>=haClose
              then haClose
              else double.nan;

AddChart(growColor = Color.plum, fallColor = Color.blue, neutralColor = Color.current, high = haHigh_fall, low = haLow_fall, open = haOpen_fall, close = haClose_fall , type = ChartType.CANDLE);


def haOpen_rise = if haOpen<haClose
                then haClose
                else double.nan;
def haHigh_rise  = if haOpen<=haClose
              then haHigh
              else double.nan;
def haLow_rise   = if haOpen<=haClose
              then haLow
              else double.nan;
def haClose_rise   = if haOpen<=haClose
              then haOpen
              else double.nan;

AddChart(growColor = Color.blue, fallColor = Color.plum, neutralColor = Color.current, high = haHigh_rise, low = haLow_rise, open = haOpen_rise, close = HAclose_rise, type = ChartType.CANDLE);

#############################################################################

#############################################################
###   Determine a flat market
#############################################################


input TradeInFlatRange = Yes;
input BarsForFlatRange = 15;
input BarsReqToStayInRange = 13;

def HH = Highest(high[1], BarsForFlatRange);
def LL = Lowest(low[1], BarsForFlatRange);
def maxH = Highest(HH, BarsReqToStayInRange);
def maxL = Lowest(LL, BarsReqToStayInRange);
def HHn = if maxH == maxH[1] or maxL == maxL then maxH else HHn[1];
def LLn = if maxH == maxH[1] or maxL == maxL then maxL else LLn[1];
def Bh = if high <= HHn and HHn == HHn[1] then HHn else Double.NaN;
def Bl = if low >= LLn and LLn == LLn[1] then LLn else Double.NaN;
def CountH = if IsNaN(Bh) or IsNaN(Bl) then 2 else CountH[1] + 1;
def CountL = if IsNaN(Bh) or IsNaN(Bl) then 2 else CountL[1] + 1;
def ExpH = if BarNumber() == 1 then Double.NaN else
            if CountH[-BarsReqToStayInRange] >= BarsReqToStayInRange then HHn[-BarsReqToStayInRange] else
            if high <= ExpH[1] then ExpH[1] else Double.NaN;
def ExpL = if BarNumber() == 1 then Double.NaN else
            if CountL[-BarsReqToStayInRange] >= BarsReqToStayInRange then LLn[-BarsReqToStayInRange] else
            if low >= ExpL[1] then ExpL[1] else Double.NaN;

plot BoxHigh = if !isnan(expL) and !isnan(ExpH) then ExpH else double.nan;
plot BoxLow = if !isnan(expL) and !isnan(ExpH) then ExpL else double.nan;


addcloud( BoxHigh, BoxLow, color.gray, color.gray);


def Flat = if (!isNan(BoxHigh[1]) and !isNan(BoxLow[1])) AND !TradeInFlatRange then 1 else 0;

#addChartBubble(Flat==1 and isNan(Flat[1]),BoxHigh[1],"Flat Market",color.gray,yes);

input trailType = {default modified, unmodified};
input ATRPeriod = 5;
input ATRFactor = 3.0;
input firstTrade = {default long, short};
input averageType = AverageType.WILDERS;

Assert(ATRFactor > 0, "'atr factor' must be positive: " + ATRFactor);

def HiLo = Min(high - low, 1.5 * Average(high - low, ATRPeriod));
def HRef = if low <= high[1]
    then high - close[1]
    else (high - close[1]) - 0.5 * (low - high[1]);
def LRef = if high >= low[1]
    then close[1] - low
    else (close[1] - low) - 0.5 * (low[1] - high);

def trueRange;
switch (trailType) {
case modified:
    trueRange = Max(HiLo, Max(HRef, LRef));
case unmodified:
    trueRange = TrueRange(high, close, low);
}
def loss = ATRFactor * MovingAverage(averageType, trueRange, ATRPeriod);

def state = {default init, long, short};
def trail;
switch (state[1]) {
case init:
    if (!IsNaN(loss)) {
        switch (firstTrade) {
        case long:
            state = state.long;
            trail =  close - loss;
        case short:
            state = state.short;
            trail = close + loss;
        }
    } else {
        state = state.init;
        trail = Double.NaN;
    }
case long:
    if (close > trail[1]) {
        state = state.long;
        trail = Max(trail[1], close - loss);
    } else {
        state = state.short;
        trail = close + loss;
    }
case short:
    if (close < trail[1]) {
        state = state.short;
        trail = Min(trail[1], close + loss);
    } else {
        state = state.long;
        trail =  close - loss;
    }
}

#def BuySignal = Crosses(state == state.long, 0, CrossingDirection.ABOVE);
#def SellSignal = Crosses(state == state.short, 0, CrossingDirection.ABOVE);

plot TrailingStop = trail;

TrailingStop.SetPaintingStrategy(PaintingStrategy.line);
TrailingStop.DefineColor("Buy", color.blue);
TrailingStop.DefineColor("Sell", color.plum);
TrailingStop.AssignValueColor(if state == state.long
    then TrailingStop.Color("Buy")
    else TrailingStop.Color("Sell"));


############################################
##  Define BuySignal and SellSignal above
##  or uncomment them out below and set
##  them to your buy/sell conditions
##
##  If using stops, define them below
############################################

###------------------------------------------------------------------------------------------

input showSignals = yes;
input showLabels  = yes;
input showBubbles = yes;
input useStops = no;
input useAlerts = no;

###------------------------------------------------------------------------------------------

############################################
##  Create Signals -
##  FILL IN THIS SECTION IF NOT DEFINED ABOVE
##
############################################


def BuySignal = state == state.long AND (haOpen < haClose) and (haOpen[1] < haClose[1]) and !Flat ; # insert condition to create long position
def SellSignal = state == state.short AND (haOpen > haClose)  and (haOpen[1] > haClose[1]) and !Flat; # insert condition to create short position

def BuyStop  = if !useStops then 0 else if  state == state.long AND (haOpen > haClose) and Flat then 1 else 0  ; # insert condition to stop in place of the 0<0
def SellStop = if !useStops then 0 else if  state == state.short AND (haOpen < haClose) and Flat then 1 else 0  ; # insert condition to stop in place of the 0>0

#######################################
##  Maintain the position of trades
#######################################

def CurrentPosition;  # holds whether flat = 0 long = 1 short = -1

if (BarNumber()==1) OR isNaN(CurrentPosition[1]) {
    CurrentPosition = 0;
}else{
        if CurrentPosition[1] == 0 {            # FLAT
            if (BuySignal) {
                CurrentPosition = 1;
            } else if (SellSignal){
                CurrentPosition = -1;
            } else {
                CurrentPosition = CurrentPosition[1];
            }
       } else if CurrentPosition[1] == 1 {      # LONG
            if (SellSignal){
                CurrentPosition = -1;
            } else if (BuyStop and useStops){
                CurrentPosition = 0;
            } else {
                CurrentPosition = CurrentPosition[1];
            }
       } else if CurrentPosition[1] == -1 {     # SHORT
            if (BuySignal){
                CurrentPosition = 1;
            } else if (SellStop and useStops){
                CurrentPosition = 0;
            } else {
                CurrentPosition = CurrentPosition[1];
            }
       } else {
            CurrentPosition = CurrentPosition[1];
       }
}


def isLong  = if CurrentPosition == 1 then 1 else 0;
def isShort = if CurrentPosition == -1 then 1 else 0;
def isFlat  = if CurrentPosition == 0 then 1 else 0;

# If not already long and get a BuySignal
Plot BuySig = if (!isLong[1] and BuySignal and showSignals) then 1 else 0;
BuySig.AssignValueColor(color.cyan);
BuySig.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
BuySig.SetLineWeight(5);

Alert(BuySig and useAlerts, "Buy Signal",Alert.bar,sound.Ding);
Alert(BuySig and useAlerts, "Buy Signal",Alert.bar,sound.Ding);

# If not already short and get a SellSignal
Plot SellSig = if (!isShort[1] and SellSignal and showSignals) then 1 else 0;
SellSig.AssignValueColor(color.cyan);
SellSig.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
SellSig.SetLineWeight(5);

Alert(SellSig and useAlerts, "Sell Signal",Alert.bar,sound.Ding);
Alert(SellSig and useAlerts, "Sell Signal",Alert.bar,sound.Ding);

# If long and get a BuyStop
Plot BuyStpSig = if (BuyStop and isLong[1] and showSignals and useStops) then 1 else 0;
BuyStpSig.AssignValueColor(color.light_gray);
BuyStpSig.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
BuyStpSig.SetLineWeight(3);

# If short and get a SellStop
Plot SellStpSig = if (SellStop and isShort[1] and showSignals and useStops) then 1 else 0;
SellStpSig.AssignValueColor(color.light_gray);
SellStpSig.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
SellStpSig.SetLineWeight(3);


#######################################
##  Orders
#######################################

def isOrder = if CurrentPosition == CurrentPosition[1] then 0 else 1; # Position changed so it's a new order

# If there is an order, then the price is the next days close
def orderPrice = if (isOrder and (BuySignal or SellSignal)) then close else orderPrice[1];

#######################################
##  Price and Profit
#######################################

def profitLoss;


if (!isOrder or orderPRice[1]==0){
    profitLoss = 0;
} else if ((isOrder and isLong[1]) and (SellSig or BuyStpSig)){
    profitLoss = close - orderPrice[1];
} else if ((isOrder and isShort[1]) and (BuySig or SellStpSig)) {
    profitLoss = orderPrice[1] - close;
} else {
    profitLoss = 0;
}


# Total Profit or Loss
def profitLossSum = compoundValue(1, if isNaN(isOrder)  or barnumber()==1 then 0 else if isOrder then profitLossSum[1] + profitLoss else profitLossSum[1], 0);

# How many trades won or lost
def profitWinners = compoundValue(1, if isNaN(profitWinners[1]) or barnumber()==1 then 0 else if isOrder and profitLoss > 0 then profitWinners[1] + 1 else profitWinners[1], 0);
def profitLosers = compoundValue(1, if isNaN(profitLosers[1])  or barnumber()==1 then 0 else if isOrder and profitLoss < 0 then profitLosers[1] + 1 else profitLosers[1], 0);
def profitPush = compoundValue(1, if isNaN(profitPush[1])  or barnumber()==1 then 0 else if isOrder and profitLoss == 0 then profitPush[1] + 1 else profitPush[1], 0);

def orderCount = (profitWinners + profitLosers + profitPush) - 1;

# Current Open Trade Profit or Loss
def TradePL = If isLong then Round(((close - orderprice)/TickSize())*TickValue()) else if isShort then Round(((orderPrice - close)/TickSize())*TickValue()) else 0;

# Convert to actual dollars based on Tick Value for bubbles
def dollarProfitLoss = if orderPRice[1]==0 or isNaN(orderPrice[1]) then 0 else round((profitLoss/Ticksize())*Tickvalue());

# Closed Orders dollar P/L
def dollarPLSum = round((profitLossSum/Ticksize())*Tickvalue());


# Split profits or losses by long and short trades
def profitLong = compoundValue(1, if isNan(profitLong[1])  or barnumber()==1 then 0 else if isOrder and isLong[1] then profitLong[1]+dollarProfitLoss else profitLong[1],0);
def profitShort = compoundValue(1, if isNan(profitShort[1])  or barnumber()==1 then 0 else if isOrder and isShort[1] then profitShort[1]+dollarProfitLoss else profitShort[1],0);
def countLong = compoundValue(1, if isNaN(countLong[1])  or barnumber()==1 then 0 else if isOrder and isLong[1] then countLong[1]+1 else countLong[1],0);
def countShort = compoundValue(1, if isNaN(countShort[1])  or barnumber()==1 then 0 else if isOrder and isShort[1] then countShort[1]+1 else countShort[1],0);

# What was the biggest winning and losing trade
def biggestWin = compoundValue(1, if isNaN(biggestWin[1]) or barnumber()==1 then 0 else if isOrder and (dollarProfitLoss > 0) and (dollarProfitLoss > biggestWin[1]) then dollarProfitLoss else biggestWin[1], 0);
def biggestLoss = compoundValue(1, if isNaN(biggestLoss[1]) or barnumber()==1 then 0 else if isOrder and (dollarProfitLoss < 0) and (dollarProfitLoss < biggestLoss[1]) then dollarProfitLoss else biggestLoss[1], 0);

# What percent were winners
def PCTWin = round((profitWinners/orderCount)*100,2);


# Average trade
def avgTrade = round((dollarPLSum/orderCount),2);


#######################################
##  Create Labels
#######################################

AddLabel(showLabels, GetSymbol()+" Tick Size: "+TickSize()+" Value: "+TickValue(), color.white);
AddLabel(showLabels, "Closed Orders: " + orderCount + " P/L: " + AsDollars(dollarPLSum), if dollarPLSum > 0 then Color.GREEN else if dollarPLSum< 0 then Color.RED else Color.GRAY);
AddLabel(if !IsNan(orderPrice) and showLabels then 1 else 0, "Closed+Open P/L: "+ AsDollars(TradePL+dollarPLSum), if ((TradePL+dollarPLSum) > 0) then color.green else if ((TradePL+dollarPLSum) < 0) then color.red else color.gray);

AddLabel(showLabels, "Avg per Trade: "+ AsDollars(avgTrade), if avgTrade > 0 then Color.Green else if avgTrade < 0 then Color.RED else Color.GRAY);
AddLabel(showLabels, "Winners: "+ PCTWin +"%",if PCTWin > 50 then color.green else if PCTWin > 40 then color.yellow else color.gray);

AddLabel(showLabels, "MaxUp: "+ AsDollars(biggestWin) +" MaxDown: "+AsDollars(biggestLoss), color.white);
AddLabel(showLabels, "Long Profit: " +AsDollars(profitLong), if profitLong > 0 then color.green else if profitLong < 0 then color.red else color.gray);
AddLabel(showLabels, "Short Profit: " +AsDollars(profitShort), if profitShort > 0 then color.green else if profitShort < 0 then color.red else color.gray);
AddLabel(if !IsNan(CurrentPosition) and showLabels then 1 else 0, "Open: "+ (If isLong then "Bought" else "Sold") + " @ "+orderPrice, color.white);
AddLabel(if !IsNan(orderPrice) and showLabels then 1 else 0, "Open Trade P/L: "+ AsDollars(TradePL), if (TradePL > 0) then color.green else if (TradePl < 0) then color.red else color.gray);



#######################################
##  Chart Bubbles for Profit/Loss
#######################################


AddChartBubble(showSignals and showBubbles and isOrder and isLong[1], low, "$"+dollarProfitLoss, if dollarProfitLoss == 0 then Color.LIGHT_GRAY else if dollarProfitLoss > 0 then Color.GREEN else color.Red, 0);
AddChartBubble(showSignals and showBubbles and isOrder and isShort[1], high,  "$"+dollarProfitLoss, if dollarProfitLoss == 0 then Color.LIGHT_GRAY else if dollarProfitLoss > 0 then Color.GREEN else color.Red, 1);

#AssignPriceColor(if CurrentPosition == 1 then color.green else if CurrentPosition == -1 then color.red else color.gray);

View attachment 13350


and yes, I picked one where it works really well on a daily 1yr. Some aren't so pretty. :)

Here's one that's not as pretty, but not awful either, also a 1yr daily

View attachment 13351
Very nice work on this but for the life of me I cannot get this script to display stops / sells / buys on a chart. I'm no coder but I do have a limited working knowledge of TS. Looking through the script I see some things are remarked out but I'm pretty helpless to alter the script correctly to. obtain the stops. Would really appreciate being talked down off this ledge if at all possible. Thanks in advance.
 

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
493 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