ParabolicSAR - PSAR Moving Average Strategy For ThinkOrSwim

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

I think Merryday the mod updated the logic? The price was changed to the open of the previous candle as opposed to the current candle ( which looks nice when you backtest but you can't do that in real time. )

Use the updated version , while the results are reduced , I have compared that to the 1st 3 pages of strategies here and it is still the leading strategy by a mile.

the 2nd closest is the https://usethinkscript.com/threads/multi-timeframe-rsi-strategy-indicator-for-thinkorswim.11327/ which repaints. repainting can give false signals in real time but looks picture perfect when you backtest it.




I plan to forward test this on Monday

For the added Critiera , the ADX thick line should be above 25 to trade. ( I removed the bottom line as the strategy was :
  • For all entries, ADX > 25.
  • For long entries, DI+ > DI-.
  • For short entries DI- > DI+.)
For longs ADX line should be blue while the DMI should be blue( that looks like a histogram). Enter when you see long and put the stop loss on the low of the previous candle.
For Shorts ADX line should be white while DMI should be white.
Enter when you see Short and put the stop loss on the high of the previous candle.
I cant wait to throw real risk into this and very delighted to hear it's working out well for you and others.

I've been testing an ADX above and below filter. So far mixed results. I'll go ahead and share though inspired by your interest.
 
First things first. I am sharing this version due to interest and not because I have completed the logic to my full comfort. I welcome any and all inspection and am open to improvements and corrections. Thanks for your interest. That said. It works well. The way the logic works is similar to the original but now this version adds the ADX. What I am trying to accomplish: When the price goes into a consolidation it will do the opposite from when its trending. If you have been testing this for a while you would notice that when the price is consolidating or going sideways the old PSAR strat is wrong. In fact when the price showed down was exactly when it should buy. This is what I am trying to anticipate. Take a look at the logic and signal conditions. I try to lay out my strategies easy to follow along. Enjoy and Good Luck testing.


CSS:
# Parabolic_SAR_Moving_Average_Trading_Strategy
# ParabolicSAR_Trendy_Strategy_1_18

# by BabyTrader using the following article: Parabolic SAR Moving Average Trading Strategy

# https://tradingstrategyguides.com/parabolic-sar-moving-average-trade-strategy/

# ParabolicSAR_withAlerts_JQ
# 2018-04-15 Mods by Johnny Quotron
#    with a very helpful kickstart from DMonkey
# Mods include
#    1. splitting the PSAR into two visible plots so that they can be colored seperately
#    2. adding alert arrows at the PSAR to enhance visibility
#        a. original alert arrows remain available but are hidden by default
#    3. add ability to color color alert arrows
#

# Combined/Modified/Altered by SilverWolf


declare upper;
 
#======== Inputs ==============================================================================

input TradeSize = 1;
input SarBars = 3;
input accelerationFactor = 0.012;
input accelerationLimit = 0.2;
input extremeoffset = 0.0;

input MovAvgType = AverageType.EXPONENTIAL;
input MovAvgTrendMethod = {default "SINGLE", "CROSSING"};
input CrossingAvgLength = 9;
input TrendTriggerAvgLength = 21;

input TradeClosingMethod = {default "SAR", "MOVAVG"};


def Trend = if MovAvgTrendMethod == MovAvgTrendMethod."SINGLE" then 1 else
            if MovAvgTrendMethod == MovAvgTrendMethod."CROSSING" then 2 else 0;

def PlotCross = if Trend == 2 then yes else no;

def Closer = if TradeClosingMethod == TradeClosingMethod."SAR" then 1 else
             if TradeClosingMethod == TradeClosingMethod."MOVAVG" then 2 else 0;

#======== Moving Averages ======================================================================

plot TriggerAVG = MovingAverage(MovAvgType, close, TrendTriggerAvgLength);
TriggerAVG.SetLineWeight(3);
TriggerAVG.SetDefaultColor(Color.WHITE);

plot CrossingAVG = MovingAverage(MovAvgType, close, CrossingAvgLength);
CrossingAVG.SetHiding(!PlotCross);
CrossingAVG.SetLineWeight(3);
CrossingAVG.SetDefaultColor(Color.PINK);

#======== ParabolicSAR =========================================================================

Assert(accelerationFactor > 0, "'acceleration factor' must be positive: " + accelerationFactor);
Assert(accelerationLimit >= accelerationFactor, "'acceleration limit' (" + accelerationLimit + ") must be greater than or equal to 'acceleration factor' (" + accelerationFactor + ")");

def state = {default init, long, short};
def extreme;
def SAR;
def acc;

switch (state[1]) {
case init:
    state = state.long;
    acc = accelerationFactor;
    extreme = high;
    SAR = low;
case short:
    if (SAR[1] < high)
    then {
        state = state.long;
        acc = accelerationFactor;
        extreme = high + extremeoffset;
        SAR = extreme[1];
    } else {
        state = state.short;
        if (low < extreme[1])
        then {
            acc = Min(acc[1] + accelerationFactor, accelerationLimit);
            extreme = low - extremeoffset;
        } else {
            acc = acc[1];
            extreme = extreme[1];
        }
        SAR = Max(Max(high, high[1]), SAR[1] + acc * (extreme - SAR[1]));
    }
case long:
    if (SAR[1] > low)
    then {
        state = state.short;
        acc = accelerationFactor;
        extreme = low - extremeoffset;
        SAR = extreme[1];
    } else {
        state = state.long;
        if (high > extreme[1])
        then {
            acc = Min(acc[1] + accelerationFactor, accelerationLimit);
            extreme = high + extremeoffset;
        } else {
            acc = acc[1];
            extreme = extreme[1];
        }
        SAR = Min(Min(low, low[1]), SAR[1] + acc * (extreme - SAR[1]));
    }
}

#======== ADX ===========================================================================

input ADXlength = 14;
input averageType = AverageType.WILDERS;
input mom = 20;

def hiDiff = high - high[1];
def loDiff = low[1] - low;

def plusDM = if hiDiff > loDiff and hiDiff > 0 then hiDiff else 0;
def minusDM =  if loDiff > hiDiff and loDiff > 0 then loDiff else 0;

def ATR = MovingAverage(averageType, TrueRange(high, close, low), ADXlength);
def "DI+" = 100 * MovingAverage(averageType, plusDM, ADXlength) / ATR;
def "DI-" = 100 * MovingAverage(averageType, minusDM, ADXlength) / ATR;

def DX = if ("DI+" + "DI-" > 0) then 100 * AbsValue("DI+" - "DI-") / ("DI+" + "DI-") else 0;
def ADX = MovingAverage(averageType, DX, ADXlength);


#======== Logic =========================================================================
input adxLogic = yes;

def Logic = if adxLogic and ADX > mom

then 1

else if adxLogic and ADX < mom

then 2

else if !adxLogic

then 1

else Double.NaN;


def TrendingUp = if "DI-" > ADX and ADX > "DI+"

then 1

else Double.NaN;

def TrendingDown = if "DI-" > ADX and ADX > "DI+"

then 1

else Double.NaN;

#======== SIGNALS =========================================================================

def BuySignal = if Logic == 1 and Trend == 1 and (close > TriggerAVG ) and (SAR crosses below close)

then 1

else if Logic == 1 and Trend == 2 and (close > TriggerAVG) and (CrossingAVG > TriggerAVG) and (SAR crosses below close)

then 1

else if Logic == 2 and Trend == 1 and (close < TriggerAVG ) and (SAR crosses above close)

then 1

else if Logic == 2 and Trend == 2 and (close < TriggerAVG) and (CrossingAVG < TriggerAVG) and (SAR crosses above close)

then 1

else Double.NaN;


def SellSignal = if Logic == 1 and Trend == 1 and (close < TriggerAVG ) and (SAR crosses above close)

then 1

else if Logic == 1 and Trend == 2 and (close < TriggerAVG) and (CrossingAVG < TriggerAVG) and (SAR crosses above close)

then 1

else if Logic == 2 and Trend == 1 and (close > TriggerAVG ) and (SAR crosses below close)

then 1

else if Logic == 2 and Trend == 2 and (close > TriggerAVG) and (CrossingAVG > TriggerAVG) and (SAR crosses below close)

then 1

else Double.NaN;


def BuyExit = if Logic == 1 and Closer == 1 and (close crosses below SAR)

then 1

else if Logic == 1 and Closer == 2 and (close crosses below TriggerAVG)

then 1

else if Logic == 2 and Closer == 1 and (close crosses above SAR)

then 1

else if Logic == 2 and Closer == 2 and (close crosses above TriggerAVG)

then 1

else if Logic == 1 and Closer == 1 and (adx crosses mom)

then 1

else if Logic == 1 and Closer == 2 and (adx crosses mom)

then 1

else if Logic == 2 and Closer == 1 and (adx crosses mom)

then 1

else if Logic == 2 and Closer == 2 and (adx crosses mom)

then 1

else Double.NaN;


def SellExit = if Logic == 1 and Closer == 1 and (close crosses above SAR)

then 1

else if Logic == 1 and Closer == 2 and (close crosses above TriggerAVG)

then 1

else if Logic == 2 and Closer == 1 and (close crosses below SAR)

then 1

else if Logic == 2 and Closer == 2 and (close crosses below TriggerAVG)

then 1

else if Logic == 1 and Closer == 1 and (adx crosses mom)

then 1

else if Logic == 1 and Closer == 2 and (adx crosses mom)

then 1

else if Logic == 2 and Closer == 1 and (adx crosses mom)

then 1

else if Logic == 2 and Closer == 2 and (adx crosses mom)

then 1

else Double.NaN;


#======== STRATEGY ORDERS ===================================================================

def VolStrength = Lg(volume[1]) - Lg(SimpleMovingAvg(volume[1], 2000));
def HighPrice = high;
def LowPrice = low;
#input Price = close; #{default Close, Open, high[1] + low[1]/2};


AddOrder(OrderType.BUY_TO_OPEN, BuySignal, open[-1], TradeSize, Color.GREEN, Color.GREEN, name = "Long");

AddOrder(OrderType.SELL_TO_CLOSE, BuyExit, open[-1], TradeSize, Color.RED, Color.RED, name = "Close");

AddOrder(OrderType.SELL_TO_OPEN, SellSignal, open[-1], TradeSize, Color.ORANGE, Color.ORANGE, name = "Short");

AddOrder(OrderType.BUY_TO_CLOSE, SellExit, open[-1], TradeSize, Color.WHITE, Color.WHITE, name = "Close");



#AddOrder(OrderType.BUY_TO_OPEN, BuySignal, Price[0], TradeSize, Color.GREEN, Color.GREEN, name = "Long");

#AddOrder(OrderType.SELL_TO_CLOSE, BuyExit, (HighPrice[-1] + LowPrice[-1]) / 2, TradeSize, Color.RED, Color.RED, name = "Long Close");

#AddOrder(OrderType.SELL_TO_OPEN, SellSignal, Price[0], TradeSize, Color.ORANGE, Color.ORANGE, name = "Short");

#AddOrder(OrderType.BUY_TO_CLOSE, SellExit, (HighPrice[-1] + LowPrice[-1]) / 2, TradeSize, Color.WHITE, Color.WHITE, name = "Short Close");
 

#======== PLOTS ============================================================================

plot BullPSAR = if SAR < close then SAR else Double.NaN;
BullPSAR.SetPaintingStrategy(PaintingStrategy.POINTS);
BullPSAR.SetDefaultColor(Color.LIME);

plot BearPSAR = if SAR > close then SAR else Double.NaN;
BearPSAR.SetPaintingStrategy(PaintingStrategy.POINTS);
BearPSAR.SetDefaultColor(Color.PINK);

#---

def BullSignalAtCandle = Crosses(SAR, close, CrossingDirection.BELOW);
plot BullSignalAtPSAR = if close crosses above SAR
                     then SAR
                     else Double.NaN;
BullSignalAtPSAR.SetLineWeight(1);
BullSignalAtPSAR.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
BullSignalAtPSAR.SetDefaultColor(Color.LIME);

def BearSignalAtCandle = Crosses(SAR, close, CrossingDirection.ABOVE);
plot BearSignalAtPSAR = if close crosses below SAR
                     then SAR
                     else Double.NaN;
BearSignalAtPSAR.SetLineWeight(1);
BearSignalAtPSAR.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
BearSignalAtPSAR.SetDefaultColor(Color.PINK);

#---

plot LongEntrySignal = if BuySignal then BuySignal else Double.NaN;
LongEntrySignal.SetDefaultColor(Color.UPTICK);
LongEntrySignal.SetLineWeight(5);
LongEntrySignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);


