Combining two indicators into one strategy

Jack Sprat

New member
Hi everyone~
I've been trying to write a strategy combining the PSAR and the MA Crossover indicators listed below. For the past week I've been trying to write a way to place an order when :

1. PSAR is bullish and fast MA has crossed over slow MA
2. PSAR is bearish and slow MA has crossed over fast MA

but for the life of me I can't seem to get agreement when both occur on one chart versus plotting each on separate charts. Any help would be greatly greatly appreciated. I have been able to get the first condition but still no luck on the second.

# This study looks for a PSAR state transition (either from bullish to bearish
# or vice versa) and plots a horizontal price line into the expansion area. If
# the state transition already triggered, it calculates the number of bars ago
# the event happened. I've included labels, alerts as well as chart bubbles

input accelerationFactor = 0.02;
input accelerationLimit = 0.2;
input offSet = 2;

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 bar = BarNumber();
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;
SAR = extreme[1];
} else {
state = state.short;
if (low < extreme[1])
then {
acc = Min(acc[1] + accelerationFactor, accelerationLimit);
extreme = low;
} 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;
SAR = extreme[1];
} else {
state = state.long;
if (high > extreme[1])
then {
acc = Min(acc[1] + accelerationFactor, accelerationLimit);
extreme = high;
} else {
acc = acc[1];
extreme = extreme[1];
}
SAR = Min(Min(low, low[1]), SAR[1] + acc * (extreme - SAR[1]));
}
}

plot parSAR = SAR;
parSAR.SetPaintingStrategy(PaintingStrategy.POINTS);
parSAR.SetDefaultColor(GetColor(5));
def transitionBull = state[1] == state.short and state == state.long;
def transitionBear = state[1] == state.long and state == state.short;
def transitionBar = if transitionBull or transitionBear
then bar
else transitionBar[1];
def transitionPrice = if bar == (transitionBar)
then close
else transitionPrice[1];
def transitionBarsAgo = if bar != transitionBar
then bar - transitionBar
else if bar == transitionBar
then Double.NaN
else transitionBarsAgo[1];
def timeAxis = if IsNaN(close[-1]) and !IsNaN(close) then bar else timeAxis[1];
def hline = if GetTime() <= RegularTradingEnd(GetYYYYMMDD()) and
transitionBar == (transitionBar)
then transitionPrice
else hline[1];
plot horizLine = hline;
horizLine.SetLineWeight(2);
horizLine.SetDefaultColor(Color.YELLOW);
AddLabel(transitionBull or transitionBear, "PSAR Transition Detected Now!", Color.YELLOW);
AddLabel(!(transitionBull or transitionBear), "PSAR Transition " + transitionBarsAgo + " bars ago", Color.CYAN);
Alert(transitionBull, "PSAR Transition Bull", Alert.BAR, Sound.Ding);
Alert(transitionBear, "PSAR Transition Bear", Alert.BAR, Sound.Ring);
AddChartBubble(bar == HighestAll(timeAxis + offSet), transitionPrice, "PSAR\nTransitioned", Color.WHITE);

input showpricecolor = yes;
def bull = if transitionBull then 1 else if bull[1] == 1 and !transitionBear then 1 else 0;
AssignPriceColor(if !showpricecolor then Color.CURRENT else if bull and close > hline then Color.WHITE else if !bull and close < hline then Color.RED else Color.BLACK);

def cond11 = if bull and close > hline then 1 else 0;
def cond22 = if !bull and close < hline then 1 else 0;

#addverticalline( cond11, "UP", color.green, curve.firm );
#addverticalline( cond22, "DOWN", color.red, curve.firm );

#AssignBackgroundColor(if cond11 then color.light_green else if cond22 then color.light_red else Color.BLACK);

input EMAPeriod = 10;
input EMAPeriod2 = 21;
input price = close;
def na = Double.NaN;

plot fastema = ExpAverage(price, EMAPeriod);
plot slowema = ExpAverage(price, EMAPeriod2);
def crossover = if fastema > slowema and fastema[1] <= slowema[1] then 1 else 0;
def crossunder = if fastema < slowema and fastema[1] >= slowema[1] then 1 else 0;

