Signals — Crossover Signals
תוכן זה אינו זמין עדיין בשפה שלך.
A fast simple moving average that also draws a triangle on the chart every time price crosses it. From a strategy you read the average; the triangles are a chart-side annotation.
Signals is the identifier a strategy writes; Crossover Signals is the label the chart’s indicator picker shows. Single value — .value is the only accessor.
Signature
Signals(period, on=<source>)| Argument | Type | Required | Notes |
|---|---|---|---|
period |
int Param or literal | Yes | Length of the signal moving average. Default 10, bounds 2–200. |
on= |
symbol, OHLCV field, or indicator | No | Source. Defaults to the trade symbol’s close. |
Formula
The value is a simple moving average of the source:
$$ \text{Signals}t = \frac{1}{N} \sum{i=0}^{N-1} \text{close}_{t-i} $$
On top of that, once the window is full, the indicator emits a per-bar marker:
| Condition | Marker |
|---|---|
| Close crosses from at-or-below the average to above it | Green triangle, below the bar |
| Close crosses from above the average to at-or-below it | Red triangle, above the bar |
Markers are chart-only
self.shape(...) emissions ride the chart’s wire format, not the indicator’s value. A strategy that reads signals.value gets the moving average and nothing else — there is no .marker accessor. To act on the same crossings in code, compare self.trade.close against signals.value, exactly as the example below does.
Warmup
period bars before the markers start firing.
The value has no dead zone — the average is computed with sum(buffer) / len(buffer) on every bar, so the leading bars plot a partial-window mean rather than a placeholder. Only the triangles are gated on the full window.
Reading the value
signals.value # the fast moving averagesignals.value_at(1)signals > 100signals.crossed_above(slow_ma)Example
class SignalLineFollower(Strategy): """Trade the same crossings the Signals triangles mark.""" period = Param(10, min=2, max=200) trade = Symbol() sizing = FixedCapital()
def execute(self): signal_ma = Signals(self.period, on=self.trade) self.stop_loss(2.5)
if self.trade.close > signal_ma.value and self.trade.is_flat: self.buy(self.trade, reason=f"Close above the signal line {signal_ma.value:.2f}")
if self.trade.close < signal_ma.value and self.trade.is_long: self.sell(self.trade, self.trade.position, reason="Close back below the signal line")Notes
- Numerically this is
SMA. Same window, same arithmetic, drawn on the price pane. The reason to chooseSignalsis the markers — if a chart reader needs to see where the crossings happened, this is the indicator that shows them. If nobody is looking at the chart,SMAsays the same thing more plainly. - The marker rule treats
close == averageas not above, so an exact touch does not fire a triangle and does not flip the internal state. - The triangles reflect the indicator’s own crossing rule, not your strategy’s entries. A strategy with extra filters will trade a subset of the marked bars — that mismatch is expected, not a bug.
- Because the leading bars use a partial window, the plotted line starts closer to price than the settled average would be.