plot ShortEntrySignal = if SellSignal then SellSignal else Double.NaN;
ShortEntrySignal.SetDefaultColor(Color.DOWNTICK);
ShortEntrySignal.SetLineWeight(5);
ShortEntrySignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);

plot LongExitSignal = if BuyExit then BuyExit else Double.NaN;
LongExitSignal.SetDefaultColor(Color.WHITE);
LongExitSignal.SetLineWeight(1);
LongExitSignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);


plot ShortExitSignal = if SellExit then SellExit else Double.NaN;
ShortExitSignal.SetDefaultColor(Color.WHITE);
ShortExitSignal.SetLineWeight(1);
ShortExitSignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);

#======== ALERTS ===========================================================================

input AlertsOn = No;
Alert(AlertsOn and BullSignalAtCandle, "Bullish PSAR", Alert.BAR, Sound.Ring);
Alert(AlertsOn and BearSignalAtCandle, "Bearish PSAR", Alert.BAR, Sound.Ring);
Alert(AlertsOn and BuySignal, "Bullish PSAR above AVG", Alert.BAR, Sound.Ring);
Alert(AlertsOn and SellSignal, "Bullish PSAR below AVG", Alert.BAR, Sound.Ring);

#======== Paint Bars =======================================================================

input paintBars = No;
AssignPriceColor(if !paintBars
    then Color.CURRENT
    else if SAR < close
        then Color.GREEN
        else if  SAR > close
            then Color.RED
            else Color.CURRENT);

#======== Labels ===========================================================================

#Spacer
input blink = no;
input AdvLabelsOn = no;
input simpleLabels = no;

def NewBar = if close[1] != close[2] or high[1] != high[2] or low[1] != low[2] then yes else Double.NaN;
def Clock = if !IsNaN(NewBar) and Clock[1] == 1 then 0 else if !IsNaN(NewBar) and Clock[1] == 0 then 1 else Clock[1];

AddLabel(blink and AdvLabelsOn or SimpleLabels, "                                                                     ParabolicSAR Strategy Version 01.11                                                                                                     ", if Clock == 0 then Color.WHITE else Color.YELLOW);
AddLabel(!blink and AdvLabelsOn or SimpleLabels, "                                                                     ParabolicSAR Strategy Version 01.11                                                                                                     ",  Color.WHITE);


