//@version=6
// SPDX-License-Identifier: Apache-2.0
// Copyright 2026 PineForge
// PineForge Owned Strategy: Ledger Outcome Throttle
// The most recent realized outcome selects the next fixed order quantity.
strategy("PineForge — Ledger Outcome Throttle", overlay=true,
initial_capital=100000,
default_qty_type=strategy.fixed, default_qty_value=2,
pyramiding=0, commission_type=strategy.commission.percent,
commission_value=0.05, slippage=1,
margin_long=100, margin_short=100,
process_orders_on_close=false, calc_on_order_fills=false)
fastLength = input.int(17, "Fast EMA Length", minval=2, group="Signal")
slowLength = input.int(49, "Slow EMA Length", minval=5, group="Signal")
fullQuantity = input.float(2.0, "Full Quantity", minval=0.1, step=0.1, group="Sizing")
recoveryQuantity = input.float(1.0, "Recovery Quantity", minval=0.1, step=0.1, group="Sizing")
atrLength = input.int(16, "ATR Length", minval=2, group="Risk")
maximumAtrLoss = input.float(2.3, "Maximum ATR Loss", minval=0.5, step=0.1, group="Risk")
fastLine = ta.ema(close, fastLength)
slowLine = ta.ema(close, slowLength)
atrValue = ta.atr(atrLength)
float nextQuantity = fullQuantity
if strategy.closedtrades > 0
lastClosedIndex = strategy.closedtrades - 1
lastRealizedProfit = strategy.closedtrades.profit(lastClosedIndex)
nextQuantity := lastRealizedProfit < 0 ? recoveryQuantity : fullQuantity
enterLong = ta.crossover(fastLine, slowLine)
trendEnded = ta.crossunder(fastLine, slowLine)
riskExceeded = strategy.position_size > 0 and close < strategy.position_avg_price - atrValue * maximumAtrLoss
if strategy.position_size == 0 and enterLong
strategy.entry("Ledger Throttle Long", strategy.long, qty=nextQuantity)
else if strategy.position_size > 0 and (trendEnded or riskExceeded)
strategy.close("Ledger Throttle Long", comment=riskExceeded ? "ATR risk" : "Trend ended")
plot(fastLine, "Fast EMA", color=color.blue)
plot(slowLine, "Slow EMA", color=color.orange)
plot(nextQuantity, "Next Quantity", color=color.purple, display=display.data_window)