DonchianLow — Donchian Low
The lowest close of the last N bars — the lower rail of a close-based Donchian channel, and the classic trailing-exit level.
DonchianLow is the identifier a strategy writes; Donchian Low is the label the chart’s indicator picker shows. Single value — .value is the only accessor.
Signature
DonchianLow(period, on=<source>)| Argument | Type | Required | Notes |
|---|---|---|---|
period |
int Param or literal | Yes | Lookback window. Default 20, bounds 2–200. |
on= |
symbol, OHLCV field, or indicator | No | Source. Defaults to the trade symbol’s close. |
Formula
$$ \text{DonchianLow}t = \min(\text{close}{t-N+1}, \dots, \text{close}_t) $$
The window includes the current bar, so self.trade.close <= low.value is true exactly on the bar that sets a new N-bar closing low. For a break of the level as it stood before this bar, read low.value_at(1).
Warmup
period bars — that is when the buffer is full and execute() starts.
The value has no dead zone: both branches of the seeded source return min(buffer), so from the first bar the chart plots the minimum of however many closes have arrived. It can only fall as the window fills, which makes the leading edge of the plot look flatter than the finished line.
Reading the value
low.value # lowest close including this barlow.value_at(1) # the level as it stood before this barlow < 50Example
class ChannelStopTrend(Strategy): """Trend-follow above the average, exit on a channel break.""" entry_period = Param(20, min=2, max=200) exit_period = Param(10, min=2, max=200) trade = Symbol() sizing = FixedCapital()
def execute(self): channel_low = DonchianLow(self.exit_period, on=self.trade) sma = SMA(self.entry_period, on=self.trade) self.stop_loss(4.0)
channel_stop = channel_low.value_at(1)
if self.trade.close > sma.value and self.trade.is_flat: self.buy(self.trade, reason="Above the trend average")
if self.trade.close < channel_stop and self.trade.is_long: self.sell(self.trade, self.trade.position, reason=f"Channel stop {channel_stop:.2f}")Notes
- As a trailing exit this ratchets one way only while you are long: the level rises as old lows leave the window and never falls below the window minimum. That is the behaviour that makes it a stop rather than a signal.
- Use
value_at(1)for break tests — comparing the close to a window that already includes it makes the condition trivially true on every new low. - Close-based. A wick through the level does not register; only a close does. If you need intrabar protection, add
self.stop_loss(...)as well — the example above does both. - Also available:
DonchianHigh,DonchianMid, andPriceChannelWidthfor the same window’s width.