Files
Tradingview/Bullmania_Money_Line_v2.pine

116 lines
4.5 KiB
Plaintext

//@version=5
strategy("Bullmania Money Line v2", overlay=true,
initial_capital=10000, currency=currency.USD, pyramiding=0,
commission_type=strategy.commission.percent, commission_value=0.1, // 0.1% commission
slippage=1, process_orders_on_close=true)
// Inputs
atrPeriod = input.int(10, "ATR Period", minval=1)
multiplier = input.float(3.0, "Multiplier", minval=0.1, step=0.1)
// Backtest toggles
enableLongs = input.bool(true, "Enable Longs")
enableShorts = input.bool(true, "Enable Shorts")
// Date range filter
startYear = input.int(2020, "Start Year", minval=1970, maxval=2100)
startMonth = input.int(1, "Start Month", minval=1, maxval=12)
startDay = input.int(1, "Start Day", minval=1, maxval=31)
endYear = input.int(2100, "End Year", minval=1970, maxval=2100)
endMonth = input.int(12, "End Month", minval=1, maxval=12)
endDay = input.int(31, "End Day", minval=1, maxval=31)
startTime = timestamp(startYear, startMonth, startDay, 0, 0)
endTime = timestamp(endYear, endMonth, endDay, 23, 59)
inDateRange = time >= startTime and time <= endTime
// Position sizing
riskMode = input.string("Percent of equity", "Sizing Mode", options=["Percent of equity", "Fixed contracts"])
posSizePct = input.float(10.0, "Position Size % of Equity", minval=0.0, step=0.1)
fixedQty = input.float(1.0, "Fixed Contracts/Qty", minval=0.0, step=0.1)
allowFractional = input.bool(true, "Allow fractional quantity")
usePct = riskMode == "Percent of equity"
calcQty(price) =>
qtyCalc = usePct ? (strategy.equity * (posSizePct / 100.0)) / price : fixedQty
allowFractional ? qtyCalc : math.floor(qtyCalc)
// Stops/Targets
useMoneyLineStop = input.bool(true, "Use Money Line as Stop")
tpAtrMult = input.float(0.0, "Take Profit ATR Multiplier (0 = Off)", minval=0.0, step=0.1)
// Core calculations (same as 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)
// Signals
longSignal = trend == 1 and trend[1] == -1
shortSignal = trend == -1 and trend[1] == 1
// Plot buy/sell signals
plotshape(longSignal, title="Buy Signal", location=location.belowbar, color=color.green, style=shape.circle, size=size.small)
plotshape(shortSignal, 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))
// Alerts
alertcondition(longSignal, title="Bullmania Long", message="Bullmania Money Line: Long signal")
alertcondition(shortSignal, title="Bullmania Short", message="Bullmania Money Line: Short signal")
// Backtest entries
canLong = enableLongs and inDateRange
canShort = enableShorts and inDateRange
// Issue entries on signal
if longSignal and canLong
strategy.entry(id="Long", direction=strategy.long, qty = calcQty(close))
if shortSignal and canShort
strategy.entry(id="Short", direction=strategy.short, qty = calcQty(close))
// Dynamic stops/targets via strategy.exit
longStop = useMoneyLineStop and trend == 1 ? supertrend : na
shortStop = useMoneyLineStop and trend == -1 ? supertrend : na
// Optional ATR-based take profits referenced from average fill price
longTP = tpAtrMult > 0 and strategy.position_size > 0 ? strategy.position_avg_price + atr * tpAtrMult : na
shortTP = tpAtrMult > 0 and strategy.position_size < 0 ? strategy.position_avg_price - atr * tpAtrMult : na
// Update exits every bar (works even when not in position)
strategy.exit("XL", from_entry="Long", stop=longStop, limit=longTP)
strategy.exit("XS", from_entry="Short", stop=shortStop, limit=shortTP)