Signal#
Signal generation from spread residuals.
Direction#
Signal#
- class spreadpy.signal.signal.Signal(direction: Direction, zscore: float, timestamp: Timestamp, prob: float = nan, is_entry: bool = False)[source]#
Output of a SignalGenerator at a single bar.
- Parameters:
direction (Direction) – Desired position direction (LONG, SHORT, or FLAT).
zscore (float) – Z-score of the spread at signal time, used for position sizing.
timestamp (pd.Timestamp) – Bar timestamp.
prob (float) – Conditional mean-reversion probability from a copula signal, or
nanfor z-score signals.is_entry (bool) – True for new position entries; False for holds or exits.
SignalGenerator#
Abstract base class for all signal generators.
- class spreadpy.signal.signal.SignalGenerator[source]#
Abstract base class for signal generators.
Enforces the fit / generate discipline required for walk-forward backtesting:
fit()is called on in-sample data to calibrate any parameters, thengenerate()is called on out-of-sample data to produce signals without lookahead.- abstractmethod fit(spread: SpreadSeries) SignalGenerator[source]#
Calibrate parameters on in-sample spread data.
Must be called before
generate(). Implementations should compute any statistics (thresholds, copula parameters, etc.) fromspreadand store them as instance attributes.- Parameters:
spread (SpreadSeries) – In-sample spread series used for fitting.
- Returns:
self(for method chaining).- Return type:
- abstractmethod generate(spread: SpreadSeries) Series[source]#
Generate a
Signalfor each bar ofspread.Should be called after
fit().spreadmay be the same in-sample series or a disjoint out-of-sample window; in either case no lookahead is permitted — signal at bar t may only depend on observations up to and including t.- Parameters:
spread (SpreadSeries) – Spread series to generate signals for.
- Returns:
Series of
Signalobjects indexed byspread.index.- Return type:
pd.Series
ZScoreSignal#
- class spreadpy.signal.zScoreSignal.ZScoreSignal(window: int = 60, entry_threshold: float = 1.0, revert_threshold: float = 0.0)[source]#
Classic z-score entry / exit signal generator.
At each bar, computes a rolling z-score of the spread residuals:
\[z_t = \frac{s_t - \hat{\mu}_t}{\hat{\sigma}_t}\]where \(\hat{\mu}_t\) and \(\hat{\sigma}_t\) are the rolling mean and standard deviation over the last
windowbars (no lookahead).Entry / exit rules:
LONG if z_t < -entry_threshold SHORT if z_t > +entry_threshold FLAT if LONG and z_t > -revert_threshold (z reverted back up) FLAT if SHORT and z_t < +revert_threshold (z reverted back down)
Setting
revert_threshold=0exits at the mean crossing (\(z\) crosses 0). Setting it to a positive value exits before the mean is fully reached.- Parameters:
window (int) – Number of bars for the rolling z-score computation.
entry_threshold (float) – \(|z|\) level above which a position is opened.
revert_threshold (float) – \(z\) level at which mean reversion is considered complete and the position is closed. Must be \(\leq\)
entry_threshold. Use 0.0 to exit at the mean (default).
- fit(spread: SpreadSeries) ZScoreSignal[source]#
Compute in-sample mean and standard deviation of the spread residuals.
These statistics are stored but not used by
generate(), which relies on the rolling estimators instead. Callingfitis required by theSignalGeneratorinterface.- Parameters:
spread (SpreadSeries) – In-sample spread series.
- Returns:
self.- Return type:
- generate(spread: SpreadSeries) Series[source]#
Compute the rolling z-score and map each bar to a
Signal.At each bar \(t\) the z-score is:
\[z_t = \frac{s_t - \hat{\mu}_{t,w}}{\hat{\sigma}_{t,w}}\]where \(\hat{\mu}_{t,w}\) and \(\hat{\sigma}_{t,w}\) are the rolling mean and standard deviation over the previous
windowbars (no lookahead). Bars with fewer thanwindowpredecessors yieldDirection.FLATwithzscore=NaN.- Parameters:
spread (SpreadSeries) – Spread series to generate signals for (may be out-of-sample).
- Returns:
Series of
Signalobjects indexed byspread.index.- Return type:
pd.Series
RollingADFFilter#
- class spreadpy.signal.rollingADFFilter.RollingADFFilter(base: SignalGenerator, adf_window: int = 120, p_threshold: float = 0.05, min_confirm: int = 1)[source]#
Wraps any
SignalGeneratorand suppresses new entries when the spread fails a rolling ADF stationarity test.At each bar t, the ADF test is evaluated on the preceding
adf_windowbars of the spread residuals. A new position is only opened if the p-value is belowp_threshold(i.e. the spread is stationary).Exits and holds are always passed through unchanged. If an entry is blocked and the spread becomes stationary while still in the entry zone, the position opens at the first bar where the confirmation condition is met — with
is_entry=Trueso sizers compute a fresh size.To reduce false signals from a noisy p-value, set
min_confirm > 1: entry is only allowed aftermin_confirmconsecutive bars where the p-value stayed belowp_threshold.Usage:
signal_gen = RollingADFFilter( base=ZScoreSignal(window=60, entry_threshold=1.5), adf_window=120, p_threshold=0.05, min_confirm=3, )
- Parameters:
base (SignalGenerator) – Underlying signal generator to wrap.
adf_window (int) – Number of bars for the rolling ADF window.
p_threshold (float) – Maximum p-value to allow an entry (default 0.05).
min_confirm (int) – Number of consecutive bars the p-value must stay above
p_thresholdto block an entry (default 1). With the default of 1, any bar above the threshold blocks entry. Increase to require sustained non-stationarity before blocking — a single noisy bar above the threshold will not prevent entry.
- fit(spread: SpreadSeries) RollingADFFilter[source]#
Calibrate parameters on in-sample spread data.
Must be called before
generate(). Implementations should compute any statistics (thresholds, copula parameters, etc.) fromspreadand store them as instance attributes.- Parameters:
spread (SpreadSeries) – In-sample spread series used for fitting.
- Returns:
self(for method chaining).- Return type:
- generate(spread: SpreadSeries) Series[source]#
Generate a
Signalfor each bar ofspread.Should be called after
fit().spreadmay be the same in-sample series or a disjoint out-of-sample window; in either case no lookahead is permitted — signal at bar t may only depend on observations up to and including t.- Parameters:
spread (SpreadSeries) – Spread series to generate signals for.
- Returns:
Series of
Signalobjects indexed byspread.index.- Return type:
pd.Series