# SPX Strategy
# Strategy designed by Hypoluxa
# barbaros - v1 - 2021/02/25
# barbaros - v2 - 2021/02/25 - added warning arrows, alerts, statistics and non SPX trading option
# barbaros - v3 - 2021/02/26 - added SMA plots, chart type, and price plot
# Setup
# 10 Min chart
# Heikin Ashi candles
# SMA 3/9
# MACD Bollinger Bands (the one Ben has posted on here a while back) 8,16,36 and uncheck "show plot" on the BB upper, BB lower and BB mid line. You will only be using the zero line, MACD dots and MACD Line for entry purposes. The inputs of "b length" and "bb num dev" are irrelevant here since you will remove the the plots that I mentioned.
# ErgodicOsc 2,10,36 (changed the default negative to red)
# Option call logic:
# 1. The SMA's have to cross first.
# 2. For a call opportunity, you will then wait to see if the MACD dots cross above the MACD zero line. Its critical here to wait until one dot has cleared the zero line...you MUST see a gap....never enter with the dot on the line. Dots must be consistent as well...if its going up...then they must all be white...if a red dot populates between the time a white dot hits the zero line and the time one crosses clear....don't enter. I have a screenshot below showing this example - 13:00 a red dot appears.
# 3. The ErgodicOsc HAS to be green when the MACD dot crosses above the zero line. You can hold the trade most of the time until this turns from green to red....but I always set a sell limit just in case it whips back in the opposite direction.
# Option put logic:
# Obviously its the complete opposite of what I've described above for a call. BUT - the SMA's still have to cross first.
declare upper;
input price = close;
input SMAFastLength = 3;
input SMASlowLength = 9;
input BBlength = 30;
input BBNum_Dev = 0.8;
input BBCrossInBars = 3;
input BBCrossDistance = 1.0;
input MACDfastLength = 8;
input MACDslowLength = 16;
input MACDLength = 36;
input ERGODICLongLength = 2;
input ERGODICShortLength = 10;
input ERGODICSignalLength = 36;
input ERGODICAverageType = {"SIMPLE", default "EXPONENTIAL", "WEIGHTED", "WILDERS", "HULL"};
input ShowWarnArrows = no;
input ShowStatistics = no;
input ProfitDelta = 1.0;
input AllowNonSPX = no;
# Check for 10min chart
Assert(AllowNonSPX or GetAggregationPeriod() == AggregationPeriod.TEN_MIN, "Incorrect Chart Time, use 10m");
Assert(AllowNonSPX or GetSymbol() == "SPX", "Incorrect Chart Time, use 10m");
# MACD
def MACD_Data = MACD(fastLength = MACDfastLength, slowLength = MACDslowLength, MACDLength = MACDLength);
def MACD_Direction = if MACD_Data > MACD_Data[1] then 1 else -1;
# Ergodic
def Ergodic_Data = ErgodicOsc("long length" = ERGODICLongLength, "short length" = ERGODICShortLength, "signal length" = ERGODICSignalLength, "average type" = ERGODICAverageType).ErgodicOsc;
# SMAs
def SMA_Fast = SimpleMovingAvg(price, SMAFastLength);
def SMA_Slow = SimpleMovingAvg(price, SMASlowLength);
# Signals
def buySignal = SMA_Fast > SMA_Slow and Ergodic_Data > 0 and MACD_Direction == 1 and MACD_Data >= BBCrossDistance and MACD_Data crosses above 0 within BBCrossInBars bars;
def buyWarnSignal = SMA_Fast > SMA_Slow and Ergodic_Data > 0 and MACD_Direction == 1 and MACD_Data crosses above 0 within BBCrossInBars bars;
def sellSignal = SMA_Fast < SMA_Slow and Ergodic_Data < 0 and MACD_Direction == -1 and MACD_Data <= -BBCrossDistance and MACD_Data crosses below 0 within BBCrossInBars bars;
def sellWarnSignal = SMA_Fast < SMA_Slow and Ergodic_Data < 0 and MACD_Direction == -1 and MACD_Data crosses below 0 within BBCrossInBars bars;
# Plots
plot buy = buySignal and !buySignal[1];
buy.setPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
buy.setDefaultColor(Color.GREEN);
buy.setLineWeight(3);
plot buyWarn = if ShowWarnArrows then buyWarnSignal and !buyWarnSignal[1] else Double.NaN;
buyWarn.setPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
buyWarn.setDefaultColor(Color.CYAN);
buyWarn.setLineWeight(1);
buyWarn.setHiding(!ShowWarnArrows);
plot sell = sellSignal and !sellSignal[1];
sell.setPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
sell.setDefaultColor(Color.RED);
sell.setLineWeight(3);
plot sellWarn = if ShowWarnArrows then sellWarnSignal and !sellWarnSignal[1] else Double.NaN;
sellWarn.setPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
sellWarn.setDefaultColor(Color.MAGENTA);
sellWarn.setLineWeight(1);
sellWarn.setHiding(!ShowWarnArrows);
plot lastPrice = price;
lastPrice.setPaintingStrategy(PaintingStrategy.POINTS);
lastPrice.setDefaultColor(Color.GREEN);
plot fast = SMA_Fast;
fast.setPaintingStrategy(PaintingStrategy.LINE);
fast.setDefaultColor(Color.CYAN);
fast.setLineWeight(1);
plot slow = SMA_Slow;
slow.setPaintingStrategy(PaintingStrategy.LINE);
slow.setDefaultColor(Color.MAGENTA);
slow.setLineWeight(1);
SetChartType(ChartType.HEIKIN_ASHI);
# Alerts
Alert(buy, "Buy", Alert.BAR, Sound.Ring);
Alert(sell, "Sell", Alert.BAR, Sound.Ring);
Alert(buyWarn, "Buy Warning", Alert.BAR, Sound.Ding);
Alert(sellWarn, "Sell Warning", Alert.BAR, Sound.Ding);
# PnL
def entryPrice = if (buySignal and !buySignal[1]) or (sellSignal and !sellSignal[1]) then close else entryPrice[1];
def profitTarget = if buySignal and !buySignal[1] then entryPrice + ProfitDelta else if sellSignal and !sellSignal[1] then entryPrice - ProfitDelta else profitTarget[1];
def orderDir = if BarNumber() == 1 then 0
else if orderDir[1] == 0 and buySignal and !buySignal[1] then 1
else if orderDir[1] == 1 and (MACD_Direction != 1 or close crosses above profitTarget) then 0
else if orderDir[1] == 0 and sellSignal and !sellSignal[1] then -1
else if orderDir[1] == -1 and (MACD_Direction != -1 or close crosses below profitTarget) then 0
else orderDir[1];
def isOrder = if IsNaN(orderDir) then no else orderDir crosses 0;
def orderCount = CompoundValue(1, if IsNaN(isOrder) then 0 else if isOrder then orderCount[1] + 1 else orderCount[1], 0);
def orderWinners = if BarNumber() == 1 then 0
else if orderDir[1] == 1 and orderDir == 0 then
if close >= profitTarget[1] then orderWinners[1] + 1 else orderWinners[1]
else if orderDir[1] == -1 and orderDir == 0 then
if close <= profitTarget[1] then orderWinners[1] + 1 else orderWinners[1]
else orderWinners[1];
def winRate = orderWinners / orderCount;
AddLabel(ShowStatistics, "SPX Strategy", Color.WHITE);
AddLabel(ShowStatistics, "" + orderCount + " Trades | " + AsPercent(winRate), if winRate > 0.5 then Color.GREEN else Color.RED);