PriceChannel — Price Channel
The n-bar high, the n-bar low and their midline, delivered as one indicator — the Donchian
channel when you want all three lines from a single declaration rather than three.
Signature
PriceChannel(period, on=<source>)| Argument | Type | Required | Notes |
|---|---|---|---|
period |
int Param or literal | Yes | Channel lookback. Default 20, bounds 1–400. |
on= |
symbol | No | Source symbol. Defaults to the trade symbol. Reads high and low. |
Formula
$$ \text{upper} = \max(H, n), \quad \text{lower} = \min(L, n), \quad \text{mid} = \frac{\text{upper} + \text{lower}}{2} $$
Warmup
period bars; during the lead-in the channel covers the bars seen so far.
Reading the value
pc.upperpc.midpc.lowerMulti-value: cannot be chained onto or crossed. Use DonchianHighTrue / DonchianLowTrue when
you need value_at(1) for breakout logic or want to smooth a single line.
Example
class MidlineRevert(Strategy): """Buy the lower channel, exit at the midline.""" trade = Symbol() sizing = FixedCapital()
def execute(self): pc = PriceChannel(20, on=self.trade) if self.trade.close <= pc.lower and self.trade.is_flat: self.buy(self.trade, reason="At the channel low") if self.trade.close >= pc.mid and self.trade.is_long: self.sell(self.trade, self.trade.position, reason="Midline reached")Notes
- Same computation as the true Donchian pair; shipped as one indicator for chart convenience.
- Proven by an assert-via-trade run on SPY daily (all three outputs matched a strategy-side rolling max/min to 1e-3 on every bar; zero alarm trades).
- The current bar is inside the channel, so
close >= pc.upperis a touch, never a breakout — breakouts compare against the previous bar’s channel.