Skip to content
Open RaamTrade

ChandeKrollStop — Chande Kroll Stop

ATR-offset stop levels on both sides of the market, then smoothed: the raw long stop is the n-bar high minus a multiple of ATR, and the published level is the highest such raw stop over a second window. Wider and steadier than a plain ATR trail.

Signature

ChandeKrollStop(period, multiplier, stop_period, on=<source>)
Argument Type Required Notes
period int Param or literal Yes Window for the extremes and the ATR. Default 10, bounds 1–200.
multiplier float Param or literal Yes ATR offset. Default 3.0, bounds 0.1–10.0.
stop_period int Param or literal Yes Smoothing window over the raw stops. Default 9, bounds 1–200.
on= symbol No Source symbol. Defaults to the trade symbol. Reads high, low, close.

Formula

$$ \text{raw long} = \max(H, n) - m,\text{ATR}, \quad \text{raw short} = \min(L, n) + m,\text{ATR} $$ $$ \text{long} = \max(\text{raw long}, s), \quad \text{short} = \min(\text{raw short}, s) $$

Warmup

period + stop_period bars; the ATR seeds cumulatively over its first period bars.

Reading the value

cks.long
cks.short
self.trade.close < cks.long

Multi-value: cannot be chained onto or crossed.

Example

class CksTrail(Strategy):
"""Trail a long position on the Chande Kroll long stop."""
trade = Symbol()
sizing = FixedCapital()
def execute(self):
cks = ChandeKrollStop(10, 3.0, 9, on=self.trade)
sma = SMA(50, on=self.trade)
if self.trade.close > sma.value and self.trade.is_flat:
self.buy(self.trade, reason="Trend entry")
if self.trade.close < cks.long and self.trade.is_long:
self.sell(self.trade, self.trade.position, reason=f"Stop {cks.long:.2f}")

Notes

  • Tushar Chande and Stanley Kroll, The New Technical Trader (1994).
  • Proven by an assert-via-trade run on SPY daily (both levels matched a full strategy-side replication within 0.05 once the ATR converged; zero alarm trades).
  • The long stop can sit above the short stop when the channel is wider than 2 × multiplier × ATR — that is the construction, not an error.