//@version=6
// SPDX-License-Identifier: Apache-2.0
// Copyright 2026 PineForge
// PineForge Owned Strategy: Zenith RCI WPR
// Rank correlation and Williams percent range jointly confirm momentum.
strategy("PineForge — Zenith RCI WPR", 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)
rciLength = input.int(17, "RCI Length", minval=3, group="Momentum")
wprLength = input.int(22, "Williams %R Length", minval=3, group="Momentum")
rciEntryLevel = input.float(18.0, "RCI Entry Level", minval=-80, maxval=80, step=1, group="Momentum")
wprEntryLevel = input.float(-58.0, "Williams %R Entry Level", minval=-95, maxval=-5, step=1, group="Momentum")
rciExitLevel = input.float(-14.0, "RCI Exit Level", minval=-80, maxval=80, step=1, group="Momentum")
atrLength = input.int(14, "ATR Length", minval=2, group="Risk")
maximumAtrLoss = input.float(2.0, "Maximum ATR Loss", minval=0.5, step=0.1, group="Risk")
rciValue = ta.rci(close, rciLength)
williamsValue = ta.wpr(wprLength)
atrValue = ta.atr(atrLength)
enterLong = ta.crossover(rciValue, rciEntryLevel) and williamsValue > wprEntryLevel
momentumEnded = rciValue < rciExitLevel or williamsValue < -82
riskExceeded = strategy.position_size > 0 and close < strategy.position_avg_price - atrValue * maximumAtrLoss
if strategy.position_size == 0 and enterLong
strategy.entry("Zenith Long", strategy.long)
else if strategy.position_size > 0 and (momentumEnded or riskExceeded)
strategy.close("Zenith Long", comment=riskExceeded ? "ATR risk" : "Momentum ended")
plot(rciValue, "RCI", color=color.blue, display=display.data_window)
plot(williamsValue, "Williams %R", color=color.purple, display=display.data_window)