#Buy
AddLabel(AdvLabelsOn,
if  Logic == 1 and Trend == 1 and (close > TriggerAVG ) and (SAR crosses below close) within SarBars bars
or  Logic == 1 and Trend == 2 and (close > TriggerAVG) and (CrossingAVG > TriggerAVG) and (SAR crosses below close) within SarBars bars
or  Logic == 2 and Trend == 1 and (close < TriggerAVG) and (SAR crosses above close) within SarBars bars
or  Logic == 2 and Trend == 2 and (close < TriggerAVG) and (CrossingAVG < TriggerAVG) and (SAR crosses above close) within SarBars bars then "         " else "         ",

if  Logic == 1 and Trend == 1 and (close > TriggerAVG) and (SAR crosses below close) within SarBars bars
or  Logic == 1 and Trend == 2 and (close > TriggerAVG) and (CrossingAVG > TriggerAVG) and (SAR crosses below close) within SarBars bars
or  Logic == 2 and Trend == 1 and (close < TriggerAVG) and (SAR crosses above close) within SarBars bars
or  Logic == 2 and Trend == 2 and (close < TriggerAVG) and (CrossingAVG < TriggerAVG) and (SAR crosses above close) within SarBars bars then Color.GREEN else Color.WHITE);


#BuyClose
AddLabel(AdvLabelsOn,
if  Logic == 1 and Closer == 1 and (SAR > close) within SarBars bars
or  Logic == 1 and  Closer == 2 and (close < TriggerAVG) within SarBars bars
or  Logic == 2 and Closer == 1 and (SAR < close) within SarBars bars
or  Logic == 2 and Closer == 2 and (close > TriggerAVG)
or  Logic == 1 and Closer == 1 and (adx crosses above mom) within SarBars bars
or  Logic == 1 and Closer == 2 and (adx crosses above mom) within SarBars bars
or  Logic == 2 and Closer == 1 and (adx crosses below mom) within SarBars bars
or  Logic == 2 and Closer == 2 and (adx crosses below mom) within SarBars bars then "         " else "         ",

if  Logic == 1 and Closer == 1 and (SAR > close) within SarBars bars
or  Logic == 1 and  Closer == 2 and (close < TriggerAVG) within SarBars bars
or  Logic == 2 and Closer == 1 and (SAR < close) within SarBars bars
or  Logic == 2 and Closer == 2 and (close > TriggerAVG)
or  Logic == 1 and Closer == 1 and (adx crosses above mom) within SarBars bars
or  Logic == 1 and Closer == 2 and (adx crosses above mom) within SarBars bars
or  Logic == 2 and Closer == 1 and (adx crosses below mom) within SarBars bars
or  Logic == 2 and Closer == 2 and (adx crosses below mom) within SarBars bars then Color.MAGENTA else Color.WHITE);

#Sell
AddLabel(AdvLabelsOn,
if  Logic == 1 and Trend == 1 and (close < TriggerAVG) and (SAR crosses above close) within SarBars bars
or  Logic == 1 and Trend == 2 and (close < TriggerAVG) and (CrossingAVG < TriggerAVG) and (SAR crosses above close) within SarBars bars
or Logic == 2 and Trend == 1 and (close > TriggerAVG) and (SAR crosses below close) within SarBars bars
or  Logic == 2 and Trend == 2 and (close > TriggerAVG) and (CrossingAVG > TriggerAVG) and (SAR crosses below close) within SarBars bars then "         " else "         ",

if  Logic == 1 and Trend == 1 and (close < TriggerAVG) and (SAR crosses above close) within SarBars bars
or  Logic == 1 and Trend == 2 and (close < TriggerAVG) and (CrossingAVG < TriggerAVG) and (SAR crosses above close) within SarBars bars
or  Logic == 2 and Trend == 1 and (close > TriggerAVG) and (SAR crosses below close) within SarBars bars
or  Logic == 2 and Trend == 2 and (close > TriggerAVG) and (CrossingAVG > TriggerAVG) and (SAR crosses below close) within SarBars bars then Color.RED else Color.WHITE);


#SellClose
AddLabel(AdvLabelsOn,
if  Logic == 1 and Closer == 1 and (SAR < close) within SarBars bars
or  Logic == 1 and Closer == 2 and (close > TriggerAVG) within SarBars bars
or  Logic == 2 and Closer == 1 and (SAR > close) within SarBars bars
or  Logic == 2 and Closer == 2 and (close < TriggerAVG)
or  Logic == 1 and Closer == 1 and (adx crosses below mom) within SarBars bars
or  Logic == 1 and Closer == 2 and (adx crosses below mom) within SarBars bars
or  Logic == 2 and Closer == 1 and (adx crosses above mom) within SarBars bars
or  Logic == 2 and Closer == 2 and (adx crosses above mom) within SarBars bars then "         " else "         ",

if  Logic == 1 and Closer == 1 and (SAR < close) within SarBars bars
or  Logic == 1 and Closer == 2 and (close > TriggerAVG) within SarBars bars
or Logic == 2 and Closer == 1 and (SAR> close) within SarBars bars
or  Logic == 2 and Closer == 2 and (close < TriggerAVG)
or  Logic == 1 and Closer == 1 and (adx crosses below mom) within SarBars bars
or  Logic == 1 and Closer == 2 and (adx crosses below mom) within SarBars bars
or  Logic == 2 and Closer == 1 and (adx crosses above mom) within SarBars bars
or  Logic == 2 and Closer == 2 and (adx crosses above mom) within SarBars bars then Color.LIGHT_GREEN else Color.WHITE);




AddLabel (simpleLabels, if BuySignal within SarBars bars then  "         " else   "         ", if BuySignal >= 1 within SarBars bars then Color.GREEN else Color.WHITE);
AddLabel (simpleLabels, if BuyExit within SarBars bars then  "         " else   "         ", if BuyExit >= 1 within SarBars bars then Color.MAGENTA else Color.WHITE);
AddLabel (simpleLabels, if SellSignal within SarBars bars then  "         " else   "         ", if SellSignal >= 1 within SarBars bars then Color.RED else Color.WHITE);
AddLabel (simpleLabels, if SellExit within SarBars bars then  "         " else   "         ", if SellExit >= 1 within SarBars bars then Color.LIGHT_GREEN else Color.WHITE);



AddLabel (AdvLabelsOn or simpleLabels,
if Logic == 2 then "  Modified Logic  " else "   Normal Logic   ", Color.WHITE);


#======== EOF =========================================================================
 
Last edited:
My initial thoughts are based on your 2nd code vs version 1_18

I think you are trying to change too many things at once :ROFLMAO:

What is the new logic you are trying to implement ?



the performance dropped from positive to negative



I have adjusted the mom to 25 but it seems that the entry went on even though it shouldn't have.
That thicker blue /white line , is the ADX , is below 25 and entry went through .
  • For all entries, ADX > 25.
  • For long entries, DI+ > DI-.
  • For short entries DI- > DI+.
 
If the logic chosen is slope from :

https://www.tradingsetupsreview.com/secret-using-adx-indicator/

then https://usethinkscript.com/threads/...-or-decreasing-adx-indicator.8079/#post-77095 should be looked at

ADX.AssignValueColor(if ADX > ADX[1] then ADX.color("Up") else ADX.color("Down"));

he compares current ADX with previous ADX value.





the switch over here doesn't seem to switch off ?
e.g. if it is trendingup when the conditions are fulfilled , maybe it is a good idea to turn Trendingdown to 0 ? and viceversa




