v5: add timeframe profiles with auto/override + default per-timeframe ATR/Multiplier; README updated
This commit is contained in:
115
Bullmania_Money_Line_v2.pine
Normal file
115
Bullmania_Money_Line_v2.pine
Normal file
@@ -0,0 +1,115 @@
|
||||
//@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)
|
||||
Reference in New Issue
Block a user