v7: add SuperTrend + RSI (15m) gate with profiles, HA/Chart source, entry filters, alerts; update README

This commit is contained in:
root
2025-10-21 19:51:24 +02:00
parent a1a0280abd
commit 29d6555803
2 changed files with 186 additions and 0 deletions

View File

@@ -0,0 +1,184 @@
//@version=5
indicator("Bullmania Money Line v7 (SuperTrend + RSI 15m)", overlay=true)
// Calculation source (Chart vs Heikin Ashi) for Money Line
srcMode = input.string("Chart", "Calculation source", options=["Chart","Heikin Ashi"], tooltip="Use regular chart candles or Heikin Ashi for the line calculation.")
// Parameter Mode
paramMode = input.string("Profiles by timeframe", "Parameter Mode", options=["Single", "Profiles by timeframe"], tooltip="Choose whether to use one global set of parameters or timeframe-specific profiles.")
// Single (global) parameters
atrPeriodSingle = input.int(10, "ATR Period (Single mode)", minval=1, group="Single Mode")
multiplierSingle = input.float(3.0, "Multiplier (Single mode)", minval=0.1, step=0.1, group="Single Mode")
// Profile override when using profiles
profileOverride = input.string("Auto", "Profile Override", options=["Auto", "Minutes", "Hours", "Daily", "Weekly/Monthly"], tooltip="When in 'Profiles by timeframe' mode, choose a fixed profile or let it auto-detect from the chart timeframe.", group="Profiles")
// Timeframe profile parameters (defaults tuned from v5)
// Minutes (<= 59m)
atr_m = input.int(12, "ATR Period (Minutes)", minval=1, group="Profiles — Minutes")
mult_m = input.float(3.3, "Multiplier (Minutes)", minval=0.1, step=0.1, group="Profiles — Minutes")
// Hours (>=1h and <1d)
atr_h = input.int(10, "ATR Period (Hours)", minval=1, group="Profiles — Hours")
mult_h = input.float(3.0, "Multiplier (Hours)", minval=0.1, step=0.1, group="Profiles — Hours")
// Daily (>=1d and <1w)
atr_d = input.int(10, "ATR Period (Daily)", minval=1, group="Profiles — Daily")
mult_d = input.float(2.8, "Multiplier (Daily)", minval=0.1, step=0.1, group="Profiles — Daily")
// Weekly/Monthly (>=1w)
atr_w = input.int(7, "ATR Period (Weekly/Monthly)", minval=1, group="Profiles — Weekly/Monthly")
mult_w = input.float(2.5, "Multiplier (Weekly/Monthly)", minval=0.1, step=0.1, group="Profiles — Weekly/Monthly")
// Optional MACD confirmation (same as v5)
useMacd = input.bool(false, "Use MACD confirmation", inline="macd")
macdSrc = input.source(close, "MACD Source", inline="macd")
macdFastLen = input.int(12, "Fast", minval=1, inline="macdLens")
macdSlowLen = input.int(26, "Slow", minval=1, inline="macdLens")
macdSigLen = input.int(9, "Signal", minval=1, inline="macdLens")
// RSI gate (designed for 15m by default)
useRsi = input.bool(true, "Use RSI gate", group="RSI Gate", tooltip="Require RSI to be oversold for longs and overbought for shorts.")
rsiTf = input.timeframe("15", "RSI timeframe", group="RSI Gate")
rsiLen = input.int(14, "RSI Length", minval=1, group="RSI Gate")
rsiOverbought = input.int(70, "RSI Overbought", minval=1, maxval=100, group="RSI Gate")
rsiOversold = input.int(30, "RSI Oversold", minval=1, maxval=100, group="RSI Gate")
// Entry filters (optional, same behavior as v5)
groupFilters = "Entry filters"
useEntryBuffer = input.bool(false, "Require entry buffer (ATR)", group=groupFilters, tooltip="Close must be beyond the Money Line by this buffer to avoid wick flips.")
entryBufferATR = input.float(0.15, "Buffer size (in ATR)", minval=0.0, step=0.05, group=groupFilters, tooltip="0.100.20 works well on intraday.")
confirmBars = input.int(0, "Bars to confirm after flip", minval=0, maxval=2, group=groupFilters, tooltip="0 = show on flip bar. 1 = wait one bar.")
useAdx = input.bool(false, "Use ADX trend-strength filter", group=groupFilters, tooltip="Require ADX above a threshold to reduce chop.")
adxLen = input.int(14, "ADX Length", minval=1, group=groupFilters)
adxMin = input.int(20, "ADX minimum", minval=0, maxval=100, group=groupFilters)
// Determine effective parameters based on selected mode/profile
var string activeProfile = ""
resSec = timeframe.in_seconds(timeframe.period)
isMinutes = resSec < 3600
isHours = resSec >= 3600 and resSec < 86400
isDaily = resSec >= 86400 and resSec < 604800
isWeeklyOrMore = resSec >= 604800
string profileBucket = "Single"
if paramMode == "Single"
profileBucket := "Single"
else
if profileOverride == "Minutes"
profileBucket := "Minutes"
else if profileOverride == "Hours"
profileBucket := "Hours"
else if profileOverride == "Daily"
profileBucket := "Daily"
else if profileOverride == "Weekly/Monthly"
profileBucket := "Weekly/Monthly"
else
profileBucket := isMinutes ? "Minutes" : isHours ? "Hours" : isDaily ? "Daily" : "Weekly/Monthly"
atrPeriod = profileBucket == "Single" ? atrPeriodSingle : profileBucket == "Minutes" ? atr_m : profileBucket == "Hours" ? atr_h : profileBucket == "Daily" ? atr_d : atr_w
multiplier = profileBucket == "Single" ? multiplierSingle : profileBucket == "Minutes" ? mult_m : profileBucket == "Hours" ? mult_h : profileBucket == "Daily" ? mult_d : mult_w
activeProfile := profileBucket
// Build selected source OHLC (for Money Line)
haTicker = ticker.heikinashi(syminfo.tickerid)
[haO, haH, haL, haC] = request.security(haTicker, timeframe.period, [open, high, low, close], lookahead=barmerge.lookahead_off)
calcH = srcMode == "Heikin Ashi" ? haH : high
calcL = srcMode == "Heikin Ashi" ? haL : low
calcC = srcMode == "Heikin Ashi" ? haC : close
// ATR on selected source (true range + RMA)
tr = math.max(calcH - calcL, math.max(math.abs(calcH - calcC[1]), math.abs(calcL - calcC[1])))
atr = ta.rma(tr, atrPeriod)
srcMid = (calcH + calcL) / 2
up = srcMid - (multiplier * atr)
dn = srcMid + (multiplier * atr)
var float up1 = na
var float dn1 = na
up1 := nz(up1[1], up)
dn1 := nz(dn1[1], dn)
up1 := calcC[1] > up1 ? math.max(up, up1) : up
dn1 := calcC[1] < dn1 ? math.min(dn, dn1) : dn
var int trend = 1
var float tsl = na
tsl := nz(tsl[1], up1)
if trend == 1
tsl := math.max(up1, tsl)
trend := calcC < tsl ? -1 : 1
else
tsl := math.min(dn1, tsl)
trend := calcC > tsl ? 1 : -1
supertrend = tsl
// Plot the Money Line
upTrend = trend == 1 ? supertrend : na
downTrend = trend == -1 ? supertrend : na
plot(upTrend, "Up Trend", color=color.new(color.green, 0), style=plot.style_linebr, linewidth=2)
plot(downTrend, "Down Trend", color=color.new(color.red, 0), style=plot.style_linebr, linewidth=2)
// Show active profile/RSI TF
showProfileLabel = input.bool(true, "Show active profile label", group="Profiles")
var label profLbl = na
if barstate.islast and showProfileLabel
if not na(profLbl)
label.delete(profLbl)
profLbl := label.new(bar_index, calcC, text="Profile: " + activeProfile + " | ATR=" + str.tostring(atrPeriod) + " Mult=" + str.tostring(multiplier) + " | RSI TF=" + rsiTf, yloc=yloc.price, style=label.style_label_upper_left, textcolor=color.white, color=color.new(color.blue, 20))
// RSI from selected timeframe (use regular close for RSI by default)
rsiTfVal = request.security(syminfo.tickerid, rsiTf, ta.rsi(close, rsiLen), lookahead=barmerge.lookahead_off)
longRsiOk = not useRsi or (rsiTfVal <= rsiOversold)
shortRsiOk = not useRsi or (rsiTfVal >= rsiOverbought)
// MACD confirmation logic
[macdLine, macdSignal, macdHist] = ta.macd(macdSrc, macdFastLen, macdSlowLen, macdSigLen)
longMacdOk = not useMacd or (macdLine > macdSignal)
shortMacdOk = not useMacd or (macdLine < macdSignal)
// Combined confirmations
longOk = longRsiOk and longMacdOk
shortOk = shortRsiOk and shortMacdOk
// Flip detection
buyFlip = trend == 1 and trend[1] == -1
sellFlip = trend == -1 and trend[1] == 1
// ADX (manual) on selected OHLC if enabled
upMove = calcH - calcH[1]
downMove = calcL[1] - calcL
plusDM = (upMove > downMove and upMove > 0) ? upMove : 0.0
minusDM = (downMove > upMove and downMove > 0) ? downMove : 0.0
trADX = math.max(calcH - calcL, math.max(math.abs(calcH - calcC[1]), math.abs(calcL - calcC[1])))
atrADX = ta.rma(trADX, adxLen)
plusDI = atrADX == 0.0 ? 0.0 : 100.0 * ta.rma(plusDM, adxLen) / atrADX
minusDI = atrADX == 0.0 ? 0.0 : 100.0 * ta.rma(minusDM, adxLen) / atrADX
dx = (plusDI + minusDI == 0.0) ? 0.0 : 100.0 * math.abs(plusDI - minusDI) / (plusDI + minusDI)
adxVal = ta.rma(dx, adxLen)
adxOk = not useAdx or (adxVal > adxMin)
// Entry buffer and confirmation
longBufferOk = not useEntryBuffer or (calcC > supertrend + entryBufferATR * atr)
shortBufferOk = not useEntryBuffer or (calcC < supertrend - entryBufferATR * atr)
buyReady = ta.barssince(buyFlip) == confirmBars
sellReady = ta.barssince(sellFlip) == confirmBars
// Final signals
finalLongSignal = buyReady and longOk and adxOk and longBufferOk
finalShortSignal = sellReady and shortOk and adxOk and shortBufferOk
plotshape(finalLongSignal, title="Buy Signal", location=location.belowbar, color=color.green, style=shape.circle, size=size.small)
plotshape(finalShortSignal, title="Sell Signal", location=location.abovebar, color=color.red, style=shape.circle, size=size.small)
// Fill area between price and Money Line
fill(plot(calcC, display=display.none), plot(upTrend, display=display.none), color=color.new(color.green, 90))
fill(plot(calcC, display=display.none), plot(downTrend, display=display.none), color=color.new(color.red, 90))
// Alerts (set to Once per bar close)
alertcondition(finalLongSignal, title="Bullmania v7 Buy", message="Buy {{ticker}} {{interval}} | Profile={{activeProfile}} ATR={{atrPeriod}} Mult={{multiplier}} | RSI TF=" + rsiTf + " <= " + str.tostring(rsiOversold))
alertcondition(finalShortSignal, title="Bullmania v7 Sell", message="Sell {{ticker}} {{interval}} | Profile={{activeProfile}} ATR={{atrPeriod}} Mult={{multiplier}} | RSI TF=" + rsiTf + " >= " + str.tostring(rsiOverbought))

