Add strategy version v5 for backtesting; update README with backtesting guide
This commit is contained in:
139
Bullmania_Money_Line_Strategy_v5.pine
Normal file
139
Bullmania_Money_Line_Strategy_v5.pine
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
//@version=5
|
||||||
|
strategy("Bullmania Money Line Strategy v5", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// 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
|
||||||
|
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")
|
||||||
|
|
||||||
|
// Strategy settings
|
||||||
|
useStopLoss = input.bool(false, "Use Stop Loss", group="Strategy")
|
||||||
|
stopLossPct = input.float(1.0, "Stop Loss %", minval=0.1, step=0.1, group="Strategy")
|
||||||
|
useTakeProfit = input.bool(false, "Use Take Profit", group="Strategy")
|
||||||
|
takeProfitPct = input.float(2.0, "Take Profit %", minval=0.1, step=0.1, group="Strategy")
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// Resolve profile bucket
|
||||||
|
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
|
||||||
|
|
||||||
|
// Core Money Line logic (unchanged from v1)
|
||||||
|
atr = ta.atr(atrPeriod)
|
||||||
|
src = (high + low) / 2
|
||||||
|
|
||||||
|
up = src - (multiplier * atr)
|
||||||
|
dn = src + (multiplier * atr)
|
||||||
|
|
||||||
|
var float up1 = na
|
||||||
|
var float dn1 = na
|
||||||
|
|
||||||
|
up1 := nz(up1[1], up)
|
||||||
|
dn1 := nz(dn1[1], dn)
|
||||||
|
|
||||||
|
up1 := close[1] > up1 ? math.max(up, up1) : up
|
||||||
|
dn1 := close[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 := close < tsl ? -1 : 1
|
||||||
|
else
|
||||||
|
tsl := math.min(dn1, tsl)
|
||||||
|
trend := close > 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)
|
||||||
|
|
||||||
|
// MACD confirmation logic
|
||||||
|
[macdLine, macdSignal, macdHist] = ta.macd(macdSrc, macdFastLen, macdSlowLen, macdSigLen)
|
||||||
|
longOk = not useMacd or (macdLine > macdSignal)
|
||||||
|
shortOk = not useMacd or (macdLine < macdSignal)
|
||||||
|
|
||||||
|
// Strategy logic
|
||||||
|
buyFlip = trend == 1 and trend[1] == -1
|
||||||
|
sellFlip = trend == -1 and trend[1] == 1
|
||||||
|
|
||||||
|
if buyFlip and longOk
|
||||||
|
strategy.entry("Long", strategy.long)
|
||||||
|
|
||||||
|
if sellFlip and shortOk
|
||||||
|
strategy.entry("Short", strategy.short)
|
||||||
|
|
||||||
|
// Exits
|
||||||
|
if useStopLoss
|
||||||
|
strategy.exit("Exit Long SL", "Long", stop=close * (1 - stopLossPct / 100))
|
||||||
|
strategy.exit("Exit Short SL", "Short", stop=close * (1 + stopLossPct / 100))
|
||||||
|
|
||||||
|
if useTakeProfit
|
||||||
|
strategy.exit("Exit Long TP", "Long", limit=close * (1 + takeProfitPct / 100))
|
||||||
|
strategy.exit("Exit Short TP", "Short", limit=close * (1 - takeProfitPct / 100))
|
||||||
|
|
||||||
|
// Plot buy/sell signals
|
||||||
|
plotshape(buyFlip and longOk, title="Buy Signal", location=location.belowbar, color=color.green, style=shape.circle, size=size.small)
|
||||||
|
plotshape(sellFlip and shortOk, title="Sell Signal", location=location.abovebar, color=color.red, style=shape.circle, size=size.small)
|
||||||
|
|
||||||
|
// Fill area between price and Money Line
|
||||||
|
fill(plot(close, display=display.none), plot(upTrend, display=display.none), color=color.new(color.green, 90))
|
||||||
|
fill(plot(close, display=display.none), plot(downTrend, display=display.none), color=color.new(color.red, 90))
|
||||||
13
README.md
13
README.md
@@ -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_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_v5.pine` — v1 + optional MACD confirmation gate and optional timeframe profiles (Single mode or auto profile by chart TF).
|
||||||
- `Bullmania_Money_Line_v6.pine` — v5 + optional RSI confirmation gate (SuperTrend + RSI combo).
|
- `Bullmania_Money_Line_v6.pine` — v5 + optional RSI confirmation gate (SuperTrend + RSI combo).
|
||||||
|
- `Bullmania_Money_Line_Strategy_v5.pine` — Strategy version of v5 for backtesting with entry/exit rules, optional SL/TP.
|
||||||
|
|
||||||
## How it works (all versions)
|
## How it works (all versions)
|
||||||
- Money Line is derived from a mid-price `(high + low) / 2` and `ATR(atrPeriod)` scaled by `multiplier`.
|
- Money Line is derived from a mid-price `(high + low) / 2` and `ATR(atrPeriod)` scaled by `multiplier`.
|
||||||
@@ -170,12 +171,12 @@ ATR Period ≈ round(T / timeframe_minutes)
|
|||||||
|
|
||||||
Keep Multiplier roughly stable and fine-tune by small increments; HA candles allow slightly tighter settings than regular candles.
|
Keep Multiplier roughly stable and fine-tune by small increments; HA candles allow slightly tighter settings than regular candles.
|
||||||
|
|
||||||
## How to use in TradingView
|
## Backtesting with Strategy Version
|
||||||
1) Open TradingView → Pine Editor.
|
For automated testing of different settings, use `Bullmania_Money_Line_Strategy_v5.pine`:
|
||||||
2) New blank script.
|
- Load it as a strategy in TradingView.
|
||||||
3) Copy the contents of the desired `.pine` file and paste.
|
- In the Strategy Tester, set date ranges and use "Optimize" to sweep parameters like ATR Period, Multiplier, or MACD lengths.
|
||||||
4) Save and “Add to chart”.
|
- Review performance metrics (win rate, profit factor) to find optimal combos.
|
||||||
5) Open Inputs to adjust parameters.
|
- Note: Indicators (like v5/v6) show signals but don't backtest; strategies do.
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
- v6 — v5 + optional RSI confirmation gate (buy requires RSI < overbought; sell requires RSI > oversold). Combines with MACD if enabled.
|
- v6 — v5 + optional RSI confirmation gate (buy requires RSI < overbought; sell requires RSI > oversold). Combines with MACD if enabled.
|
||||||
|
|||||||
Reference in New Issue
Block a user