maclce-algonexta.pine · 198 lines · 11.1 KB
Not yet verified on the native platform — test it before relying on it.
The original uploaded source.
// ============================================================================
// © algonexta
// This script is for education and research; it does not guarantee results.
// Verify this source in TradingView before use.
// ============================================================================
//@version=6
indicator("AlgoNexta MAC/ICE V1", "MAC/ICE V1", overlay = true, max_labels_count = 500, max_lines_count = 500)
// Signals
string GROUP_SIGNAL = "Signal Inputs"
float source = input.source(close, "Source", group = GROUP_SIGNAL)
int shortEmaPeriod = input.int(60, "Short EMA", minval = 1, group = GROUP_SIGNAL)
int longEmaPeriod = input.int(240, "Long EMA", minval = 1, group = GROUP_SIGNAL)
int macdFastPeriod = input.int(12, "MACD Fast", minval = 1, group = GROUP_SIGNAL)
int macdSlowPeriod = input.int(26, "MACD Slow", minval = 1, group = GROUP_SIGNAL)
int macdSignalPeriod = input.int(9, "MACD Signal", minval = 1, group = GROUP_SIGNAL)
string signalMode = input.string("EMA trend MACD crosses", "Signal mode", options = ["Exact cTrader", "EMA trend MACD crosses"], group = GROUP_SIGNAL)
// Risk management
string GROUP_RISK = "Risk Management"
int atrPeriod = input.int(14, "ATR Period", minval = 1, group = GROUP_RISK)
float atrMultiplier = input.float(1.5, "SL ATR Multiplier", minval = 0.1, step = 0.1, group = GROUP_RISK)
float riskPercent = input.float(1.0, "Account Risk %", minval = 0.1, maxval = 100, step = 0.1, group = GROUP_RISK)
float accountBalance = input.float(10000.0, "Account Balance", minval = 0.0, step = 100.0, group = GROUP_RISK)
float unitPointValue = input.float(1.0, "Value of 1.0 Price Move per Unit", minval = 0.000001, step = 0.01, group = GROUP_RISK, tooltip = "Set this to the cash P/L of one trading unit when price moves by 1.0. For XAUUSD, one ounce is commonly 1; verify with your broker.")
int projectionBars = input.int(35, "Level Projection Bars", minval = 5, maxval = 500, group = GROUP_RISK)
int historicalSetups = input.int(50, "Historical Setups", minval = 1, maxval = 65, group = GROUP_RISK, tooltip = "Number of previous signal risk boxes to keep on the chart.")
// Appearance
string GROUP_DISPLAY = "Appearance"
bool showEma = input.bool(true, "Show EMAs", group = GROUP_DISPLAY)
bool shadeTrend = input.bool(true, "Shade EMA Trend", group = GROUP_DISPLAY)
bool showPriceLabels = input.bool(true, "Show Level Prices", group = GROUP_DISPLAY)
color buyColor = input.color(color.rgb(0, 210, 150), "Buy Color", group = GROUP_DISPLAY)
color sellColor = input.color(color.rgb(255, 72, 88), "Sell Color", group = GROUP_DISPLAY)
float emaShort = ta.ema(source, shortEmaPeriod)
float emaLong = ta.ema(source, longEmaPeriod)
[macdLine, macdSignalLine, _] = ta.macd(source, macdFastPeriod, macdSlowPeriod, macdSignalPeriod)
float atrValue = ta.atr(atrPeriod)
bool bullish = emaShort > emaLong
bool bearish = emaShort < emaLong
bool macdCrossUp = ta.crossover(macdLine, macdSignalLine)
bool macdCrossDown = ta.crossunder(macdLine, macdSignalLine)
bool exactBuy = bullish and macdLine < 0 and macdCrossUp
bool exactSell = bearish and macdLine > 0 and macdCrossDown
bool rawBuy = signalMode == "Exact cTrader" ? exactBuy : bullish and macdCrossUp
bool rawSell = signalMode == "Exact cTrader" ? exactSell : bearish and macdCrossDown
color transparent = color.new(color.white, 100)
shortPlot = plot(showEma ? emaShort : na, "Fast EMA", color = color.new(bullish ? buyColor : sellColor, 5), linewidth = 2)
longPlot = plot(showEma ? emaLong : na, "Slow EMA", color = color.new(color.silver, 25), linewidth = 2)
fill(shortPlot, longPlot, color = shadeTrend and showEma ? color.new(bullish ? buyColor : sellColor, 90) : transparent, title = "Trend Shade")
// Signals must alternate: after BUY, another BUY is ignored until a valid SELL,
// and vice versa. Risk levels themselves remain active until SL, TP3, or reversal.
var bool tradeActive = false
var int tradeDirection = 0
var int lastSignalDirection = 0
var int entryBar = na
var float entryPrice = na
var float stopPrice = na
var float tp1Price = na
var float tp2Price = na
var float tp3Price = na
var int reachedR = 0
var line entryLine = na
var line stopLine = na
var line tp1Line = na
var line tp2Line = na
var line tp3Line = na
var linefill riskFill = na
var linefill rewardFill = na
var label entryLabel = na
var label stopLabel = na
var label tp1Label = na
var label tp2Label = na
var label tp3Label = na
var label statusLabel = na
// Keep completed setups visible. The arrays let us remove only the oldest
// setup when the user-selected history limit is exceeded.
var array<line> setupLines = array.new<line>()
var array<linefill> setupFills = array.new<linefill>()
var array<label> setupLabels = array.new<label>()
trimSetupHistory() =>
while array.size(setupLines) > historicalSetups * 5
for i = 0 to 4
line.delete(array.shift(setupLines))
for i = 0 to 1
linefill.delete(array.shift(setupFills))
for i = 0 to 5
label.delete(array.shift(setupLabels))
bool acceptedBuy = barstate.isconfirmed and rawBuy and not rawSell and lastSignalDirection != 1 and not na(atrValue) and atrValue > 0
bool acceptedSell = barstate.isconfirmed and rawSell and not rawBuy and lastSignalDirection != -1 and not na(atrValue) and atrValue > 0
// Resolve an existing setup on the completed candle BEFORE accepting a reversal.
// On OHLC bars, if SL and TP are both touched, SL takes precedence.
if barstate.isconfirmed and tradeActive and bar_index > entryBar
bool stopHit = tradeDirection == 1 ? low <= stopPrice : high >= stopPrice
bool tp1Hit = tradeDirection == 1 ? high >= tp1Price : low <= tp1Price
bool tp2Hit = tradeDirection == 1 ? high >= tp2Price : low <= tp2Price
bool tp3Hit = tradeDirection == 1 ? high >= tp3Price : low <= tp3Price
if stopHit
tradeActive := false
label.set_text(statusLabel, "SL HIT\n-1R (full-position reference)")
label.set_color(statusLabel, sellColor)
line.set_color(stopLine, color.white)
else
if tp1Hit and reachedR < 1
reachedR := 1
line.set_style(tp1Line, line.style_solid)
line.set_width(tp1Line, 2)
if tp2Hit and reachedR < 2
reachedR := 2
line.set_style(tp2Line, line.style_solid)
line.set_width(tp2Line, 2)
if tp3Hit
reachedR := 3
tradeActive := false
label.set_text(statusLabel, "TP3 HIT\n+3R (full-position reference)")
label.set_color(statusLabel, buyColor)
line.set_color(tp3Line, color.white)
if acceptedBuy or acceptedSell
if tradeActive
tradeActive := false
label.set_text(statusLabel, "REVERSED\nMax TP touched: " + str.tostring(reachedR) + "R (not realized P/L)")
label.set_color(statusLabel, color.gray)
tradeActive := true
tradeDirection := acceptedBuy ? 1 : -1
lastSignalDirection := tradeDirection
entryBar := bar_index
entryPrice := close
float riskDistance = atrValue * atrMultiplier
float riskCash = accountBalance * riskPercent / 100.0
float suggestedUnits = riskCash / (riskDistance * unitPointValue)
stopPrice := entryPrice - tradeDirection * riskDistance
tp1Price := entryPrice + tradeDirection * riskDistance
tp2Price := entryPrice + tradeDirection * riskDistance * 2.0
tp3Price := entryPrice + tradeDirection * riskDistance * 3.0
reachedR := 0
int x2 = bar_index + projectionBars
color directionColor = tradeDirection == 1 ? buyColor : sellColor
entryLine := line.new(bar_index, entryPrice, x2, entryPrice, color = color.white, width = 2)
stopLine := line.new(bar_index, stopPrice, x2, stopPrice, color = sellColor, width = 2)
tp1Line := line.new(bar_index, tp1Price, x2, tp1Price, color = color.new(buyColor, 35), style = line.style_dashed)
tp2Line := line.new(bar_index, tp2Price, x2, tp2Price, color = color.new(buyColor, 15), style = line.style_dashed)
tp3Line := line.new(bar_index, tp3Price, x2, tp3Price, color = buyColor, width = 2)
riskFill := linefill.new(entryLine, stopLine, color.new(sellColor, 88))
rewardFill := linefill.new(entryLine, tp3Line, color.new(buyColor, 91))
string priceSuffix = showPriceLabels ? " " + str.tostring(entryPrice, format.mintick) : ""
entryLabel := label.new(x2, entryPrice, (tradeDirection == 1 ? "LONG" : "SHORT") + " ENTRY" + priceSuffix, xloc = xloc.bar_index, style = label.style_label_left, color = directionColor, textcolor = color.white, size = size.small)
stopLabel := label.new(x2, stopPrice, "SL" + (showPriceLabels ? " " + str.tostring(stopPrice, format.mintick) : ""), xloc = xloc.bar_index, style = label.style_label_left, color = sellColor, textcolor = color.white, size = size.small)
tp1Label := label.new(x2, tp1Price, "TP1 | 1R (reference)", xloc = xloc.bar_index, style = label.style_label_left, color = color.new(buyColor, 25), textcolor = color.white, size = size.tiny)
tp2Label := label.new(x2, tp2Price, "TP2 | 2R (reference)", xloc = xloc.bar_index, style = label.style_label_left, color = color.new(buyColor, 12), textcolor = color.white, size = size.tiny)
tp3Label := label.new(x2, tp3Price, "TP3 | 3R" + (showPriceLabels ? " " + str.tostring(tp3Price, format.mintick) : ""), xloc = xloc.bar_index, style = label.style_label_left, color = buyColor, textcolor = color.white, size = size.small)
statusLabel := label.new(bar_index, tradeDirection == 1 ? low : high, (tradeDirection == 1 ? "BUY" : "SELL") + "\nRisk " + str.tostring(riskPercent, "#.##") + "% | Size " + str.tostring(suggestedUnits, "#.##"), style = tradeDirection == 1 ? label.style_label_up : label.style_label_down, color = directionColor, textcolor = color.white)
array.push(setupLines, entryLine)
array.push(setupLines, stopLine)
array.push(setupLines, tp1Line)
array.push(setupLines, tp2Line)
array.push(setupLines, tp3Line)
array.push(setupFills, riskFill)
array.push(setupFills, rewardFill)
array.push(setupLabels, entryLabel)
array.push(setupLabels, stopLabel)
array.push(setupLabels, tp1Label)
array.push(setupLabels, tp2Label)
array.push(setupLabels, tp3Label)
array.push(setupLabels, statusLabel)
trimSetupHistory()
// Keep the active setup projected to the right as new bars arrive.
if tradeActive
int liveX2 = bar_index + projectionBars
line.set_x2(entryLine, liveX2)
line.set_x2(stopLine, liveX2)
line.set_x2(tp1Line, liveX2)
line.set_x2(tp2Line, liveX2)
line.set_x2(tp3Line, liveX2)
label.set_x(entryLabel, liveX2)
label.set_x(stopLabel, liveX2)
label.set_x(tp1Label, liveX2)
label.set_x(tp2Label, liveX2)
label.set_x(tp3Label, liveX2)
plotshape(acceptedBuy, "Buy Signal", shape.triangleup, location.belowbar, buyColor, size = size.small)
plotshape(acceptedSell, "Sell Signal", shape.triangledown, location.abovebar, sellColor, size = size.small)
alertcondition(acceptedBuy, "AlgoNexta MAC/ICE Buy", "MAC/ICE BUY on {{ticker}} {{interval}}")
alertcondition(acceptedSell, "AlgoNexta MAC/ICE Sell", "MAC/ICE SELL on {{ticker}} {{interval}}")
alertcondition(barstate.isconfirmed and not tradeActive and tradeActive[1], "AlgoNexta MAC/ICE Setup Closed", "MAC/ICE setup closed on {{ticker}} {{interval}}")