//@version=6 indicator("Hercules GUS-V5 ยท Confirmed", shorttitle="GUS-V5", overlay=true, max_labels_count=200) // Hercules uses standard exchange candles for every calculation. Heikin Ashi may be // used as a visual chart style, but it must not become the indicator's source. groupSignal = "Signals" wtChannel = input.int(9, "WaveTrend channel", minval=2, group=groupSignal) wtAverage = input.int(12, "WaveTrend average", minval=2, group=groupSignal) wtSmooth = input.int(3, "WaveTrend signal", minval=1, group=groupSignal) wtOversold = input.float(-53.0, "WaveTrend oversold", group=groupSignal) wtOverbought = input.float(53.0, "WaveTrend overbought", group=groupSignal) requireTrend = input.bool(false, "Require trend alignment", group=groupSignal) showTrendWatch = input.bool(true, "Show trend-continuation watch", group=groupSignal) groupTrend = "Trend and volatility" emaFastLength = input.int(20, "Fast EMA", minval=2, group=groupTrend) emaSlowLength = input.int(50, "Slow EMA", minval=3, group=groupTrend) emaContextLength = input.int(200, "Context EMA", minval=10, group=groupTrend) atrLength = input.int(14, "ATR length", minval=2, group=groupTrend) supertrendLength = input.int(10, "Supertrend ATR", minval=2, group=groupTrend) supertrendFactor = input.float(3.0, "Supertrend factor", minval=0.1, step=0.1, group=groupTrend) showBands = input.bool(false, "Show Bollinger bands", group=groupTrend) showSessionVwap = input.bool(true, "Show session VWAP", group=groupTrend) groupRisk = "Reference levels" showAtrLevels = input.bool(true, "Show ATR invalidation/target after signal", group=groupRisk) stopAtr = input.float(1.5, "Invalidation ATR", minval=0.1, step=0.1, group=groupRisk) targetAtr = input.float(2.5, "Target ATR", minval=0.1, step=0.1, group=groupRisk) // ticker.standard keeps calculations on exchange OHLC even when the operator // displays Heikin-Ashi or another synthetic chart type. standardTicker = ticker.standard(syminfo.tickerid) [rawOpen, rawHigh, rawLow, rawClose, rawVolume, standardVwap] = request.security(standardTicker, timeframe.period, [open, high, low, close, volume, ta.vwap(hlc3)], gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off) f_waveTrend(float source, int channelLength, int averageLength, int signalLength) => float esa = ta.ema(source, channelLength) float deviation = ta.ema(math.abs(source - esa), channelLength) float ci = deviation == 0.0 ? 0.0 : (source - esa) / (0.015 * deviation) float wave = ta.ema(ci, averageLength) float signal = ta.sma(wave, signalLength) [wave, signal] [wt1, wt2] = f_waveTrend((rawHigh + rawLow + rawClose) / 3.0, wtChannel, wtAverage, wtSmooth) ema20 = ta.ema(rawClose, emaFastLength) ema50 = ta.ema(rawClose, emaSlowLength) ema200 = ta.ema(rawClose, emaContextLength) rsi = ta.rsi(rawClose, 14) [macdLine, macdSignal, macdHistogram] = ta.macd(rawClose, 12, 26, 9) rawTrueRange = math.max(rawHigh - rawLow, math.max(math.abs(rawHigh - rawClose[1]), math.abs(rawLow - rawClose[1]))) atr = ta.rma(rawTrueRange, atrLength) atrPercent = rawClose == 0.0 ? na : atr / rawClose * 100.0 basis = ta.sma(rawClose, 20) deviation = ta.stdev(rawClose, 20) bbUpper = basis + 2.0 * deviation bbLower = basis - 2.0 * deviation bbWidth = basis == 0.0 ? na : (bbUpper - bbLower) / basis * 100.0 sessionVwap = standardVwap [supertrend, supertrendDirection] = request.security(standardTicker, timeframe.period, ta.supertrend(supertrendFactor, supertrendLength), gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off) trendBull = ema20 > ema50 and rawClose > ema20 and supertrendDirection < 0 trendBear = ema20 < ema50 and rawClose < ema20 and supertrendDirection > 0 momentumBull = rsi > 50.0 and rsi < 70.0 and macdHistogram > 0.0 momentumBear = rsi < 50.0 and rsi > 30.0 and macdHistogram < 0.0 // Signals are committed only when the realtime bar is confirmed. They do not // move into the past. request.security() is used only with ticker.standard and // lookahead_off so a synthetic display never becomes the signal source. confirmed = barstate.isconfirmed gusLongRaw = ta.crossover(wt1, wt2) and wt2 <= wtOversold gusShortRaw = ta.crossunder(wt1, wt2) and wt2 >= wtOverbought gusLong = confirmed and gusLongRaw and (not requireTrend or trendBull) gusShort = confirmed and gusShortRaw and (not requireTrend or trendBear) trendLongWatch = confirmed and showTrendWatch and trendBull and momentumBull trendShortWatch = confirmed and showTrendWatch and trendBear and momentumBear plot(ema20, "EMA fast", color=color.new(#36c2d7, 0), linewidth=1) plot(ema50, "EMA slow", color=color.new(#efc45c, 15), linewidth=2) plot(ema200, "EMA context", color=color.new(#9aa8ba, 35), linewidth=2) plot(showSessionVwap ? sessionVwap : na, "Session VWAP", color=color.new(#c98bff, 15), linewidth=1) plot(supertrend, "Supertrend", color=supertrendDirection < 0 ? color.new(#20c98b, 20) : color.new(#f06575, 20), style=plot.style_linebr) bbUpperPlot = plot(showBands ? bbUpper : na, "BB upper", color=color.new(#8094aa, 60)) bbLowerPlot = plot(showBands ? bbLower : na, "BB lower", color=color.new(#8094aa, 60)) fill(bbUpperPlot, bbLowerPlot, color=color.new(#60788f, 92), title="Bollinger envelope") plotshape(gusLong, title="GUS-V5 LONG", style=shape.labelup, location=location.belowbar, color=#176647, text="GUS L", textcolor=color.white, size=size.tiny) plotshape(gusShort, title="GUS-V5 SHORT", style=shape.labeldown, location=location.abovebar, color=#842f3f, text="GUS S", textcolor=color.white, size=size.tiny) plotshape(trendLongWatch and not gusLong, title="Trend LONG watch", style=shape.triangleup, location=location.belowbar, color=#36c2d7, text="T", textcolor=#071524, size=size.tiny) plotshape(trendShortWatch and not gusShort, title="Trend SHORT watch", style=shape.triangledown, location=location.abovebar, color=#efc45c, text="T", textcolor=#071524, size=size.tiny) var float activeEntry = na var float activeStop = na var float activeTarget = na if gusLong activeEntry := rawClose activeStop := rawClose - atr * stopAtr activeTarget := rawClose + atr * targetAtr else if gusShort activeEntry := rawClose activeStop := rawClose + atr * stopAtr activeTarget := rawClose - atr * targetAtr plot(showAtrLevels ? activeEntry : na, "Signal reference", color=color.new(#36c2d7, 35), style=plot.style_linebr) plot(showAtrLevels ? activeStop : na, "ATR invalidation", color=color.new(#f06575, 15), style=plot.style_linebr) plot(showAtrLevels ? activeTarget : na, "ATR target", color=color.new(#20c98b, 15), style=plot.style_linebr) f_state(bool bull, bool bear) => bull ? "BULL" : bear ? "BEAR" : "MIXED" f_color(bool bull, bool bear) => bull ? #20c98b : bear ? #f06575 : #efc45c var table status = table.new(position.bottom_right, 2, 7, bgcolor=color.new(#101923, 10), frame_color=color.new(#526173, 35), border_width=1) if barstate.islast table.cell(status, 0, 0, "GUS-V5", text_color=color.silver) table.cell(status, 1, 0, confirmed ? "CONFIRMED" : "FORMING", text_color=confirmed ? #20c98b : #efc45c) table.cell(status, 0, 1, "Trend", text_color=color.silver) table.cell(status, 1, 1, f_state(trendBull, trendBear), text_color=f_color(trendBull, trendBear)) table.cell(status, 0, 2, "WT1 / WT2", text_color=color.silver) table.cell(status, 1, 2, str.tostring(wt1, "#.0") + " / " + str.tostring(wt2, "#.0"), text_color=color.white) table.cell(status, 0, 3, "RSI 14", text_color=color.silver) table.cell(status, 1, 3, str.tostring(rsi, "#.0"), text_color=rsi > 55 ? #20c98b : rsi < 45 ? #f06575 : #efc45c) table.cell(status, 0, 4, "MACD hist", text_color=color.silver) table.cell(status, 1, 4, str.tostring(macdHistogram, "#.####"), text_color=macdHistogram > 0 ? #20c98b : #f06575) table.cell(status, 0, 5, "ATR 14", text_color=color.silver) table.cell(status, 1, 5, str.tostring(atrPercent, "#.##") + "%", text_color=color.white) table.cell(status, 0, 6, "BB width", text_color=color.silver) table.cell(status, 1, 6, str.tostring(bbWidth, "#.##") + "%", text_color=color.white) rawCloseForAlert = plot(rawClose, "Raw close for alert", display=display.none) alertcondition(gusLong, "GUS-V5 LONG confirmed", "{\"schema\":\"hercules.signal.v1\",\"strategy\":\"GUS-V5\",\"version\":\"1.0.0\",\"side\":\"LONG\",\"symbol\":\"{{ticker}}\",\"timeframe\":\"{{interval}}\",\"price\":{{plot(\"Raw close for alert\")}},\"barTime\":\"{{time}}\",\"environment\":\"PAPER\"}") alertcondition(gusShort, "GUS-V5 SHORT confirmed", "{\"schema\":\"hercules.signal.v1\",\"strategy\":\"GUS-V5\",\"version\":\"1.0.0\",\"side\":\"SHORT\",\"symbol\":\"{{ticker}}\",\"timeframe\":\"{{interval}}\",\"price\":{{plot(\"Raw close for alert\")}},\"barTime\":\"{{time}}\",\"environment\":\"PAPER\"}") if gusLong alert('{"schema":"hercules.signal.v1","strategy":"GUS-V5","version":"1.0.0","side":"LONG","symbol":"' + standardTicker + '","timeframe":"' + timeframe.period + '","price":' + str.tostring(rawClose) + ',"barTime":' + str.tostring(time_close) + ',"environment":"PAPER"}', alert.freq_once_per_bar_close) else if gusShort alert('{"schema":"hercules.signal.v1","strategy":"GUS-V5","version":"1.0.0","side":"SHORT","symbol":"' + standardTicker + '","timeframe":"' + timeframe.period + '","price":' + str.tostring(rawClose) + ',"barTime":' + str.tostring(time_close) + ',"environment":"PAPER"}', alert.freq_once_per_bar_close)