if the logic chosen is :
  • For all entries, ADX > 25.
  • For long entries, DI+ > DI-.
  • For short entries DI- > DI+.
so perhaps TrendingUp = "DI+" > "DI-" ?
Trending Down = "DI-" > "DI+"
 
If the logic chosen is slope from :

https://www.tradingsetupsreview.com/secret-using-adx-indicator/

then https://usethinkscript.com/threads/...-or-decreasing-adx-indicator.8079/#post-77095 should be looked at

ADX.AssignValueColor(if ADX > ADX[1] then ADX.color("Up") else ADX.color("Down"));

he compares current ADX with previous ADX value.





the switch over here doesn't seem to switch off ?
e.g. if it is trendingup when the conditions are fulfilled , maybe it is a good idea to turn Trendingdown to 0 ? and viceversa




if the logic chosen is :
  • For all entries, ADX > 25.
  • For long entries, DI+ > DI-.
  • For short entries DI- > DI+.
so perhaps TrendingUp = "DI+" > "DI-" ?
Trending Down = "DI-" > "DI+"
I havent implemented the trendingup or trendingdown yet.. The only thing I have been testing is ADX above and below the filter(mom)

please check that you have switched on the "ADX logic" input. What should happen is that it would buy right where you circled.


n2VQoWG.png
 
Im using this as I test to visually see when adx is below the filter. it will paint the bars as well

CSS:
declare lower;

input length = 14;
input averageType = AverageType.WILDERS;

input CutOffLine = 25;
def na = Double.NaN;

plot ADX = DMI(length, averageType).ADX;
ADX.SetDefaultColor(GetColor(5));

plot TheLine = if IsNaN(close) then na else CutOffLine;
TheLine.SetDefaultColor(Color.GREEN);


input ColorBars = yes;
AssignPriceColor(if !ColorBars then Color.CURRENT else
                 if ADX < TheLine then Color.GRAY else
                 if ADX > TheLine then Color.GREEN else
                 if ADX > TheLine + 10 then Color.DARK_GREEN else
                 if ADX < TheLine - 10 then Color.RED else Color.DARK_RED);


input ShowLabel = yes;
AddLabel(ShowLabel and ADX > CutOffLine, Concat(Round(ADX, 1), " |         | Trending"), (Color.GREEN));
AddLabel(ShowLabel and ADX < CutOffLine, Concat(Round(ADX, 1), " |         | Choppy"), (Color.RED));
 
# Parabolic_SAR_Moving_Average_Trading_Strategy

# by BabyTrader using the following article: Parabolic SAR Moving Average Trading Strategy

# https://tradingstrategyguides.com/parabolic-sar-moving-average-trade-strategy/

# ParabolicSAR_withAlerts_JQ
# 2018-04-15 Mods by Johnny Quotron
# with a very helpful kickstart from DMonkey
# Mods include
# 1. splitting the PSAR into two visible plots so that they can be colored seperately
# 2. adding alert arrows at the PSAR to enhance visibility
# a. original alert arrows remain available but are hidden by default
# 3. add ability to color color alert arrows
#

# Combined/Modified/Altered by SilverWolf


declare upper;

#======== Inputs ==============================================================================



input accelerationFactor = 0.012;
input accelerationLimit = 0.2;
input extremeoffset = 0.0;

input MovAvgType = AverageType.EXPONENTIAL;
input MovAvgTrendMethod = {default "SINGLE", "CROSSING"};
input CrossingAvgLength = 9;
input TrendTriggerAvgLength = 21;

input TradeClosingMethod = {default "SAR", "MOVAVG"};
input TradeSize = 1;
##this is to get ADX's level
#input ADXlength = 14;
#input averageType = AverageType.WILDERS;

def Trend = if MovAvgTrendMethod == MovAvgTrendMethod."SINGLE" then 1 else
if MovAvgTrendMethod == MovAvgTrendMethod."CROSSING" then 2 else 0;

def PlotCross = if Trend == 2 then yes else no;

def Closer = if TradeClosingMethod == TradeClosingMethod."SAR" then 1 else
if TradeClosingMethod == TradeClosingMethod."MOVAVG" then 2 else 0;


#======== ADX from ADXBreakoutsLE strategy ==================================================================================
input adxLength = 14;
input CutOffLine = 25;
input averageType = AverageType.WILDERS;

plot adx = reference ADX(length = adxLength);




#======== Moving Averages ======================================================================

plot TriggerAVG = MovingAverage(MovAvgType, close, TrendTriggerAvgLength);
TriggerAVG.SetLineWeight(3);
TriggerAVG.SetDefaultColor(Color.WHITE);

plot CrossingAVG = MovingAverage(MovAvgType, close, CrossingAvgLength);
CrossingAVG.SetHiding(!PlotCross);
CrossingAVG.SetLineWeight(3);
CrossingAVG.SetDefaultColor(Color.PINK);

#======== ParabolicSAR =========================================================================

Assert(accelerationFactor > 0, "'acceleration factor' must be positive: " + accelerationFactor);
Assert(accelerationLimit >= accelerationFactor, "'acceleration limit' (" + accelerationLimit + ") must be greater than or equal to 'acceleration factor' (" + accelerationFactor + ")");

def state = {default init, long, short};
def extreme;
def SAR;
def acc;

switch (state[1]) {
case init:
state = state.long;
acc = accelerationFactor;
extreme = high;
SAR = low;
case short:
if (SAR[1] < high)
then {
state = state.long;
acc = accelerationFactor;
extreme = high + extremeoffset;
SAR = extreme[1];
} else {
state = state.short;
if (low < extreme[1])
then {
acc = Min(acc[1] + accelerationFactor, accelerationLimit);
extreme = low - extremeoffset;
} else {
acc = acc[1];
extreme = extreme[1];
}
SAR = Max(Max(high, high[1]), SAR[1] + acc * (extreme - SAR[1]));
}
case long:
if (SAR[1] > low)
then {
state = state.short;
acc = accelerationFactor;
extreme = low - extremeoffset;
SAR = extreme[1];
} else {
state = state.long;
if (high > extreme[1])
then {
acc = Min(acc[1] + accelerationFactor, accelerationLimit);
extreme = high + extremeoffset;
} else {
acc = acc[1];
extreme = extreme[1];
}
SAR = Min(Min(low, low[1]), SAR[1] + acc * (extreme - SAR[1]));
}
}


#======== SIGNALS =========================================================================




def BuySignal = if Trend == 1 and (close > TriggerAVG ) and (SAR crosses below close) and ADX > CutOffLine
then 1

else if Trend == 2 and (close > TriggerAVG) and (CrossingAVG crosses above TriggerAVG) and (SAR < close)

then 1
else Double.NaN;


def SellSignal = if Trend == 1 and (close < TriggerAVG ) and (SAR crosses above close) and ADX > CutOffLine
then 1

else if Trend == 2 and (close < TriggerAVG) and (CrossingAVG crosses below TriggerAVG) and (SAR > close)

then 1

else Double.NaN;


def BuyExit = if Closer == 1 and (close crosses below SAR[-1])

then 1

else if Closer == 2 and (TriggerAVG > CrossingAVG)

then 1

else Double.NaN;


def SellExit = if Closer == 1 and (close crosses above SAR[-1])

then 1

else if Closer == 2 and (TriggerAVG < CrossingAVG)

then 1

else Double.NaN;