#Plot arrows
plot up = if crossover then low - TickSize() else na;
plot down = if crossunder then high + TickSize() else na;
up.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
down.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);

#Trigger alerts
Alert(crossover[1], "Crossover", Alert.BAR, Sound.Bell);
Alert(crossunder[1], "Crossunder", Alert.BAR, Sound.Bell);

#BUY
plot sma1 = cond11;
plot sma2 = crossover;
def cond1 = cond11 and crossover;
def close1 = if cond1 then close else close1[1];
plot cond2 = if cond1 and close > close1[1] then 1 else 0;
cond2.setpaintingstrategy(paintingstrategy.boolean_arrow_up);
input debug = yes;
addchartbubble(debug and cond1, high, close1, color.white);

#SELL
plot sma11 = cond22;
plot sma22 = crossunder;
def cond3 = cond22 and crossunder;
def close2 = if cond3 then close else close2[1];
plot cond4 = if cond3 and close > close2[1] then 1 else 0;
cond4.setpaintingstrategy(paintingstrategy.boolean_arrow_down);
addchartbubble(debug and cond3, low, close2, color.red);

#addorder(ordertype.buy_TO_CLOSE, cond2);
#AddOrder(OrderType.BUY_AUTO, cond2);
#addOrder(OrderType.SELL_TO_CLOSE, cond4);
#addOrder(OrderType.SELL_AUTO, cond4);
 
Last edited:
Solution
Hi everyone~
I've been trying to write a strategy combining the PSAR and the MA Crossover indicators listed below. For the past week I've been trying to write a way to place an order when :

1. PSAR is bullish and fast MA has crossed over slow MA
2. PSAR is bearish and slow MA has crossed over fast MA

but for the life of me I can't seem to get agreement when both occur on one chart versus plotting each on separate charts. Any help would be greatly greatly appreciated. I have been able to get the first condition but still no luck on the second.

# This study looks for a PSAR state transition (either from bullish to bearish
# or vice versa) and plots a horizontal price line into the expansion area. If
# the state transition already...
Hi everyone~
I've been trying to write a strategy combining the PSAR and the MA Crossover indicators listed below. For the past week I've been trying to write a way to place an order when :

1. PSAR is bullish and fast MA has crossed over slow MA
2. PSAR is bearish and slow MA has crossed over fast MA

but for the life of me I can't seem to get agreement when both occur on one chart versus plotting each on separate charts. Any help would be greatly greatly appreciated. I have been able to get the first condition but still no luck on the second.

# This study looks for a PSAR state transition (either from bullish to bearish
# or vice versa) and plots a horizontal price line into the expansion area. If
# the state transition already triggered, it calculates the number of bars ago
# the event happened. I've included labels, alerts as well as chart bubbles

input accelerationFactor = 0.02;
input accelerationLimit = 0.2;
input offSet = 2;

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 bar = BarNumber();
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;
SAR = extreme[1];
} else {
state = state.short;
if (low < extreme[1])
then {
acc = Min(acc[1] + accelerationFactor, accelerationLimit);
extreme = low;
} 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;
SAR = extreme[1];
} else {
state = state.long;
if (high > extreme[1])
then {
acc = Min(acc[1] + accelerationFactor, accelerationLimit);
extreme = high;
} else {
acc = acc[1];
extreme = extreme[1];
}
SAR = Min(Min(low, low[1]), SAR[1] + acc * (extreme - SAR[1]));
}
}

