//@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)