#======== STRATEGY ORDERS ===================================================================
AddOrder(OrderType.BUY_TO_OPEN, BuySignal, open[-1], TradeSize, Color.GREEN, Color.GREEN, name = "Long");
AddOrder(OrderType.SELL_TO_CLOSE, BuyExit, open[-1], TradeSize, Color.RED, Color.RED, name = "Close");
AddOrder(OrderType.SELL_TO_OPEN, SellSignal, open[-1], TradeSize, Color.ORANGE, Color.ORANGE, name = "Short");
AddOrder(OrderType.BUY_TO_CLOSE, SellExit, open[-1], TradeSize, Color.WHITE, Color.WHITE, name = "Close");
#======== PLOTS ============================================================================

plot BullPSAR = if SAR < close then SAR else Double.NaN;
BullPSAR.SetPaintingStrategy(PaintingStrategy.POINTS);
BullPSAR.SetDefaultColor(Color.LIME);

plot BearPSAR = if SAR > close then SAR else Double.NaN;
BearPSAR.SetPaintingStrategy(PaintingStrategy.POINTS);
BearPSAR.SetDefaultColor(Color.PINK);

#---

def BullSignalAtCandle = Crosses(SAR, close, CrossingDirection.BELOW);
plot BullSignalAtPSAR = if close crosses above SAR
then SAR
else Double.NaN;
BullSignalAtPSAR.SetLineWeight(1);
BullSignalAtPSAR.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
BullSignalAtPSAR.SetDefaultColor(Color.LIME);

def BearSignalAtCandle = Crosses(SAR, close, CrossingDirection.ABOVE);
plot BearSignalAtPSAR = if close crosses below SAR
then SAR
else Double.NaN;
BearSignalAtPSAR.SetLineWeight(1);
BearSignalAtPSAR.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
BearSignalAtPSAR.SetDefaultColor(Color.PINK);

#---

plot LongEntrySignal = if BuySignal then BuySignal else Double.NaN;
LongEntrySignal.SetDefaultColor(Color.UPTICK);
LongEntrySignal.SetLineWeight(5);
LongEntrySignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);


plot ShortEntrySignal = if SellSignal then SellSignal else Double.NaN;
ShortEntrySignal.SetDefaultColor(Color.DOWNTICK);
ShortEntrySignal.SetLineWeight(5);
ShortEntrySignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);

plot LongExitSignal = if BuyExit then BuyExit else Double.NaN;
LongExitSignal.SetDefaultColor(Color.White);
LongExitSignal.SetLineWeight(1);
LongExitSignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);


plot ShortExitSignal = if SellExit then SellExit else Double.NaN;
ShortExitSignal.SetDefaultColor(Color.White);
ShortExitSignal.SetLineWeight(1);
ShortExitSignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);



#======== ALERTS ===========================================================================

input AlertsOn = No;
Alert(AlertsOn and BullSignalAtCandle, "Bullish PSAR", Alert.BAR, Sound.Ring);
Alert(AlertsOn and BearSignalAtCandle, "Bearish PSAR", Alert.BAR, Sound.Ring);
Alert(AlertsOn and BuySignal, "Bullish PSAR above AVG", Alert.BAR, Sound.Ring);
Alert(AlertsOn and SellSignal, "Bullish PSAR below AVG", Alert.BAR, Sound.Ring);

#======== EOF ===========================================================================


I added an ADX into the equation so that the signals include when ADX > 25 but the results dropped instead .
 
# Parabolic_SAR_Moving_Average_Trading_Strategy

# by BabyTrader using the following article: Parabolic SAR Moving Average Trading Strategy

# https://tradingstrategyguides.com/parabolic-sar-moving-average-trade-strategy/

# ParabolicSAR_withAlerts_JQ
# 2018-04-15 Mods by Johnny Quotron
# with a very helpful kickstart from DMonkey
# Mods include
# 1. splitting the PSAR into two visible plots so that they can be colored seperately
# 2. adding alert arrows at the PSAR to enhance visibility
# a. original alert arrows remain available but are hidden by default
# 3. add ability to color color alert arrows
#

# Combined/Modified/Altered by SilverWolf


declare upper;

#======== Inputs ==============================================================================



input accelerationFactor = 0.012;
input accelerationLimit = 0.2;
input extremeoffset = 0.0;

input MovAvgType = AverageType.EXPONENTIAL;
input MovAvgTrendMethod = {default "SINGLE", "CROSSING"};
input CrossingAvgLength = 9;
input TrendTriggerAvgLength = 21;

input TradeClosingMethod = {default "SAR", "MOVAVG"};
input TradeSize = 1;
##this is to get ADX's level
#input ADXlength = 14;
#input averageType = AverageType.WILDERS;

def Trend = if MovAvgTrendMethod == MovAvgTrendMethod."SINGLE" then 1 else
if MovAvgTrendMethod == MovAvgTrendMethod."CROSSING" then 2 else 0;

def PlotCross = if Trend == 2 then yes else no;

def Closer = if TradeClosingMethod == TradeClosingMethod."SAR" then 1 else
if TradeClosingMethod == TradeClosingMethod."MOVAVG" then 2 else 0;


#======== ADX ==================================================================================
input adxLength = 14;
input CutOffLine = 25;
input averageType = AverageType.WILDERS;

plot adx = reference ADX(length = adxLength);



#======== Moving Averages ======================================================================

plot TriggerAVG = MovingAverage(MovAvgType, close, TrendTriggerAvgLength);
TriggerAVG.SetLineWeight(3);
TriggerAVG.SetDefaultColor(Color.WHITE);

plot CrossingAVG = MovingAverage(MovAvgType, close, CrossingAvgLength);
CrossingAVG.SetHiding(!PlotCross);
CrossingAVG.SetLineWeight(3);
CrossingAVG.SetDefaultColor(Color.PINK);

#======== ParabolicSAR =========================================================================

Assert(accelerationFactor > 0, "'acceleration factor' must be positive: " + accelerationFactor);
Assert(accelerationLimit >= accelerationFactor, "'acceleration limit' (" + accelerationLimit + ") must be greater than or equal to 'acceleration factor' (" + accelerationFactor + ")");

def state = {default init, long, short};
def extreme;
def SAR;
def acc;

switch (state[1]) {
case init:
state = state.long;
acc = accelerationFactor;
extreme = high;
SAR = low;
case short:
if (SAR[1] < high)
then {
state = state.long;
acc = accelerationFactor;
extreme = high + extremeoffset;
SAR = extreme[1];
} else {
state = state.short;
if (low < extreme[1])
then {
acc = Min(acc[1] + accelerationFactor, accelerationLimit);
extreme = low - extremeoffset;
} else {
acc = acc[1];
extreme = extreme[1];
}
SAR = Max(Max(high, high[1]), SAR[1] + acc * (extreme - SAR[1]));
}
case long:
if (SAR[1] > low)
then {
state = state.short;
acc = accelerationFactor;
extreme = low - extremeoffset;
SAR = extreme[1];
} else {
state = state.long;
if (high > extreme[1])
then {
acc = Min(acc[1] + accelerationFactor, accelerationLimit);
extreme = high + extremeoffset;
} else {
acc = acc[1];
extreme = extreme[1];
}
SAR = Min(Min(low, low[1]), SAR[1] + acc * (extreme - SAR[1]));
}
}


#======== SIGNALS =========================================================================


#def BuySignal = SAR crosses below close and ADX > ADX[-1];

def BuySignal = if Trend == 1 and (close > TriggerAVG ) and (SAR crosses below close) and ADX > ADX[-1]
then 1