plot parSAR = SAR;
parSAR.SetPaintingStrategy(PaintingStrategy.POINTS);
parSAR.SetDefaultColor(GetColor(5));
def transitionBull = state[1] == state.short and state == state.long;
def transitionBear = state[1] == state.long and state == state.short;
def transitionBar = if transitionBull or transitionBear
then bar
else transitionBar[1];
def transitionPrice = if bar == (transitionBar)
then close
else transitionPrice[1];
def transitionBarsAgo = if bar != transitionBar
then bar - transitionBar
else if bar == transitionBar
then Double.NaN
else transitionBarsAgo[1];
def timeAxis = if IsNaN(close[-1]) and !IsNaN(close) then bar else timeAxis[1];
def hline = if GetTime() <= RegularTradingEnd(GetYYYYMMDD()) and
transitionBar == (transitionBar)
then transitionPrice
else hline[1];
plot horizLine = hline;
horizLine.SetLineWeight(2);
horizLine.SetDefaultColor(Color.YELLOW);
AddLabel(transitionBull or transitionBear, "PSAR Transition Detected Now!", Color.YELLOW);
AddLabel(!(transitionBull or transitionBear), "PSAR Transition " + transitionBarsAgo + " bars ago", Color.CYAN);
Alert(transitionBull, "PSAR Transition Bull", Alert.BAR, Sound.Ding);
Alert(transitionBear, "PSAR Transition Bear", Alert.BAR, Sound.Ring);
AddChartBubble(bar == HighestAll(timeAxis + offSet), transitionPrice, "PSAR\nTransitioned", Color.WHITE);

input showpricecolor = yes;
def bull = if transitionBull then 1 else if bull[1] == 1 and !transitionBear then 1 else 0;
AssignPriceColor(if !showpricecolor then Color.CURRENT else if bull and close > hline then Color.WHITE else if !bull and close < hline then Color.RED else Color.BLACK);

def cond11 = if bull and close > hline then 1 else 0;
def cond22 = if !bull and close < hline then 1 else 0;

#addverticalline( cond11, "UP", color.green, curve.firm );
#addverticalline( cond22, "DOWN", color.red, curve.firm );

#AssignBackgroundColor(if cond11 then color.light_green else if cond22 then color.light_red else Color.BLACK);

input EMAPeriod = 10;
input EMAPeriod2 = 21;
input price = close;
def na = Double.NaN;

plot fastema = ExpAverage(price, EMAPeriod);
plot slowema = ExpAverage(price, EMAPeriod2);
def crossover = if fastema > slowema and fastema[1] <= slowema[1] then 1 else 0;
def crossunder = if fastema < slowema and fastema[1] >= slowema[1] then 1 else 0;

#Plot arrows
plot up = if crossover then low - TickSize() else na;
plot down = if crossunder then high + TickSize() else na;
up.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
down.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);

#Trigger alerts
Alert(crossover[1], "Crossover", Alert.BAR, Sound.Bell);
Alert(crossunder[1], "Crossunder", Alert.BAR, Sound.Bell);

#BUY
plot sma1 = cond11;
plot sma2 = crossover;
def cond1 = cond11 and crossover;
def close1 = if cond1 then close else close1[1];
plot cond2 = if cond1 and close > close1[1] then 1 else 0;
cond2.setpaintingstrategy(paintingstrategy.boolean_arrow_up);
input debug = yes;
addchartbubble(debug and cond1, high, close1, color.white);

#SELL
plot sma11 = cond22;
plot sma22 = crossunder;
def cond3 = cond22 and crossunder;
def close2 = if cond3 then close else close2[1];
plot cond4 = if cond3 and close > close2[1] then 1 else 0;
cond4.setpaintingstrategy(paintingstrategy.boolean_arrow_down);
addchartbubble(debug and cond3, low, close2, color.red);

#addorder(ordertype.buy_TO_CLOSE, cond2);
#AddOrder(OrderType.BUY_AUTO, cond2);
#addOrder(OrderType.SELL_TO_CLOSE, cond4);
#addOrder(OrderType.SELL_AUTO, cond4);


this might help. take a look at the last code lines to see what i used for logic to represent the 2 signals.

i changed some lines and added code to the end.
--------------------------
problem. 4 booleans were plotted. they were drawing lines at 0 and 1. this caused the chart candles to appear tiny.

fix,
change 4 plots to def. this caused the chart to appear as it should.

#BUY
#plot sma1 = cond11;
#plot sma2 = crossover;
def sma1 = cond11;
def sma2 = crossover;

#SELL
#plot sma11 = cond22;
#plot sma22 = crossunder;
def sma11 = cond22;
def sma22 = crossunder;

----------------------

create rows of dots to represent the logic of 2 signals, psar and ma.
find the lowest low and use that as a reference for the dot rows.
top row, psar logic, green if true
2nd row, green if fast is above slow
bottom row, combined logic. if both true(green), then true(green)



