Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //@version=6
- indicator("Prime Indicator v1.2.0", shorttitle = "Prime Indicator v1.2.0", overlay = true, precision = 1, max_labels_count = 500, max_lines_count = 500, max_bars_back = 500)
- string G_MAIN = "Main Settings"
- string G_FILTER = "Signal Engine"
- string G_TRADE = "Trade Management"
- string G_LEVELS = "Entry / Stop Loss / Take Profit Levels"
- string G_SIGNAL = "Signal Labels"
- string G_DASH = "Dashboard"
- string G_MTF = "Dashboard Timeframes"
- string G_COLOR = "Signal & Level Colors"
- string G_DCOLOR = "Dashboard Colors"
- string G_ALERT = "Alerts & Automation"
- string i_mode = input.string("Balanced", "Trading Mode", options = ["Scalp", "Balanced", "Swing"], group = G_MAIN, tooltip = "Scalp • Fast Response: reacts quickly to strong directional moves, momentum shifts, pullback recoveries and confirmed breakouts.\nBalanced • Elite Accuracy: strict multi-factor confirmation with tightened breakout filtering (default).\nSwing • Trend Precision: focuses on strong expansion moves with selective confirmation of late follow-on entries.")
- string i_market = input.string("Futures", "Market Type", options = ["Futures", "Spot"], group = G_MAIN, tooltip = "Futures: BUY and SELL signals with direct directional transitions (long ⇄ short).\nSpot: long-only. Bearish SELL conditions close an open long with an EXIT signal.")
- bool i_confirmBar = input.bool(true, "Confirm Signals on Bar Close", group = G_MAIN, tooltip = "When enabled, signals, exits and level updates are only processed on confirmed (closed) bars. This keeps the indicator non-repainting.")
- bool i_useMtf = input.bool(true, "Multi-Timeframe Trend Alignment", group = G_FILTER, tooltip = "Blocks signals when the dashboard timeframes are aligned against the signal direction.")
- bool i_useRegime = input.bool(true, "Market Regime Filter", group = G_FILTER, tooltip = "Uses ADX and the Choppiness Index to detect ranging regimes and filter lower-quality noise.")
- bool i_useVolatility = input.bool(true, "Volatility Conditions", group = G_FILTER, tooltip = "Avoids signals during abnormally compressed or abnormally extreme volatility (ATR relative to its average).")
- bool i_useVolume = input.bool(true, "Volume Participation", group = G_FILTER, tooltip = "Rewards signals that are backed by above-average volume participation.")
- bool i_useCandle = input.bool(true, "Candle Quality", group = G_FILTER, tooltip = "Requires a signal candle that closes in the direction of the signal with a solid body and close location.")
- bool i_useLocation = input.bool(true, "Trade Location Context", group = G_FILTER, tooltip = "Avoids entries that are over-extended away from the mean (distance measured in ATR).")
- int i_adxLen = input.int(14, "ADX Length", minval = 2, maxval = 100, group = G_FILTER, inline = "len")
- int i_atrLen = input.int(14, "ATR Length", minval = 2, maxval = 100, group = G_FILTER, inline = "len")
- float i_volMult = input.float(1.2, "Volume Participation Multiplier", minval = 0.5, maxval = 5.0, step = 0.1, group = G_FILTER, tooltip = "Volume must exceed its 20-bar average by this multiplier to count as strong participation.")
- float i_slAtr = input.float(1.5, "Stop Loss ATR Multiplier", minval = 0.3, maxval = 10.0, step = 0.1, group = G_TRADE, tooltip = "Base stop distance in ATR. The selected trading mode scales this value (Scalp 0.8x • Balanced 1.0x • Swing 1.4x).")
- float i_tp1R = input.float(0.5, "TP1", minval = 0.1, maxval = 20.0, step = 0.1, group = G_TRADE, inline = "tp")
- float i_tp2R = input.float(1.0, "TP2", minval = 0.1, maxval = 20.0, step = 0.1, group = G_TRADE, inline = "tp")
- float i_tp3R = input.float(1.3, "TP3", minval = 0.1, maxval = 20.0, step = 0.1, group = G_TRADE, inline = "tp", tooltip = "Take Profit targets expressed as multiples of the initial risk (Entry to Stop Loss distance).")
- bool i_useTrail = input.bool(true, "Adaptive Trailing EXIT", group = G_TRADE, tooltip = "After TP1 is reached, an ATR trailing stop protects the move. Strong trends receive a wider trail, weakening conditions a tighter one.")
- bool i_useWeakExit = input.bool(true, "Momentum Weakness EXIT", group = G_TRADE, tooltip = "Exits when trend, momentum and structure weaken against the position. Ranging and low-volatility conditions require extra confirmation to reduce premature exits.")
- bool i_exitAtTp3 = input.bool(false, "Close Trade at TP3", group = G_TRADE, tooltip = "When enabled, reaching TP3 closes the trade with an EXIT signal. When disabled, strong moves are allowed to continue beyond TP3.")
- bool i_showLevels = input.bool(true, "Show Entry / SL / TP Levels", group = G_LEVELS)
- int i_levelOffset = input.int(10, "Label Offset (bars)", minval = 1, maxval = 100, group = G_LEVELS, tooltip = "Distance between the last bar and the level labels.")
- string i_levelSize = input.string("Small", "Level Label Size", options = ["Tiny", "Small", "Normal"], group = G_LEVELS)
- int i_levelWidth = input.int(1, "Level Line Width", minval = 1, maxval = 4, group = G_LEVELS)
- bool i_showSignals = input.bool(true, "Show BUY / SELL Labels", group = G_SIGNAL)
- bool i_showExit = input.bool(true, "Show EXIT Labels", group = G_SIGNAL)
- string i_signalSize = input.string("Small", "Signal Label Size", options = ["Tiny", "Small", "Normal"], group = G_SIGNAL)
- bool i_showDash = input.bool(true, "Show Dashboard", group = G_DASH)
- string i_dashPos = input.string("Top Right", "Dashboard Position", options = ["Top Left", "Top Right", "Bottom Left", "Bottom Right"], group = G_DASH)
- string i_dashSize = input.string("Normal", "Dashboard Size", options = ["Compact", "Normal", "Large"], group = G_DASH)
- string i_tf1 = input.timeframe("5", "Timeframe 1", group = G_MTF)
- string i_tf2 = input.timeframe("15", "Timeframe 2", group = G_MTF)
- string i_tf3 = input.timeframe("60", "Timeframe 3", group = G_MTF)
- string i_tf4 = input.timeframe("240", "Timeframe 4", group = G_MTF)
- string i_tf5 = input.timeframe("D", "Timeframe 5", group = G_MTF)
- color c_buy = input.color(#13A556, "BUY", group = G_COLOR, inline = "sig")
- color c_sell = input.color(#E1333F, "SELL", group = G_COLOR, inline = "sig")
- color c_exit = input.color(#1A6EF5, "EXIT", group = G_COLOR, inline = "sig")
- color c_sigText = input.color(#FFFFFF, "Text", group = G_COLOR, inline = "sig")
- color c_entry = input.color(#F7A21B, "Entry", group = G_COLOR, inline = "lvl")
- color c_sl = input.color(#F23645, "Stop Loss", group = G_COLOR, inline = "lvl")
- color c_tp = input.color(#4CAF50, "Take Profit", group = G_COLOR, inline = "lvl")
- color c_lvlText = input.color(#FFFFFF, "Text", group = G_COLOR, inline = "lvl")
- color c_dashBg = input.color(#131722, "Background", group = G_DCOLOR, inline = "d1")
- color c_dashBorder = input.color(#B2B5BE, "Border", group = G_DCOLOR, inline = "d1")
- color c_dashText = input.color(#FFFFFF, "Text", group = G_DCOLOR, inline = "d1")
- color c_dashValText = input.color(#131722, "Value Text", group = G_DCOLOR, inline = "d1")
- color c_dashMode = input.color(#8C9CAA, "Mode", group = G_DCOLOR, inline = "d2")
- color c_dashFutures = input.color(#FFC107, "Futures", group = G_DCOLOR, inline = "d2")
- color c_dashSpot = input.color(#00BCD4, "Spot", group = G_DCOLOR, inline = "d2")
- color c_dashBull = input.color(#2EBD85, "Bullish", group = G_DCOLOR, inline = "d3")
- color c_dashBear = input.color(#F7434F, "Bearish", group = G_DCOLOR, inline = "d3")
- color c_dashNeutral = input.color(#8C9CAA, "Neutral", group = G_DCOLOR, inline = "d3")
- string i_alertFormat = input.string("Text", "Alert Message Format", options = ["Text", "JSON"], group = G_ALERT, tooltip = "Text: readable message.\nJSON: structured payload for webhooks and third-party automation. Create the alert with 'Any alert() function call'.")
- bool i_alertBuy = input.bool(true, "BUY", group = G_ALERT, inline = "a1")
- bool i_alertSell = input.bool(true, "SELL", group = G_ALERT, inline = "a1")
- bool i_alertExit = input.bool(true, "EXIT", group = G_ALERT, inline = "a1")
- bool i_alertTp = input.bool(true, "TP Hits", group = G_ALERT, inline = "a2")
- bool i_alertSl = input.bool(true, "SL Hit", group = G_ALERT, inline = "a2")
- string i_msgBuy = input.string("", "Custom BUY Message", group = G_ALERT, tooltip = "Optional. Overrides the default message. Placeholders: {action} {ticker} {exchange} {timeframe} {price} {entry} {sl} {tp1} {tp2} {tp3} {mode} {market} {reason}")
- string i_msgSell = input.string("", "Custom SELL Message", group = G_ALERT, tooltip = "Optional. Same placeholders as the BUY message.")
- string i_msgExit = input.string("", "Custom EXIT Message", group = G_ALERT, tooltip = "Optional. Used for EXIT, TP and SL events. Same placeholders as the BUY message.")
- string INDICATOR_NAME = "Prime Indicator v1.2.0"
- float W_REGIME = 15.0
- float W_MTF = 20.0
- float W_VOLATILITY = 10.0
- float W_STRUCTURE = 15.0
- float W_MOMENTUM = 15.0
- float W_VOLUME = 10.0
- float W_CANDLE = 10.0
- float W_LOCATION = 5.0
- int ATR_AVG_LEN = 50
- int VOL_AVG_LEN = 20
- int RSI_LEN = 14
- int MACD_FAST = 12
- int MACD_SLOW = 26
- int MACD_SIGNAL = 9
- int CHOP_LEN = 14
- float CHOP_RANGING = 55.0
- float VOL_MIN_RATIO = 0.55
- float VOL_MAX_RATIO = 3.0
- float LOW_VOL_RATIO = 0.80
- int MTF_COUNT = 5
- type TradeLevels
- float entry = na
- float sl = na
- float tp1 = na
- float tp2 = na
- float tp3 = na
- int entryBar = na
- type LevelDrawings
- line entryLn = na
- line slLn = na
- line tp1Ln = na
- line tp2Ln = na
- line tp3Ln = na
- label entryLb = na
- label slLb = na
- label tp1Lb = na
- label tp2Lb = na
- label tp3Lb = na
- f_fmt(float price) =>
- na(price) ? "0" : str.tostring(price, format.mintick)
- f_labelSize(string opt) =>
- switch opt
- "Tiny" => size.tiny
- "Normal" => size.normal
- => size.small
- f_dashTextSize(string opt) =>
- switch opt
- "Compact" => size.small
- "Large" => size.large
- => size.normal
- f_tablePos(string opt) =>
- switch opt
- "Top Left" => position.top_left
- "Bottom Left" => position.bottom_left
- "Bottom Right" => position.bottom_right
- => position.top_right
- f_tfLabel(string tf) =>
- int sec = timeframe.in_seconds(tf)
- string res = switch
- sec < 60 => str.tostring(sec) + "s"
- sec < 3600 => str.tostring(math.round(sec / 60.0)) + "m"
- sec < 86400 => str.tostring(math.round(sec / 3600.0)) + "H"
- sec == 86400 => "Daily"
- sec == 604800 => "Weekly"
- sec >= 2419200 => "Monthly"
- => str.tostring(math.round(sec / 86400.0)) + "D"
- res
- f_modeText(string mode) =>
- switch mode
- "Scalp" => "Scalp • Fast Response"
- "Swing" => "Swing • Trend Precision"
- => "Balanced • Elite Accuracy"
- f_trendText(int state) =>
- state == 1 ? "Bullish" : state == -1 ? "Bearish" : "Neutral"
- f_trendColor(int state) =>
- state == 1 ? c_dashBull : state == -1 ? c_dashBear : c_dashNeutral
- f_trendState(simple int fastLen, simple int slowLen, simple int adxLen, simple float adxMin, simple int off) =>
- float ef = ta.ema(close, fastLen)
- float es = ta.ema(close, slowLen)
- [dp, dm, adxV] = ta.dmi(adxLen, adxLen)
- float rs = ta.rsi(close, RSI_LEN)
- int bullVotes = (close > es ? 1 : 0) + (ef > es ? 1 : 0) + (ef > ef[3] ? 1 : 0) + (dp > dm ? 1 : 0) + (rs > 50 ? 1 : 0)
- int bearVotes = (close < es ? 1 : 0) + (ef < es ? 1 : 0) + (ef < ef[3] ? 1 : 0) + (dm > dp ? 1 : 0) + (rs < 50 ? 1 : 0)
- int state = adxV >= adxMin and bullVotes >= 4 ? 1 : adxV >= adxMin and bearVotes >= 4 ? -1 : 0
- state[off]
- f_mtfTrend(simple string tf, simple int fastLen, simple int slowLen, simple int adxLen, simple float adxMin) =>
- bool isHtf = timeframe.in_seconds(tf) > timeframe.in_seconds(timeframe.period)
- int result = 0
- if isHtf
- result := request.security(syminfo.tickerid, tf, f_trendState(fastLen, slowLen, adxLen, adxMin, 1), lookahead = barmerge.lookahead_on)
- else
- result := request.security(syminfo.tickerid, tf, f_trendState(fastLen, slowLen, adxLen, adxMin, 0), lookahead = barmerge.lookahead_off)
- nz(result, 0)
- f_newTrade(int dir, float entry, float risk) =>
- TradeLevels.new(entry, entry - dir * risk, entry + dir * risk * i_tp1R, entry + dir * risk * i_tp2R, entry + dir * risk * i_tp3R, bar_index)
- f_drawLevel(int x1, int x2, float price, color col, string lnStyle, string txt) =>
- line ln = line.new(x1 = x1, y1 = price, x2 = x2, y2 = price, xloc = xloc.bar_index, extend = extend.none, color = col, style = lnStyle, width = i_levelWidth)
- label lb = label.new(x = x2, y = price, text = txt, xloc = xloc.bar_index, yloc = yloc.price, color = col, style = label.style_label_left, textcolor = c_lvlText, size = f_labelSize(i_levelSize), textalign = text.align_left)
- [ln, lb]
- method clearAll(LevelDrawings this) =>
- line.delete(this.entryLn)
- line.delete(this.slLn)
- line.delete(this.tp1Ln)
- line.delete(this.tp2Ln)
- line.delete(this.tp3Ln)
- label.delete(this.entryLb)
- label.delete(this.slLb)
- label.delete(this.tp1Lb)
- label.delete(this.tp2Lb)
- label.delete(this.tp3Lb)
- this
- method build(LevelDrawings this, TradeLevels t, int xEnd) =>
- this.clearAll()
- [slL, slB] = f_drawLevel(t.entryBar, xEnd, t.sl, c_sl, line.style_solid, "SL: " + f_fmt(t.sl))
- [enL, enB] = f_drawLevel(t.entryBar, xEnd, t.entry, c_entry, line.style_dotted, "Entry: " + f_fmt(t.entry))
- [t1L, t1B] = f_drawLevel(t.entryBar, xEnd, t.tp1, c_tp, line.style_solid, "TP1: " + f_fmt(t.tp1))
- [t2L, t2B] = f_drawLevel(t.entryBar, xEnd, t.tp2, c_tp, line.style_solid, "TP2: " + f_fmt(t.tp2))
- [t3L, t3B] = f_drawLevel(t.entryBar, xEnd, t.tp3, c_tp, line.style_solid, "TP3: " + f_fmt(t.tp3))
- this.slLn := slL
- this.slLb := slB
- this.entryLn := enL
- this.entryLb := enB
- this.tp1Ln := t1L
- this.tp1Lb := t1B
- this.tp2Ln := t2L
- this.tp2Lb := t2B
- this.tp3Ln := t3L
- this.tp3Lb := t3B
- this
- method extendTo(LevelDrawings this, int xEnd) =>
- line.set_x2(this.entryLn, xEnd)
- line.set_x2(this.slLn, xEnd)
- line.set_x2(this.tp1Ln, xEnd)
- line.set_x2(this.tp2Ln, xEnd)
- line.set_x2(this.tp3Ln, xEnd)
- label.set_x(this.entryLb, xEnd)
- label.set_x(this.slLb, xEnd)
- label.set_x(this.tp1Lb, xEnd)
- label.set_x(this.tp2Lb, xEnd)
- label.set_x(this.tp3Lb, xEnd)
- this
- [pFast, pSlow, pTrend, pSwing, pScoreMin, pAdxMin, pSlFactor, pTrailStrong, pTrailWeak, pCooldown, pMaxExt, pLateBars] = switch i_mode
- "Scalp" => [9, 21, 100, 3, 55.0, 16.0, 0.8, 2.2, 1.3, 1, 2.6, 12]
- "Swing" => [34, 89, 200, 8, 66.0, 22.0, 1.4, 3.8, 2.4, 3, 3.6, 30]
- => [21, 55, 150, 5, 60.0, 20.0, 1.0, 3.0, 1.8, 2, 3.0, 20]
- bool isFutures = i_market == "Futures"
- bool warmedUp = bar_index >= math.max(pTrend, ATR_AVG_LEN)
- float atrVal = ta.atr(i_atrLen)
- float atrAvg = ta.sma(atrVal, ATR_AVG_LEN)
- float atrSafe = math.max(nz(atrVal, high - low), syminfo.mintick)
- float atrRatio = nz(atrAvg) > 0 ? atrVal / atrAvg : 1.0
- float emaFast = ta.ema(close, pFast)
- float emaSlow = ta.ema(close, pSlow)
- float emaTrend = ta.ema(close, pTrend)
- [diPlus, diMinus, adxVal] = ta.dmi(i_adxLen, i_adxLen)
- float rsiVal = ta.rsi(close, RSI_LEN)
- [_, _, macdHist] = ta.macd(close, MACD_FAST, MACD_SLOW, MACD_SIGNAL)
- float volNow = nz(volume)
- float volSma = ta.sma(volNow, VOL_AVG_LEN)
- bool hasVol = nz(volSma) > 0
- float low3 = ta.lowest(low, 3)
- float high3 = ta.highest(high, 3)
- float barRange = high - low
- float bodySize = math.abs(close - open)
- float bodyRatio = barRange > 0 ? bodySize / barRange : 0.0
- float closePos = barRange > 0 ? (close - low) / barRange : 0.5
- float chopSum = math.sum(ta.atr(1), CHOP_LEN)
- float chopRange = math.max(ta.highest(high, CHOP_LEN) - ta.lowest(low, CHOP_LEN), syminfo.mintick)
- float chopVal = 100.0 * math.log10(nz(chopSum, chopRange) / chopRange) / math.log10(CHOP_LEN)
- bool isTrending = nz(adxVal) >= pAdxMin
- bool isRanging = not isTrending and chopVal > CHOP_RANGING
- bool lowVol = atrRatio < LOW_VOL_RATIO
- bool strongLong = nz(adxVal) >= pAdxMin + 5 and emaFast > emaSlow and diPlus > diMinus
- bool strongShort = nz(adxVal) >= pAdxMin + 5 and emaFast < emaSlow and diMinus > diPlus
- float ph = ta.pivothigh(high, pSwing, pSwing)
- float pl = ta.pivotlow(low, pSwing, pSwing)
- var float lastSwingHigh = na
- var float lastSwingLow = na
- if not na(ph)
- lastSwingHigh := ph
- if not na(pl)
- lastSwingLow := pl
- bool bosUp = ta.crossover(close, lastSwingHigh)
- bool bosDn = ta.crossunder(close, lastSwingLow)
- var int structBias = 0
- if bosUp
- structBias := 1
- else if bosDn
- structBias := -1
- int chartBull = (close > emaSlow ? 1 : 0) + (emaFast > emaSlow ? 1 : 0) + (emaFast > emaFast[3] ? 1 : 0) + (diPlus > diMinus ? 1 : 0) + (rsiVal > 50 ? 1 : 0)
- int chartBear = (close < emaSlow ? 1 : 0) + (emaFast < emaSlow ? 1 : 0) + (emaFast < emaFast[3] ? 1 : 0) + (diMinus > diPlus ? 1 : 0) + (rsiVal < 50 ? 1 : 0)
- int chartTrend = isTrending and chartBull >= 4 ? 1 : isTrending and chartBear >= 4 ? -1 : 0
- int mtf1 = f_mtfTrend(i_tf1, pFast, pSlow, i_adxLen, pAdxMin)
- int mtf2 = f_mtfTrend(i_tf2, pFast, pSlow, i_adxLen, pAdxMin)
- int mtf3 = f_mtfTrend(i_tf3, pFast, pSlow, i_adxLen, pAdxMin)
- int mtf4 = f_mtfTrend(i_tf4, pFast, pSlow, i_adxLen, pAdxMin)
- int mtf5 = f_mtfTrend(i_tf5, pFast, pSlow, i_adxLen, pAdxMin)
- int mtfBull = (mtf1 == 1 ? 1 : 0) + (mtf2 == 1 ? 1 : 0) + (mtf3 == 1 ? 1 : 0) + (mtf4 == 1 ? 1 : 0) + (mtf5 == 1 ? 1 : 0)
- int mtfBear = (mtf1 == -1 ? 1 : 0) + (mtf2 == -1 ? 1 : 0) + (mtf3 == -1 ? 1 : 0) + (mtf4 == -1 ? 1 : 0) + (mtf5 == -1 ? 1 : 0)
- float mtfNeutral = MTF_COUNT - mtfBull - mtfBear
- float sRegimeL = isTrending and diPlus > diMinus ? 1.0 : not isRanging ? 0.5 : 0.2
- float sRegimeS = isTrending and diMinus > diPlus ? 1.0 : not isRanging ? 0.5 : 0.2
- float sMtfL = (mtfBull + 0.5 * mtfNeutral) / MTF_COUNT
- float sMtfS = (mtfBear + 0.5 * mtfNeutral) / MTF_COUNT
- float sVolat = atrRatio >= LOW_VOL_RATIO and atrRatio <= 2.0 ? 1.0 : 0.5
- float sStructL = (structBias == 1 ? 0.6 : structBias == 0 ? 0.3 : 0.0) + (close > emaTrend ? 0.4 : 0.0)
- float sStructS = (structBias == -1 ? 0.6 : structBias == 0 ? 0.3 : 0.0) + (close < emaTrend ? 0.4 : 0.0)
- float sMomL = (macdHist > 0 ? 0.4 : 0.0) + (macdHist > macdHist[1] ? 0.3 : 0.0) + (rsiVal > 50 and rsiVal < 75 ? 0.3 : 0.0)
- float sMomS = (macdHist < 0 ? 0.4 : 0.0) + (macdHist < macdHist[1] ? 0.3 : 0.0) + (rsiVal < 50 and rsiVal > 25 ? 0.3 : 0.0)
- float sVolumeL = not hasVol ? 0.5 : volNow > volSma * i_volMult and close > open ? 1.0 : volNow > volSma * 0.8 ? 0.6 : 0.2
- float sVolumeS = not hasVol ? 0.5 : volNow > volSma * i_volMult and close < open ? 1.0 : volNow > volSma * 0.8 ? 0.6 : 0.2
- float sCandleL = close > open ? (bodyRatio >= 0.5 ? 0.6 : 0.3) + (closePos >= 0.7 ? 0.4 : closePos >= 0.5 ? 0.2 : 0.0) : 0.0
- float sCandleS = close < open ? (bodyRatio >= 0.5 ? 0.6 : 0.3) + (closePos <= 0.3 ? 0.4 : closePos <= 0.5 ? 0.2 : 0.0) : 0.0
- float extLong = (close - emaSlow) / atrSafe
- float extShort = (emaSlow - close) / atrSafe
- float sLocL = extLong >= -0.5 and extLong <= pMaxExt ? 1.0 : extLong > pMaxExt ? 0.0 : 0.4
- float sLocS = extShort >= -0.5 and extShort <= pMaxExt ? 1.0 : extShort > pMaxExt ? 0.0 : 0.4
- float wRegime = i_useRegime ? W_REGIME : 0.0
- float wMtf = i_useMtf ? W_MTF : 0.0
- float wVolat = i_useVolatility ? W_VOLATILITY : 0.0
- float wVolume = i_useVolume ? W_VOLUME : 0.0
- float wCandle = i_useCandle ? W_CANDLE : 0.0
- float wLoc = i_useLocation ? W_LOCATION : 0.0
- float wTotal = W_STRUCTURE + W_MOMENTUM + wRegime + wMtf + wVolat + wVolume + wCandle + wLoc
- float scoreLong = 100.0 * (W_STRUCTURE * sStructL + W_MOMENTUM * sMomL + wRegime * sRegimeL + wMtf * sMtfL + wVolat * sVolat + wVolume * sVolumeL + wCandle * sCandleL + wLoc * sLocL) / wTotal
- float scoreShort = 100.0 * (W_STRUCTURE * sStructS + W_MOMENTUM * sMomS + wRegime * sRegimeS + wMtf * sMtfS + wVolat * sVolat + wVolume * sVolumeS + wCandle * sCandleS + wLoc * sLocS) / wTotal
- bool crossUp = ta.crossover(emaFast, emaSlow)
- bool crossDn = ta.crossunder(emaFast, emaSlow)
- bool macdUp = ta.crossover(macdHist, 0)
- bool macdDn = ta.crossunder(macdHist, 0)
- int barsCrossUp = nz(ta.barssince(crossUp), 9999)
- int barsCrossDn = nz(ta.barssince(crossDn), 9999)
- float bosBuffer = i_mode == "Balanced" ? 0.10 * atrSafe : 0.0
- float expMult = i_mode == "Swing" ? 1.5 : 1.2
- bool bosUpOk = bosUp and close >= nz(lastSwingHigh) + bosBuffer and close > open
- bool bosDnOk = bosDn and close <= nz(lastSwingLow) - bosBuffer and close < open
- bool pullUp = emaFast > emaSlow and low3 <= emaFast and close > emaFast and close > high[1] and close > open
- bool pullDn = emaFast < emaSlow and high3 >= emaFast and close < emaFast and close < low[1] and close < open
- bool momUp = macdUp and close > emaSlow
- bool momDn = macdDn and close < emaSlow
- bool expUp = close > open and bodyRatio >= 0.65 and bodySize >= expMult * atrSafe and close > emaFast
- bool expDn = close < open and bodyRatio >= 0.65 and bodySize >= expMult * atrSafe and close < emaFast
- bool trigLong = switch i_mode
- "Scalp" => crossUp or bosUpOk or pullUp or momUp or expUp
- "Swing" => (crossUp and close > emaTrend) or bosUpOk or expUp or (pullUp and strongLong)
- => crossUp or bosUpOk or pullUp or momUp
- bool trigShort = switch i_mode
- "Scalp" => crossDn or bosDnOk or pullDn or momDn or expDn
- "Swing" => (crossDn and close < emaTrend) or bosDnOk or expDn or (pullDn and strongShort)
- => crossDn or bosDnOk or pullDn or momDn
- bool bosOnlyL = bosUpOk and not crossUp and not pullUp and not momUp
- bool bosOnlyS = bosDnOk and not crossDn and not pullDn and not momDn
- float reqLong = pScoreMin + (i_mode == "Swing" and barsCrossUp > pLateBars ? 8.0 : 0.0) + (i_mode == "Balanced" and bosOnlyL ? 4.0 : 0.0)
- float reqShort = pScoreMin + (i_mode == "Swing" and barsCrossDn > pLateBars ? 8.0 : 0.0) + (i_mode == "Balanced" and bosOnlyS ? 4.0 : 0.0)
- bool volatOk = not i_useVolatility or (atrRatio >= VOL_MIN_RATIO and atrRatio <= VOL_MAX_RATIO)
- bool regimeOkL = not i_useRegime or not isRanging or bosUpOk or expUp
- bool regimeOkS = not i_useRegime or not isRanging or bosDnOk or expDn
- bool mtfOkL = not i_useMtf or mtfBear <= mtfBull
- bool mtfOkS = not i_useMtf or mtfBull <= mtfBear
- bool locOkL = not i_useLocation or extLong <= pMaxExt
- bool locOkS = not i_useLocation or extShort <= pMaxExt
- bool candleOkL = not i_useCandle or (close > open and closePos >= 0.5)
- bool candleOkS = not i_useCandle or (close < open and closePos <= 0.5)
- bool trendOkL = i_mode == "Scalp" or close > emaTrend or bosUpOk
- bool trendOkS = i_mode == "Scalp" or close < emaTrend or bosDnOk
- bool buyBase = warmedUp and trigLong and scoreLong >= reqLong and volatOk and regimeOkL and mtfOkL and locOkL and candleOkL and trendOkL
- bool sellBase = warmedUp and trigShort and scoreShort >= reqShort and volatOk and regimeOkS and mtfOkS and locOkS and candleOkS and trendOkS
- bool rawBuy = buyBase and (not sellBase or scoreLong >= scoreShort)
- bool rawSell = sellBase and (not buyBase or scoreShort > scoreLong)
- bool weakLongNow = (emaFast < emaSlow and macdHist < 0 and close < emaFast) or bosDn
- bool weakShortNow = (emaFast > emaSlow and macdHist > 0 and close > emaFast) or bosUp
- int weakNeeded = isRanging or lowVol ? 2 : 1
- var TradeLevels trade = TradeLevels.new()
- var LevelDrawings drw = LevelDrawings.new()
- var int pos = 0
- var float trailStop = na
- var bool tp1Hit = false
- var bool tp2Hit = false
- var bool tp3Hit = false
- var int weakCount = 0
- var int lastExitBar = -100000
- bool confirmed = not i_confirmBar or barstate.isconfirmed
- bool sigBuy = false
- bool sigSell = false
- bool sigExitLong = false
- bool sigExitShort = false
- bool sigFlip = false
- bool evTp1 = false
- bool evTp2 = false
- bool evTp3 = false
- bool evSl = false
- float exitPrice = na
- string exitReason = ""
- if confirmed
- if pos == 1 and bar_index > trade.entryBar
- if not tp1Hit and high >= trade.tp1
- tp1Hit := true
- evTp1 := true
- if not tp2Hit and high >= trade.tp2
- tp2Hit := true
- evTp2 := true
- if not tp3Hit and high >= trade.tp3
- tp3Hit := true
- evTp3 := true
- float trailCandL = close - atrSafe * (strongLong ? pTrailStrong : pTrailWeak)
- if tp1Hit
- trailStop := na(trailStop) ? trailCandL : math.max(trailStop, trailCandL)
- weakCount := weakLongNow ? weakCount + 1 : 0
- bool flipNowL = isFutures and rawSell
- if low <= trade.sl
- sigExitLong := true
- evSl := true
- exitPrice := trade.sl
- exitReason := "Stop Loss"
- else if not flipNowL and i_exitAtTp3 and tp3Hit
- sigExitLong := true
- exitPrice := trade.tp3
- exitReason := "TP3 Target"
- else if not flipNowL and i_useTrail and tp1Hit and not na(trailStop) and close < trailStop
- sigExitLong := true
- exitPrice := close
- exitReason := "Trailing Stop"
- else if not flipNowL and i_useWeakExit and weakCount >= weakNeeded
- sigExitLong := true
- exitPrice := close
- exitReason := "Momentum Weakness"
- else if not isFutures and rawSell
- sigExitLong := true
- exitPrice := close
- exitReason := "Bearish Conditions"
- if pos == -1 and bar_index > trade.entryBar
- if not tp1Hit and low <= trade.tp1
- tp1Hit := true
- evTp1 := true
- if not tp2Hit and low <= trade.tp2
- tp2Hit := true
- evTp2 := true
- if not tp3Hit and low <= trade.tp3
- tp3Hit := true
- evTp3 := true
- float trailCandS = close + atrSafe * (strongShort ? pTrailStrong : pTrailWeak)
- if tp1Hit
- trailStop := na(trailStop) ? trailCandS : math.min(trailStop, trailCandS)
- weakCount := weakShortNow ? weakCount + 1 : 0
- bool flipNowS = isFutures and rawBuy
- if high >= trade.sl
- sigExitShort := true
- evSl := true
- exitPrice := trade.sl
- exitReason := "Stop Loss"
- else if not flipNowS and i_exitAtTp3 and tp3Hit
- sigExitShort := true
- exitPrice := trade.tp3
- exitReason := "TP3 Target"
- else if not flipNowS and i_useTrail and tp1Hit and not na(trailStop) and close > trailStop
- sigExitShort := true
- exitPrice := close
- exitReason := "Trailing Stop"
- else if not flipNowS and i_useWeakExit and weakCount >= weakNeeded
- sigExitShort := true
- exitPrice := close
- exitReason := "Momentum Weakness"
- if sigExitLong or sigExitShort
- pos := 0
- lastExitBar := bar_index
- trailStop := na
- weakCount := 0
- bool canEnter = bar_index - lastExitBar >= pCooldown
- float riskDist = atrSafe * i_slAtr * pSlFactor
- if pos == 0 and canEnter and rawBuy
- sigBuy := true
- else if pos == 0 and canEnter and isFutures and rawSell
- sigSell := true
- else if pos == 1 and isFutures and rawSell
- sigSell := true
- sigFlip := true
- else if pos == -1 and isFutures and rawBuy
- sigBuy := true
- sigFlip := true
- if sigBuy or sigSell
- int newDir = sigBuy ? 1 : -1
- trade := f_newTrade(newDir, close, riskDist)
- pos := newDir
- tp1Hit := false
- tp2Hit := false
- tp3Hit := false
- trailStop := na
- weakCount := 0
- bool exitLongEvt = sigExitLong or (sigFlip and sigSell)
- bool exitShortEvt = sigExitShort or (sigFlip and sigBuy)
- string sigSize = f_labelSize(i_signalSize)
- if sigBuy and i_showSignals
- label.new(x = bar_index, y = low, text = "BUY", xloc = xloc.bar_index, yloc = yloc.belowbar, color = c_buy, style = label.style_label_up, textcolor = c_sigText, size = sigSize, tooltip = INDICATOR_NAME + "\nBUY @ " + f_fmt(close) + "\nScore: " + str.tostring(scoreLong, "#.0") + "\nSL: " + f_fmt(trade.sl) + "\nTP1: " + f_fmt(trade.tp1) + "\nTP2: " + f_fmt(trade.tp2) + "\nTP3: " + f_fmt(trade.tp3))
- if sigSell and i_showSignals
- label.new(x = bar_index, y = high, text = "SELL", xloc = xloc.bar_index, yloc = yloc.abovebar, color = c_sell, style = label.style_label_down, textcolor = c_sigText, size = sigSize, tooltip = INDICATOR_NAME + "\nSELL @ " + f_fmt(close) + "\nScore: " + str.tostring(scoreShort, "#.0") + "\nSL: " + f_fmt(trade.sl) + "\nTP1: " + f_fmt(trade.tp1) + "\nTP2: " + f_fmt(trade.tp2) + "\nTP3: " + f_fmt(trade.tp3))
- if sigExitLong and i_showExit
- label.new(x = bar_index, y = high, text = "EXIT", xloc = xloc.bar_index, yloc = yloc.abovebar, color = c_exit, style = label.style_label_down, textcolor = c_sigText, size = sigSize, tooltip = INDICATOR_NAME + "\nEXIT Long @ " + f_fmt(exitPrice) + "\nReason: " + exitReason)
- if sigExitShort and i_showExit
- label.new(x = bar_index, y = low, text = "EXIT", xloc = xloc.bar_index, yloc = yloc.belowbar, color = c_exit, style = label.style_label_up, textcolor = c_sigText, size = sigSize, tooltip = INDICATOR_NAME + "\nEXIT Short @ " + f_fmt(exitPrice) + "\nReason: " + exitReason)
- int levelEnd = bar_index + i_levelOffset
- if (sigExitLong or sigExitShort) and not (sigBuy or sigSell)
- drw.clearAll()
- if (sigBuy or sigSell) and i_showLevels
- drw.build(trade, levelEnd)
- if barstate.islast and pos != 0 and i_showLevels
- drw.extendTo(levelEnd)
- plot(sigBuy ? 1 : 0, "BUY", color = c_buy, display = display.status_line + display.data_window)
- plot(sigSell ? 1 : 0, "SELL", color = c_sell, display = display.status_line + display.data_window)
- plot(sigBuy ? 1 : sigSell ? -1 : 0, "Entry Signal", color = c_entry, display = display.status_line + display.data_window)
- plot(exitLongEvt ? 1 : 0, "EXIT Long", color = c_exit, display = display.status_line + display.data_window)
- plot(exitShortEvt ? 1 : 0, "EXIT Short", color = c_exit, display = display.status_line + display.data_window)
- f_dashRow(table t, int row, string key, string val, color valBg, string ts) =>
- table.cell(t, 0, row, key, text_color = c_dashText, bgcolor = c_dashBg, text_size = ts, text_halign = text.align_center)
- table.cell(t, 1, row, val, text_color = c_dashValText, bgcolor = valBg, text_size = ts, text_halign = text.align_center)
- var table dash = i_showDash ? table.new(f_tablePos(i_dashPos), 2, 9, bgcolor = c_dashBg, frame_color = c_dashBorder, frame_width = 1, border_color = c_dashBorder, border_width = 1) : na
- if barstate.isfirst and i_showDash
- table.merge_cells(dash, 0, 0, 1, 0)
- if barstate.islast and i_showDash
- string dts = f_dashTextSize(i_dashSize)
- table.cell(dash, 0, 0, INDICATOR_NAME, text_color = c_dashText, bgcolor = c_dashBg, text_size = dts, text_halign = text.align_center)
- f_dashRow(dash, 1, "Mode", f_modeText(i_mode), c_dashMode, dts)
- f_dashRow(dash, 2, "Market", i_market, isFutures ? c_dashFutures : c_dashSpot, dts)
- f_dashRow(dash, 3, "Current Trend", f_trendText(chartTrend), f_trendColor(chartTrend), dts)
- f_dashRow(dash, 4, f_tfLabel(i_tf1), f_trendText(mtf1), f_trendColor(mtf1), dts)
- f_dashRow(dash, 5, f_tfLabel(i_tf2), f_trendText(mtf2), f_trendColor(mtf2), dts)
- f_dashRow(dash, 6, f_tfLabel(i_tf3), f_trendText(mtf3), f_trendColor(mtf3), dts)
- f_dashRow(dash, 7, f_tfLabel(i_tf4), f_trendText(mtf4), f_trendColor(mtf4), dts)
- f_dashRow(dash, 8, f_tfLabel(i_tf5), f_trendText(mtf5), f_trendColor(mtf5), dts)
- f_fillTemplate(string tpl, string action, float price, TradeLevels t, string reason) =>
- string s = tpl
- s := str.replace_all(s, "{action}", action)
- s := str.replace_all(s, "{ticker}", syminfo.ticker)
- s := str.replace_all(s, "{exchange}", syminfo.prefix)
- s := str.replace_all(s, "{timeframe}", timeframe.period)
- s := str.replace_all(s, "{price}", f_fmt(price))
- s := str.replace_all(s, "{entry}", f_fmt(t.entry))
- s := str.replace_all(s, "{sl}", f_fmt(t.sl))
- s := str.replace_all(s, "{tp1}", f_fmt(t.tp1))
- s := str.replace_all(s, "{tp2}", f_fmt(t.tp2))
- s := str.replace_all(s, "{tp3}", f_fmt(t.tp3))
- s := str.replace_all(s, "{mode}", i_mode)
- s := str.replace_all(s, "{market}", i_market)
- s := str.replace_all(s, "{reason}", reason)
- s
- f_alertMsg(string action, string custom, float price, TradeLevels t, string reason) =>
- string msg = ""
- if str.length(custom) > 0
- msg := f_fillTemplate(custom, action, price, t, reason)
- else if i_alertFormat == "JSON"
- msg := '{"indicator":"' + INDICATOR_NAME + '","action":"' + action + '","ticker":"' + syminfo.ticker + '","exchange":"' + syminfo.prefix + '","timeframe":"' + timeframe.period + '","mode":"' + i_mode + '","market":"' + i_market + '","price":' + f_fmt(price) + ',"entry":' + f_fmt(t.entry) + ',"sl":' + f_fmt(t.sl) + ',"tp1":' + f_fmt(t.tp1) + ',"tp2":' + f_fmt(t.tp2) + ',"tp3":' + f_fmt(t.tp3) + ',"reason":"' + reason + '"}'
- else
- msg := INDICATOR_NAME + " | " + action + " | " + syminfo.ticker + " (" + timeframe.period + ") | Price: " + f_fmt(price) + " | Entry: " + f_fmt(t.entry) + " | SL: " + f_fmt(t.sl) + " | TP1: " + f_fmt(t.tp1) + " | TP2: " + f_fmt(t.tp2) + " | TP3: " + f_fmt(t.tp3) + " | " + reason
- msg
- if i_alertExit and sigFlip and sigSell
- alert(f_alertMsg("EXIT LONG", i_msgExit, close, trade, "Directional Transition"), alert.freq_once_per_bar_close)
- if i_alertExit and sigFlip and sigBuy
- alert(f_alertMsg("EXIT SHORT", i_msgExit, close, trade, "Directional Transition"), alert.freq_once_per_bar_close)
- if i_alertBuy and sigBuy
- alert(f_alertMsg("BUY", i_msgBuy, close, trade, sigFlip ? "Transition From Short" : "New Long"), alert.freq_once_per_bar_close)
- if i_alertSell and sigSell
- alert(f_alertMsg("SELL", i_msgSell, close, trade, sigFlip ? "Transition From Long" : "New Short"), alert.freq_once_per_bar_close)
- if i_alertSl and evSl
- alert(f_alertMsg("SL HIT", i_msgExit, exitPrice, trade, "Stop Loss"), alert.freq_once_per_bar_close)
- if i_alertExit and sigExitLong
- alert(f_alertMsg("EXIT LONG", i_msgExit, exitPrice, trade, exitReason), alert.freq_once_per_bar_close)
- if i_alertExit and sigExitShort
- alert(f_alertMsg("EXIT SHORT", i_msgExit, exitPrice, trade, exitReason), alert.freq_once_per_bar_close)
- if i_alertTp and evTp1
- alert(f_alertMsg("TP1 HIT", i_msgExit, trade.tp1, trade, "Take Profit 1"), alert.freq_once_per_bar_close)
- if i_alertTp and evTp2
- alert(f_alertMsg("TP2 HIT", i_msgExit, trade.tp2, trade, "Take Profit 2"), alert.freq_once_per_bar_close)
- if i_alertTp and evTp3
- alert(f_alertMsg("TP3 HIT", i_msgExit, trade.tp3, trade, "Take Profit 3"), alert.freq_once_per_bar_close)
- alertcondition(sigBuy, "Prime Indicator - BUY", "Prime Indicator v1.2.0: BUY on {{exchange}}:{{ticker}} ({{interval}}) at {{close}}")
- alertcondition(sigSell, "Prime Indicator - SELL", "Prime Indicator v1.2.0: SELL on {{exchange}}:{{ticker}} ({{interval}}) at {{close}}")
- alertcondition(exitLongEvt, "Prime Indicator - EXIT Long", "Prime Indicator v1.2.0: EXIT LONG on {{exchange}}:{{ticker}} ({{interval}}) at {{close}}")
- alertcondition(exitShortEvt, "Prime Indicator - EXIT Short", "Prime Indicator v1.2.0: EXIT SHORT on {{exchange}}:{{ticker}} ({{interval}}) at {{close}}")
- alertcondition(exitLongEvt or exitShortEvt, "Prime Indicator - EXIT (Any)", "Prime Indicator v1.2.0: EXIT on {{exchange}}:{{ticker}} ({{interval}}) at {{close}}")
- alertcondition(sigBuy or sigSell or exitLongEvt or exitShortEvt, "Prime Indicator - Any Signal", "Prime Indicator v1.2.0: new BUY / SELL / EXIT signal on {{exchange}}:{{ticker}} ({{interval}}) at {{close}}")
- alertcondition(evTp1, "Prime Indicator - TP1 Hit", "Prime Indicator v1.2.0: TP1 reached on {{exchange}}:{{ticker}} ({{interval}})")
- alertcondition(evTp2, "Prime Indicator - TP2 Hit", "Prime Indicator v1.2.0: TP2 reached on {{exchange}}:{{ticker}} ({{interval}})")
- alertcondition(evTp3, "Prime Indicator - TP3 Hit", "Prime Indicator v1.2.0: TP3 reached on {{exchange}}:{{ticker}} ({{interval}})")
- alertcondition(evSl, "Prime Indicator - SL Hit", "Prime Indicator v1.2.0: Stop Loss hit on {{exchange}}:{{ticker}} ({{interval}})")
Advertisement