else if Trend == 2 and (close > TriggerAVG) and (CrossingAVG crosses above TriggerAVG) and (SAR < close)

then 1
else Double.NaN;

#def SellSignal = SAR crosses below close and ADX < ADX[-1];
def SellSignal = if Trend == 1 and (close < TriggerAVG ) and (SAR crosses above close) and ADX < ADX[-1]
then 1

else if Trend == 2 and (close < TriggerAVG) and (CrossingAVG crosses below TriggerAVG) and (SAR > close)

then 1

else Double.NaN;


def BuyExit = if Closer == 1 and (close crosses below SAR[-1])

then 1

else if Closer == 2 and (TriggerAVG > CrossingAVG)

then 1

else Double.NaN;


def SellExit = if Closer == 1 and (close crosses above SAR[-1])

then 1

else if Closer == 2 and (TriggerAVG < CrossingAVG)

then 1

else Double.NaN;


#======== STRATEGY ORDERS ===================================================================
AddOrder(OrderType.BUY_TO_OPEN, BuySignal, open[-1], TradeSize, Color.GREEN, Color.GREEN, name = "Long");
AddOrder(OrderType.SELL_TO_CLOSE, BuyExit, open[-1], TradeSize, Color.RED, Color.RED, name = "Close");
AddOrder(OrderType.SELL_TO_OPEN, SellSignal, open[-1], TradeSize, Color.ORANGE, Color.ORANGE, name = "Short");
AddOrder(OrderType.BUY_TO_CLOSE, SellExit, open[-1], TradeSize, Color.WHITE, Color.WHITE, name = "Close");
#======== PLOTS ============================================================================

plot BullPSAR = if SAR < close then SAR else Double.NaN;
BullPSAR.SetPaintingStrategy(PaintingStrategy.POINTS);
BullPSAR.SetDefaultColor(Color.LIME);

plot BearPSAR = if SAR > close then SAR else Double.NaN;
BearPSAR.SetPaintingStrategy(PaintingStrategy.POINTS);
BearPSAR.SetDefaultColor(Color.PINK);

#---

def BullSignalAtCandle = Crosses(SAR, close, CrossingDirection.BELOW);
plot BullSignalAtPSAR = if close crosses above SAR
then SAR
else Double.NaN;
BullSignalAtPSAR.SetLineWeight(1);
BullSignalAtPSAR.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
BullSignalAtPSAR.SetDefaultColor(Color.LIME);

def BearSignalAtCandle = Crosses(SAR, close, CrossingDirection.ABOVE);
plot BearSignalAtPSAR = if close crosses below SAR
then SAR
else Double.NaN;
BearSignalAtPSAR.SetLineWeight(1);
BearSignalAtPSAR.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
BearSignalAtPSAR.SetDefaultColor(Color.PINK);

#---

plot LongEntrySignal = if BuySignal then BuySignal else Double.NaN;
LongEntrySignal.SetDefaultColor(Color.UPTICK);
LongEntrySignal.SetLineWeight(5);
LongEntrySignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);


plot ShortEntrySignal = if SellSignal then SellSignal else Double.NaN;
ShortEntrySignal.SetDefaultColor(Color.DOWNTICK);
ShortEntrySignal.SetLineWeight(5);
ShortEntrySignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);

plot LongExitSignal = if BuyExit then BuyExit else Double.NaN;
LongExitSignal.SetDefaultColor(Color.White);
LongExitSignal.SetLineWeight(1);
LongExitSignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);


plot ShortExitSignal = if SellExit then SellExit else Double.NaN;
ShortExitSignal.SetDefaultColor(Color.White);
ShortExitSignal.SetLineWeight(1);
ShortExitSignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);



#======== ALERTS ===========================================================================

input AlertsOn = No;
Alert(AlertsOn and BullSignalAtCandle, "Bullish PSAR", Alert.BAR, Sound.Ring);
Alert(AlertsOn and BearSignalAtCandle, "Bearish PSAR", Alert.BAR, Sound.Ring);
Alert(AlertsOn and BuySignal, "Bullish PSAR above AVG", Alert.BAR, Sound.Ring);
Alert(AlertsOn and SellSignal, "Bullish PSAR below AVG", Alert.BAR, Sound.Ring);

#======== EOF ===========================================================================


MA Close , Parabolic SAR and increasing ADX / Decreasing ADX is ok albeit with slightly less results
 
Last edited:
How do you implement multiple timeframes into this Parabolic strategy ?


from
https://usethinkscript.com/threads/...verlay-for-thinkorswim.1425/page-2#post-14681

seems like you need to get from here :

_______________________________________________________

# Multi-Time-Frame Candle Overlay version 2.4
# 2020 Paul Townsend
# with code from UseThinkScript.com

input agg = AggregationPeriod.fifteen_min; #e.g. this can be the higher timeframe to aggregate e.g. for 1 min , one can pick 5 / 15 / 30 minutes according to TOS's specifications.
input OpenCloseLines = yes;
input HighLowLines = yes;
input HighLowGray = no;
input LineWeight =2;


addlabel(yes,"[" + agg/60000 + "]",color.white);

plot o = open(period = agg);
plot c = close(period = agg);
plot h = high(period = agg);
plot l = low(period = agg);


_________________________________________________________

Maybe can create a second subsection for PSAR and moving average then aggregate from there?
have all the parameters for the same parabolicSAR subsection be named to _higherTimeframe or something likethat
The same goes for Moving average

then for the buying selling signals , the conditions would double for all the conditions to include similar conditions but in a higher timeframe


#======== ParabolicSAR(higher) =========================================================================

Assert(accelerationFactor > 0, "'acceleration factor' must be positive: " + accelerationFactor);
Assert(accelerationLimit >= accelerationFactor, "'acceleration limit' (" + accelerationLimit + ") must be greater than or equal to 'acceleration factor' (" + accelerationFactor + ")");

def state = {default init, long, short};
def extreme;
def SAR;
def acc;

switch (state[1]) {
case init:
state = state.long;
acc = accelerationFactor;
extreme = high;
SAR = low;
case short:
if (SAR[1] < high)
then {
state = state.long;
acc = accelerationFactor;
extreme = high + extremeoffset;
SAR = extreme[1];
} else {
state = state.short;
if (low < extreme[1])
then {
acc = Min(acc[1] + accelerationFactor, accelerationLimit);
extreme = low - extremeoffset;
} else {
acc = acc[1];
extreme = extreme[1];
}
SAR = Max(Max(high, high[1]), SAR[1] + acc * (extreme - SAR[1]));
}
case long:
if (SAR[1] > low)
then {
state = state.short;
acc = accelerationFactor;
extreme = low - extremeoffset;
SAR = extreme[1];
} else {
state = state.long;
if (high > extreme[1])
then {
acc = Min(acc[1] + accelerationFactor, accelerationLimit);
extreme = high + extremeoffset;
} else {
acc = acc[1];
extreme = extreme[1];
}
SAR = Min(Min(low, low[1]), SAR[1] + acc * (extreme - SAR[1]));
}
}


#======== Moving Averages (higher) ======================================================================

plot TriggerAVG = MovingAverage(MovAvgType, close, TrendTriggerAvgLength);
TriggerAVG.SetLineWeight(3);
TriggerAVG.SetDefaultColor(Color.WHITE);

plot CrossingAVG = MovingAverage(MovAvgType, close, CrossingAvgLength);
CrossingAVG.SetHiding(!PlotCross);
CrossingAVG.SetLineWeight(3);
CrossingAVG.SetDefaultColor(Color.PINK);
 
