# Balanced BB Breakout Indicator
# Free for use. Header credits must be included when any form of the code included in this package is used.
# User assumes all risk. Author not responsible for errors or use of tool.
# v1.2 - Assembled by Chuck Edwards
# v2.0 - Barbaros cleanup
declare lower;
# Market Forecast
def pIntermediate = MarketForecast().Intermediate;
AddLabel(yes,
"Market Forecast " +
if pIntermediate >= 80 then "Bullish" else
if pIntermediate <= 20 then "Bearish" else
if pIntermediate > pIntermediate[1] then "Rising" else
if pIntermediate < pIntermediate[1] then "Falling" else " ",
if pIntermediate >= 80 then CreateColor(204, 255, 204) else # Pre_Cyan
if pIntermediate <= 20 then Color.RED else
if pIntermediate > pIntermediate[1] then CreateColor(0, 165, 0) else # LabelGreen
if pIntermediate < pIntermediate[1] then Color.RED else Color.LIGHT_GRAY
);
# MACD_BB
input BBlength = 15;
input BBNum_Dev = 1.0;
input MACDfastLength = 12;
input MACDslowLength = 26;
input fastLengthMACD = 12;
input slowLengthMACD = 26;
input MACDLength = 25;
input averageTypeMACD = AverageType.WEIGHTED;
input showBreakoutSignals = no;
def MACD_Data = MACD(fastLength = MACDfastLength, slowLength = MACDslowLength, MACDLength = MACDLength);
plot MACD_Dots = MACD_Data;
plot MACD_Line = MACD_Data;
plot BB_Upper = reference BollingerBands(price = MACD_Line, length = BBlength, Num_Dev_Dn = -BBNum_Dev, Num_Dev_Up = BBNum_Dev).UpperBand;
plot BB_Lower = reference BollingerBands(price = MACD_Line, length = BBlength, Num_Dev_Dn = -BBNum_Dev, Num_Dev_Up = BBNum_Dev).Lowerband;
plot BB_Midline = reference BollingerBands(price = MACD_Line, length = BBlength, Num_Dev_Dn = -BBNum_Dev, Num_Dev_Up = BBNum_Dev).MidLine;
BB_Upper.SetDefaultColor(Color.RED);
BB_Lower.SetDefaultColor(Color.GREEN);
BB_Midline.SetDefaultColor(Color.LIGHT_RED);
BB_Midline.SetStyle(Curve.FIRM);
MACD_Line.AssignValueColor(
if MACD_Line > MACD_Line[1] and MACD_Line >= BB_Upper then Color.GREEN
else if MACD_Line < MACD_Line[1] and MACD_Line >= BB_Upper then Color.DARK_GREEN
else if MACD_Line < MACD_Line[1] and MACD_Line <= BB_Lower then Color.RED else
if MACD_Line > MACD_Line[1] and MACD_Line <= BB_Lower then Color.DARK_RED
else Color.GRAY
);
MACD_Line.SetLineWeight(1);
MACD_Dots.AssignValueColor(
if MACD_Line > MACD_Line[1] and MACD_Line > BB_Upper then Color.GREEN
else if MACD_Line < MACD_Line[1] and MACD_Line > BB_Upper then Color.DARK_GREEN
else if MACD_Line < MACD_Line[1] and MACD_Line < BB_Lower then Color.RED
else if MACD_Line > MACD_Line[1] and MACD_Line < BB_Lower then Color.DARK_RED
else Color.GRAY
);
MACD_Dots.SetPaintingStrategy(PaintingStrategy.LINE_VS_POINTS);
MACD_Dots.SetLineWeight(1);
AddLabel(yes,
"Trend " +
if MACD_Line > MACD_Line[1] and MACD_Line > BB_Upper then "Bullish"
else if MACD_Line < MACD_Line[1] and MACD_Line > BB_Upper then "Falling"
else if MACD_Line < MACD_Line[1] and MACD_Line < BB_Lower then "Bearish"
else if MACD_Line > MACD_Line[1] and MACD_Line < BB_Lower then "Rising"
else "Neutral",
if MACD_Line > MACD_Line[1] and MACD_Line > BB_Upper then Color.GREEN
else if MACD_Line < MACD_Line[1] and MACD_Line > BB_Upper then Color.DARK_GREEN
else if MACD_Line < MACD_Line[1] and MACD_Line < BB_Lower then Color.RED
else if MACD_Line > MACD_Line[1] and MACD_Line < BB_Lower then Color.DARK_RED
else Color.GRAY
);
# Keltner Channels
input factor = 1.5;
input length = 20;
input averageType = AverageType.EXPONENTIAL;
input trueRangeAverageType = AverageType.EXPONENTIAL;
def shift = factor * MovingAverage(trueRangeAverageType, TrueRange(high, close, low), length);
def average = MovingAverage(averageType, close, length);
def Upper_Band = average + shift;
def Lower_Band = average - shift;
# Bollinger Bands
input BBLength2 = 20;
input Num_Dev_Dn = -2.0;
input Num_Dev_up = 2.0;
input bb_averageType = AverageType.SIMPLE;
def sDev = StDev(data = close, length = BBLength2);
def MidLine = MovingAverage(bb_averageType, data = close, length = BBLength2);
def LowerBand = MidLine + Num_Dev_Dn * sDev;
def UpperBand = MidLine + Num_Dev_up * sDev;
# BB Cloud
AddCloud(if UpperBand <= Upper_Band and LowerBand >= Lower_Band then BB_Upper else BB_Lower, BB_Lower, Color.YELLOW);
AddCloud(BB_Upper, BB_Lower, Color.LIGHT_RED);
# BB Alert
Alert(MACD_Line crosses above 0, "Time to Buy", Alert.BAR, Sound.Chimes);
Alert(MACD_Line crosses below 0, "Time to Sell", Alert.BAR, Sound.Bell);
# RSI/STOCASTIC/MACD CONFLUENCE COMBO
def Value = MovingAverage(averageTypeMACD, close, fastLengthMACD) - MovingAverage(averageTypeMACD, close, slowLengthMACD);
def Avg = MovingAverage(averageTypeMACD, Value, MACDLength);
plot Diff = Value - Avg;
Diff.SetDefaultColor(GetColor(5));
Diff.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
Diff.SetLineWeight(4);
Diff.DefineColor("Positive and Up", Color.GREEN);
Diff.DefineColor("Positive and Down", Color.DARK_GREEN);
Diff.DefineColor("Negative and Down", Color.RED);
Diff.DefineColor("Negative and Up", Color.DARK_RED);
Diff.AssignValueColor(
if Diff >= 0 then
if Diff > Diff[1] then Diff.Color("Positive and Up") else Diff.Color("Positive and Down")
else
if Diff < Diff[1] then Diff.Color("Negative and Down") else Diff.Color("Negative and Up")
);
plot ZeroLine = 0;
ZeroLine.SetDefaultColor(Color.RED);
ZeroLine.HideTitle();
ZeroLine.HideBubble();
plot UpSignalMACD = if Diff crosses above ZeroLine then ZeroLine else Double.NaN;
UpSignalMACD.SetDefaultColor(Color.UPTICK);
UpSignalMACD.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
UpSignalMACD.SetHiding(!showBreakoutSignals);
plot DownSignalMACD = if Diff crosses below ZeroLine then ZeroLine else Double.NaN;
DownSignalMACD.SetDefaultColor(Color.DOWNTICK);
DownSignalMACD.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
DownSignalMACD.SetHiding(!showBreakoutSignals);
input lengthRSI = 7;
input averageTypeRSI = AverageType.EXPONENTIAL;
def NetChgAvg = MovingAverage(averageTypeRSI, close - close[1], lengthRSI);
def TotChgAvg = MovingAverage(averageTypeRSI, AbsValue(close - close[1]), lengthRSI);
def ChgRatio = if TotChgAvg != 0 then NetChgAvg / TotChgAvg else 0;
def RSI = 50 * (ChgRatio + 1);
input KPeriod = 5;
input DPeriod = 3;
input averageTypeStoch = AverageType.WILDERS;
def SlowK = reference StochasticFull(80, 20, KPeriod, DPeriod, high, low, close, 3, averageTypeStoch).FullK;
def SlowD = reference StochasticFull(80, 20, KPeriod, DPeriod, high, low, close, 3, averageTypeStoch).FullD;
def rsiGreen = if RSI >= 50 then 1 else Double.NaN;
def rsiRed = if RSI < 50 then 1 else Double.NaN;
def stochGreen = if SlowK >= 50 then 1 else Double.NaN;
def stochRed = if SlowK < 50 then 1 else Double.NaN;
def macdGreen = if Value > Avg then 1 else Double.NaN;
def macdRed = if Value < Avg then 1 else Double.NaN;
input paintBars = yes;
AssignPriceColor(
if paintBars and RSI >= 50 and SlowK >= 50 and Value > Avg then Color.GREEN
else if paintBars and RSI < 50 and SlowK < 50 and Value < Avg then Color.RED
else if paintBars then Color.DARK_GRAY
else Color.CURRENT
);
# Shade areas based on criteria; adjust as needed
AddCloud(
if rsiGreen and stochGreen and macdGreen then Double.POSITIVE_INFINITY else Double.NaN,
if rsiGreen and stochGreen then Double.NEGATIVE_INFINITY else Double.NaN, Color.LIGHT_GREEN
);
AddCloud(
if rsiRed and stochRed and macdRed then Double.POSITIVE_INFINITY else Double.NaN,
if rsiRed and stochRed then Double.NEGATIVE_INFINITY else Double.NaN, Color.LIGHT_RED
);
# Balance of Power
input EMA = 20;
input TEMA = 20;
def THL = If(high != low, high - low, 0.01);
def BullOpen = (high - open) / THL;
def BearOpen = (open - low) / THL;
def BullClose = (close - low) / THL;
def BearClose = (high - close) / THL;
def BullOC = If(close > open, (close - open) / THL, 0);
def BearOC = If(open > close, (open - close) / THL, 0);
def BullReward = (BullOpen + BullClose + BullOC) / 1;
def BearReward = (BearOpen + BearClose + BearOC) / 1;
def BOP = BullReward - BearReward;
def SmoothBOP = ExpAverage(BOP, EMA);
def xPrice = SmoothBOP;
def xEMA1 = ExpAverage(SmoothBOP, TEMA);
def xEMA2 = ExpAverage(xEMA1, TEMA);
def xEMA3 = ExpAverage(xEMA2, TEMA);
def nRes = 3 * xEMA1 - 3 * xEMA2 + xEMA3;
def SmootherBOP = nRes;
def s1 = SmoothBOP;
def s2 = SmootherBOP;
def s3 = SmootherBOP[2];
def short = s2 < s3 and s2[1] > s3[1];
def long = s2 > s3 and s2[1] < s3[1];
AddVerticalLine(short, close, Color.RED, Curve.SHORT_DASH);
AddVerticalLine(long, close, Color.GREEN, Curve.SHORT_DASH);
# P/L Statement
input PandL_Label = No;
input IntraDayOnly = Yes;
def orderDir = if IntraDayOnly and (SecondsTillTime(930) > 0 or SecondsFromTime(1600) > 0) then 0 else CompoundValue(1, if s2 < s3 then 1 else if s2 > s3 then -1 else orderDir[1], 0);
def isOrder = orderDir crosses 0;
def orderCount = CompoundValue(1, if IsNaN(isOrder) then 0 else if isOrder then orderCount[1] + 1 else orderCount[1], 0);
def noBar = IsNaN(open[-1]);
def orderPrice = if isOrder then if noBar then close else open[-1] else orderPrice[1];
def profitLoss = if !isOrder or orderCount == 1 then 0
else if orderDir < 0 then orderPrice[1] - orderPrice
else if orderDir > 0 then orderPrice - orderPrice[1] else 0;
def profitLossSum = CompoundValue(1, if IsNaN(isOrder) then 0 else if isOrder then profitLossSum[1] + profitLoss else profitLossSum[1], 0);
def orderWinners = CompoundValue(1, if IsNaN(isOrder) then orderWinners[1] else if orderCount > 1 and profitLoss > 0 then orderWinners[1] + 1 else orderWinners[1], 0);
AddLabel(PandL_Label,
orderCount + " orders (" + AsPercent(orderWinners / orderCount) + ") | P/L " + AsDollars ((profitLossSum / TickSize()) * TickValue()),
if profitLossSum > 0 then Color.GREEN else if profitLossSum < 0 then Color.RED else Color.GRAY
);