View File

@@ -34,6 +34,7 @@ This repo contains multiple versions; v4 is the stable baseline and `v4+` adds o
- `Bullmania_Money_Line_v4_plus.pine` — v4-compatible but with optional filters and quality-of-life features (Pine v6).
- `Bullmania_Money_Line_v5.pine` — v1 + optional MACD confirmation gate and optional timeframe profiles (Single mode or auto profile by chart TF).
- `Bullmania_Money_Line_Strategy_v5.pine` — Strategy version of v5 for backtesting with entry/exit rules, optional SL/TP.
- `Bullmania_Money_Line_v7.pine` — v5 core + RSI gate using a selectable timeframe (default 15m oversold/overbought) with alerts.
## How it works (all versions)
- Money Line is derived from a mid-price `(high + low) / 2` and `ATR(atrPeriod)` scaled by `multiplier`.
@@ -178,6 +179,7 @@ For automated testing of different settings, use `Bullmania_Money_Line_Strategy_
- Note: Indicators show signals but don't backtest; strategies do.
## Changelog
- v7 — v5 core plus RSI oversold/overbought gate from a selectable timeframe (default 15m). Includes alerts; works with MACD gate and entry filters.
- v5 — v1 + optional MACD gate (buy dot requires MACD line > signal; sell dot requires MACD line < signal). Adds optional timeframe profiles: choose "Single" or "Profiles by timeframe". Profiles buckets: Minutes, Hours, Daily, Weekly/Monthly with independent ATR Period and Multiplier. Defaults keep v1 behavior.
- v4+ — Pine v6 variant with optional ADX/MTF/session/cooldown, calc source toggle, EMA trend filter, anti-chop (CHOP, retest, min body), gated markers, and per-timeframe profiles.
- v4.0.0 — Adds Flip confirmation bars and Flip buffer (×ATR). Defaults keep v1 behavior. Tag: `v4.0.0`.