How do you implement multiple timeframes into this Parabolic strategy ?


from
https://usethinkscript.com/threads/...verlay-for-thinkorswim.1425/page-2#post-14681

seems like you need to get from here :

_______________________________________________________

# Multi-Time-Frame Candle Overlay version 2.4
# 2020 Paul Townsend
# with code from UseThinkScript.com

input agg = AggregationPeriod.fifteen_min; #e.g. this can be the higher timeframe to aggregate e.g. for 1 min , one can pick 5 / 15 / 30 minutes according to TOS's specifications.
input OpenCloseLines = yes;
input HighLowLines = yes;
input HighLowGray = no;
input LineWeight =2;


addlabel(yes,"[" + agg/60000 + "]",color.white);

plot o = open(period = agg);
plot c = close(period = agg);
plot h = high(period = agg);
plot l = low(period = agg);


_________________________________________________________

Maybe can create a second subsection for PSAR and moving average then aggregate from there?
have all the parameters for the same parabolicSAR subsection be named to _higherTimeframe or something likethat
The same goes for Moving average

then for the buying selling signals , the conditions would double for all the conditions to include similar conditions but in a higher timeframe


#======== ParabolicSAR(higher) =========================================================================

Assert(accelerationFactor > 0, "'acceleration factor' must be positive: " + accelerationFactor);
Assert(accelerationLimit >= accelerationFactor, "'acceleration limit' (" + accelerationLimit + ") must be greater than or equal to 'acceleration factor' (" + accelerationFactor + ")");

def state = {default init, long, short};
def extreme;
def SAR;
def acc;

switch (state[1]) {
case init:
state = state.long;
acc = accelerationFactor;
extreme = high;
SAR = low;
case short:
if (SAR[1] < high)
then {
state = state.long;
acc = accelerationFactor;
extreme = high + extremeoffset;
SAR = extreme[1];
} else {
state = state.short;
if (low < extreme[1])
then {
acc = Min(acc[1] + accelerationFactor, accelerationLimit);
extreme = low - extremeoffset;
} else {
acc = acc[1];
extreme = extreme[1];
}
SAR = Max(Max(high, high[1]), SAR[1] + acc * (extreme - SAR[1]));
}
case long:
if (SAR[1] > low)
then {
state = state.short;
acc = accelerationFactor;
extreme = low - extremeoffset;
SAR = extreme[1];
} else {
state = state.long;
if (high > extreme[1])
then {
acc = Min(acc[1] + accelerationFactor, accelerationLimit);
extreme = high + extremeoffset;
} else {
acc = acc[1];
extreme = extreme[1];
}
SAR = Min(Min(low, low[1]), SAR[1] + acc * (extreme - SAR[1]));
}
}


#======== Moving Averages (higher) ======================================================================

plot TriggerAVG = MovingAverage(MovAvgType, close, TrendTriggerAvgLength);
TriggerAVG.SetLineWeight(3);
TriggerAVG.SetDefaultColor(Color.WHITE);

plot CrossingAVG = MovingAverage(MovAvgType, close, CrossingAvgLength);
CrossingAVG.SetHiding(!PlotCross);
CrossingAVG.SetLineWeight(3);
CrossingAVG.SetDefaultColor(Color.PINK);
Sounds interesting.. See if you can do it. Id like to check it out.
 
another idea is your trend break idea . got to go sleep , day 2 of CNY hahaha.

I think the problem with multi timeframe is that it would repaint so there isn't an easy way to deal with it . @MerryDay Could you share your opinion on this ?
 
another idea is your trend break idea . got to go sleep , day 2 of CNY hahaha.

I think the problem with multi timeframe is that it would repaint so there isn't an easy way to deal with it . @MerryDay Could you share your opinion on this ?
An MTF study is type of repainter. Think about it. You have a 30-min overlay on a five-min chart. There is no way of predicting at what price that 30min candle is going to close. When the 30min candle finally closes, only then can it repaint the previous 6 bars with the 30min close price that you requested."
 
If you change the strategy order code to this below it will allow the trades to be named with the logic options that were used to take that trade.

CSS:
AddOrder(OrderType.BUY_TO_OPEN, BuySignal, open[-1], TradeSize, Color.GREEN, Color.GREEN, name = "Long L" + Logic + " T" + Trend);

AddOrder(OrderType.SELL_TO_CLOSE, BuyExit, open[-1], TradeSize, Color.RED, Color.RED, name = "Close L" + Logic + " C" + Closer);

AddOrder(OrderType.SELL_TO_OPEN, SellSignal, open[-1], TradeSize, Color.ORANGE, Color.ORANGE, name = "Short L" + Logic + " T" + Trend);

AddOrder(OrderType.BUY_TO_CLOSE, SellExit, open[-1], TradeSize, Color.WHITE, Color.WHITE, name = "Close L" + Logic + " C" + Closer);

L1 would indicate Logic 1 condition from the signal portion of code
C1 would indicate Closer 1
T2 would indicate Trend 2

Here are some successful examples:
- Adx Logic 1 (adx is above filter) Here you can see price is trending
LgQHd9c.png



- ADX Logic 2 (adx is below filter) Here you can see sideways price action and the strat is trading perfectly.
xdJFeCU.png



By making that simple amendment you can better set up your strategy for the specific stock or future you are trading.
 
@SilverWolf, thanks for all your time in developing this strategy. Been learning a lot from this thread.

I am not a coder. But i am lost in understandibng this line of logic.Can you help me. Thanks.

def TrendingUp = if "DI-" > ADX and ADX > "DI+"

then 1

else Double.NaN;

def TrendingDown = if "DI-" > ADX and ADX > "DI+"

then 1
 
@SilverWolf, thanks for all your time in developing this strategy. Been learning a lot from this thread.

I am not a coder. But i am lost in understandibng this line of logic.Can you help me. Thanks.

def TrendingUp = if "DI-" > ADX and ADX > "DI+"

then 1

else Double.NaN;

def TrendingDown = if "DI-" > ADX and ADX > "DI+"

then 1
Thanks for asking.. I havent implemented the DI trend additions yet.. those are still a work in progress. In fact.. TrendingUp and TrendingDown are defined the same there lol..

Eventually I will add an option to further filter trades with those definitions. To help refine trending status.

v8bVtcc.png


Here is a snip of DMI that is built into TOS.. Green is DI+ Red is DI- and Yellow is ADX. When DI+ and ADX are both above DI- then the price is trending up. so Corrected code would look something like:

CSS:
def TrendingUp = if "DI-" < ADX and "DI+" > ADX

then 1

else Double.NaN;

def TrendingDown = if "DI-" > ADX and "DI+" < ADX

then 1

else Double.NaN;
 
Last edited:
Improved/Corrected Entry and Exit orders. Works well on mobile too

CSS:
# Parabolic_SAR_Moving_Average_Trading_Strategy

# by BabyTrader using the following article: Parabolic SAR Moving Average Trading Strategy

# https://tradingstrategyguides.com/parabolic-sar-moving-average-trade-strategy/

# ParabolicSAR_withAlerts_JQ
# 2018-04-15 Mods by Johnny Quotron
#    with a very helpful kickstart from DMonkey
# Mods include
#    1. splitting the PSAR into two visible plots so that they can be colored seperately
#    2. adding alert arrows at the PSAR to enhance visibility
#        a. original alert arrows remain available but are hidden by default
#    3. add ability to color color alert arrows
#