Ruby:
# combine_psar_ma_01


#https://usethinkscript.com/threads/combining-two-indicators-into-one-strategy.9136/
#Combining two indicators into one strategy
#Jack Sprat  12/5 at 9:08 AM

# I've been trying to write a strategy combining the PSAR and the MA Crossover indicators listed below.
# For the past week I've been trying to write a way to place an order when :

# 1. PSAR is bullish and fast MA has crossed over slow MA
# 2. PSAR is bearish and slow MA has crossed over fast MA

# but for the life of me I can't seem to get agreement when both occur on one chart versus plotting each on separate charts.
# Any help would be greatly greatly appreciated. I have been able to get the first condition but still no luck on the second.


# This study looks for a PSAR state transition (either from bullish to bearish
# or vice versa) and plots a horizontal price line into the expansion area. If
# the state transition already triggered, it calculates the number of bars ago
# the event happened. I've included labels, alerts as well as chart bubbles

def bn = barnumber();

input accelerationFactor = 0.02;
input accelerationLimit = 0.2;
input offSet = 2;

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 bar = BarNumber();
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;
SAR = extreme[1];
} else {
state = state.short;
if (low < extreme[1])
then {
acc = Min(acc[1] + accelerationFactor, accelerationLimit);
extreme = low;
} 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;
SAR = extreme[1];
} else {
state = state.long;
if (high > extreme[1])
then {
acc = Min(acc[1] + accelerationFactor, accelerationLimit);
extreme = high;
} else {
acc = acc[1];
extreme = extreme[1];
}
SAR = Min(Min(low, low[1]), SAR[1] + acc * (extreme - SAR[1]));
}
}

plot parSAR = SAR;
parSAR.SetPaintingStrategy(PaintingStrategy.POINTS);
parSAR.SetDefaultColor(GetColor(5));
def transitionBull = state[1] == state.short and state == state.long;
def transitionBear = state[1] == state.long and state == state.short;
def transitionBar = if transitionBull or transitionBear
then bar
else transitionBar[1];
def transitionPrice = if bar == (transitionBar)
then close
else transitionPrice[1];
def transitionBarsAgo = if bar != transitionBar
then bar - transitionBar
else if bar == transitionBar
then Double.NaN
else transitionBarsAgo[1];
def timeAxis = if IsNaN(close[-1]) and !IsNaN(close) then bar else timeAxis[1];
def hline = if GetTime() <= RegularTradingEnd(GetYYYYMMDD()) and
transitionBar == (transitionBar)
then transitionPrice
else hline[1];
plot horizLine = hline;
horizLine.SetLineWeight(2);
horizLine.SetDefaultColor(Color.YELLOW);
AddLabel(transitionBull or transitionBear, "PSAR Transition Detected Now!", Color.YELLOW);
AddLabel(!(transitionBull or transitionBear), "PSAR Transition " + transitionBarsAgo + " bars ago", Color.CYAN);
Alert(transitionBull, "PSAR Transition Bull", Alert.BAR, Sound.Ding);
Alert(transitionBear, "PSAR Transition Bear", Alert.BAR, Sound.Ring);
AddChartBubble(bar == HighestAll(timeAxis + offSet), transitionPrice, "PSAR\nTransitioned", Color.WHITE);

input showpricecolor = yes;
def bull = if transitionBull then 1 else if bull[1] == 1 and !transitionBear then 1 else 0;
AssignPriceColor(if !showpricecolor then Color.CURRENT else if bull and close > hline then Color.WHITE else if !bull and close < hline then Color.RED else Color.BLACK);

def cond11 = if bull and close > hline then 1 else 0;
def cond22 = if !bull and close < hline then 1 else 0;

#addverticalline( cond11, "UP", color.green, curve.firm );
#addverticalline( cond22, "DOWN", color.red, curve.firm );

#AssignBackgroundColor(if cond11 then color.light_green else if cond22 then color.light_red else Color.BLACK);

input EMAPeriod = 10;
input EMAPeriod2 = 21;
input price = close;
def na = Double.NaN;