# Combined/Modified/Altered by SilverWolf


declare upper;

#======== Inputs ==============================================================================



input accelerationFactor = 0.012;
input accelerationLimit = 0.2;
input extremeoffset = 0.0;

input MovAvgType = AverageType.EXPONENTIAL;
input MovAvgTrendMethod = {default "SINGLE", "CROSSING"};
input CrossingAvgLength = 9;
input TrendTriggerAvgLength = 21;

input TradeClosingMethod = {default "SAR", "MOVAVG"};
input TradeSize = 1;

def Trend = if MovAvgTrendMethod == MovAvgTrendMethod."SINGLE" then 1 else
            if MovAvgTrendMethod == MovAvgTrendMethod."CROSSING" then 2 else 0;

def PlotCross = if Trend == 2 then yes else no;

def Closer = if TradeClosingMethod == TradeClosingMethod."SAR" then 1 else
             if TradeClosingMethod == TradeClosingMethod."MOVAVG" then 2 else 0;




#======== Moving Averages ======================================================================

plot TriggerAVG = MovingAverage(MovAvgType, close, TrendTriggerAvgLength);
TriggerAVG.SetLineWeight(3);
TriggerAVG.SetDefaultColor(Color.WHITE);

plot CrossingAVG = MovingAverage(MovAvgType, close, CrossingAvgLength);
CrossingAVG.SetHiding(!PlotCross);
CrossingAVG.SetLineWeight(3);
CrossingAVG.SetDefaultColor(Color.PINK);

#======== ParabolicSAR =========================================================================

Assert(accelerationFactor > 0, "'acceleration factor' must be positive: " + accelerationFactor);
Assert(accelerationLimit >= accelerationFactor, "'acceleration limit' (" + accelerationLimit + ") must be greater than or equal to 'acceleration factor' (" + accelerationFactor + ")");

def state = {default init, long, short};
def extreme;
def SAR;
def acc;

switch (state[1]) {
case init:
    state = state.long;
    acc = accelerationFactor;
    extreme = high;
    SAR = low;
case short:
    if (SAR[1] < high)
    then {
        state = state.long;
        acc = accelerationFactor;
        extreme = high + extremeoffset;
        SAR = extreme[1];
    } else {
        state = state.short;
        if (low < extreme[1])
        then {
            acc = Min(acc[1] + accelerationFactor, accelerationLimit);
            extreme = low - extremeoffset;
        } else {
            acc = acc[1];
            extreme = extreme[1];
        }
        SAR = Max(Max(high, high[1]), SAR[1] + acc * (extreme - SAR[1]));
    }
case long:
    if (SAR[1] > low)
    then {
        state = state.short;
        acc = accelerationFactor;
        extreme = low - extremeoffset;
        SAR = extreme[1];
    } else {
        state = state.long;
        if (high > extreme[1])
        then {
            acc = Min(acc[1] + accelerationFactor, accelerationLimit);
            extreme = high + extremeoffset;
        } else {
            acc = acc[1];
            extreme = extreme[1];
        }
        SAR = Min(Min(low, low[1]), SAR[1] + acc * (extreme - SAR[1]));
    }
}


#======== SIGNALS =========================================================================




def BuySignal = if Trend == 1 and (close > TriggerAVG ) and (SAR crosses below close)

then 1

else if Trend == 2 and (close > TriggerAVG) and (CrossingAVG crosses above TriggerAVG) and (SAR < close)

then 1
else Double.NaN;


def SellSignal = if Trend == 1 and (close < TriggerAVG ) and (SAR crosses above close)

then 1

else if Trend == 2 and (close < TriggerAVG) and (CrossingAVG crosses below TriggerAVG) and (SAR > close)

then 1

else Double.NaN;


def BuyExit = if Closer == 1 and (close crosses below SAR[-1])

then 1

else if Closer == 2 and (TriggerAVG > CrossingAVG)

then 1

else Double.NaN;


def SellExit = if Closer == 1 and (close crosses above SAR[-1])

then 1

else if Closer == 2 and (TriggerAVG < CrossingAVG)

then 1

else Double.NaN;


#======== STRATEGY ORDERS ===================================================================
AddOrder(OrderType.BUY_TO_OPEN, BuySignal, open[-1], TradeSize, Color.GREEN, Color.GREEN, name = "Long");
AddOrder(OrderType.SELL_TO_CLOSE, BuyExit, open[-1], TradeSize, Color.RED, Color.RED, name = "Close");
AddOrder(OrderType.SELL_TO_OPEN, SellSignal, open[-1], TradeSize, Color.ORANGE, Color.ORANGE, name = "Short");
AddOrder(OrderType.BUY_TO_CLOSE, SellExit, open[-1], TradeSize, Color.WHITE, Color.WHITE, name = "Close");
#======== PLOTS ============================================================================

plot BullPSAR = if SAR < close then SAR else Double.NaN;
BullPSAR.SetPaintingStrategy(PaintingStrategy.POINTS);
BullPSAR.SetDefaultColor(Color.LIME);

plot BearPSAR = if SAR > close then SAR else Double.NaN;
BearPSAR.SetPaintingStrategy(PaintingStrategy.POINTS);
BearPSAR.SetDefaultColor(Color.PINK);

#---

def BullSignalAtCandle = Crosses(SAR, close, CrossingDirection.BELOW);
plot BullSignalAtPSAR = if close crosses above SAR
                     then SAR
                     else Double.NaN;
BullSignalAtPSAR.SetLineWeight(1);
BullSignalAtPSAR.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
BullSignalAtPSAR.SetDefaultColor(Color.LIME);

def BearSignalAtCandle = Crosses(SAR, close, CrossingDirection.ABOVE);
plot BearSignalAtPSAR = if close crosses below SAR
                     then SAR
                     else Double.NaN;
BearSignalAtPSAR.SetLineWeight(1);
BearSignalAtPSAR.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
BearSignalAtPSAR.SetDefaultColor(Color.PINK);

#---

plot LongEntrySignal = if BuySignal then BuySignal else Double.NaN;
LongEntrySignal.SetDefaultColor(Color.UPTICK);
LongEntrySignal.SetLineWeight(5);
LongEntrySignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);


plot ShortEntrySignal = if SellSignal then SellSignal else Double.NaN;
ShortEntrySignal.SetDefaultColor(Color.DOWNTICK);
ShortEntrySignal.SetLineWeight(5);
ShortEntrySignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);

plot LongExitSignal = if BuyExit then BuyExit else Double.NaN;
LongExitSignal.SetDefaultColor(Color.White);
LongExitSignal.SetLineWeight(1);
LongExitSignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);


plot ShortExitSignal = if SellExit then SellExit else Double.NaN;
ShortExitSignal.SetDefaultColor(Color.White);
ShortExitSignal.SetLineWeight(1);
ShortExitSignal.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);


#======== ALERTS ===========================================================================

input AlertsOn = No;
Alert(AlertsOn and BullSignalAtCandle, "Bullish PSAR", Alert.BAR, Sound.Ring);
Alert(AlertsOn and BearSignalAtCandle, "Bearish PSAR", Alert.BAR, Sound.Ring);
Alert(AlertsOn and BuySignal, "Bullish PSAR above AVG", Alert.BAR, Sound.Ring);
Alert(AlertsOn and SellSignal, "Bullish PSAR below AVG", Alert.BAR, Sound.Ring);

#======== EOF ===========================================================================
Nothing is opening on my chart, what am i missing ? DISREGARD, Added it as strategy
 
Last edited:

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

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