plot fastema = ExpAverage(price, EMAPeriod);
plot slowema = ExpAverage(price, EMAPeriod2);
def crossover = if fastema > slowema and fastema[1] <= slowema[1] then 1 else 0;
def crossunder = if fastema < slowema and fastema[1] >= slowema[1] then 1 else 0;

#Plot arrows
plot up = if crossover then low - TickSize() else na;
plot down = if crossunder then high + TickSize() else na;
up.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
down.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);

#Trigger alerts
Alert(crossover[1], "Crossover", Alert.BAR, Sound.Bell);
Alert(crossunder[1], "Crossunder", Alert.BAR, Sound.Bell);


#====================
# change 4 plots to def.  so not plotting boolean values, 0/1

#BUY
#plot sma1 = cond11;
#plot sma2 = crossover;
def sma1 = cond11;
def sma2 = crossover;

def cond1 = cond11 and crossover;
def close1 = if cond1 then close else close1[1];
plot cond2 = if cond1 and close > close1[1] then 1 else 0;
cond2.setpaintingstrategy(paintingstrategy.boolean_arrow_up);
input debug = yes;
addchartbubble(debug and cond1, high, close1, color.white);

#SELL
#plot sma11 = cond22;
#plot sma22 = crossunder;
def sma11 = cond22;
def sma22 = crossunder;

def cond3 = cond22 and crossunder;
def close2 = if cond3 then close else close2[1];
plot cond4 = if cond3 and close > close2[1] then 1 else 0;
cond4.setpaintingstrategy(paintingstrategy.boolean_arrow_down);
addchartbubble(debug and cond3, low, close2, color.red);

#addorder(ordertype.buy_TO_CLOSE, cond2);
#AddOrder(OrderType.BUY_AUTO, cond2);
#addOrder(OrderType.SELL_TO_CLOSE, cond4);
#addOrder(OrderType.SELL_AUTO, cond4);

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


def lo = lowestall(low);

# plot lines when a condition is true. see if the overlap

# 1. PSAR is bullish and fast MA has crossed over slow MA
# 2. PSAR is bearish and slow MA has crossed over fast MA


def sar3 = if bn == 1 then 0 else if transitionBull then 1 else if transitionBear then 0 else sar3[1];
plot sar2 = if isnan(close) then na else lo;
sar2.SetPaintingStrategy(PaintingStrategy.POINTS);
# x.SetDefaultColor(Color.red);
sar2.setlineweight(2);
sar2.hidebubble();
sar2.DefineColor("Up", color.green);
sar2.DefineColor("Down", color.red);
sar2.AssignValueColor(if sar3 then sar2.color("up") else sar2.color("down"));


def maup = fastema > slowema;
plot ma2 = if isnan(close) then na else (lo * 0.995);
ma2.SetPaintingStrategy(PaintingStrategy.POINTS);
# x.SetDefaultColor(Color.red);
ma2.setlineweight(2);
ma2.hidebubble();
ma2.DefineColor("Up", color.green);
ma2.DefineColor("Down", color.red);
ma2.AssignValueColor(if maup then ma2.color("up") else ma2.color("down"));

# -------------------
# ref line
plot z1 = if isnan(close) then na else (lo * 0.990);
z1.SetDefaultColor(Color.gray);

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

# combine 2 outputs
def combined = (sar3 and maup);
plot z2 = if isnan(close) then na else (lo * 0.985);
z2.SetPaintingStrategy(PaintingStrategy.POINTS);
z2.setlineweight(2);
z2.hidebubble();
z2.DefineColor("Up", color.green);
z2.DefineColor("Down", color.red);
z2.AssignValueColor(if combined then z2.color("up") else z2.color("down"));


def w = ( !isnan(close[6]) and isnan(close[5]) );
addchartbubble(w, lo*1.01, "PSAR" + "\n" + "MA" + "\n" + "--" + "\n" + "green = both true", color.yellow, no);
#

baIahN4.jpg
 
Last edited:
Solution
!!! Thank you soooo much, this is huge, I really appreciate it. I didn't even know what I didn't know, I was throwing lines of code at it trying to get something to stick, it was driving me crazy for awhile. Thank you so much for taking the time to help me out. I look forward to using it and looking at the the code to learn more.
Again, thanks
 

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

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
469 Online
Create Post

Similar threads

Similar threads

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