feat: cross-asset / pairwise indicators (5 new) (#109)
* feat(core): add PairwiseBeta cross-asset indicator
Rolling OLS slope of one asset's log-returns on another's. Unlike Beta,
which regresses the raw inputs it is fed, PairwiseBeta differences
consecutive prices into log-returns internally -- the conventional way to
measure cross-asset beta, where a beta on price levels would be dominated
by the shared trend.
Two-series Indicator<Input = (f64, f64)>, exposed in Rust, Python, Node
and WASM, with unit/known-value/streaming tests and a pair fuzz target.
* feat(core): add PairSpreadZScore cross-asset indicator
Standardised log-spread ln(a) - beta*ln(b) of a pair, where beta is a
rolling-OLS hedge ratio and the spread is z-scored over its own look-back.
The canonical mean-reversion / statistical-arbitrage entry signal, with
independent beta_period and z_period windows.
Two-series Indicator<Input = (f64, f64)>, exposed in Rust, Python, Node
and WASM, with sign/known-value/streaming tests and a pair fuzz target.
* feat(core): add LeadLagCrossCorrelation cross-asset indicator
Reports the integer offset k in [-max_lag, max_lag] that maximises
|corr(a[t], b[t+k])|, answering which of two assets leads the other and by
how many bars. A positive lag means a leads b. Fully causal: a's window is
held centred while b's window slides across the buffered history, so every
lag is evaluated only against data already seen.
Struct output { lag, correlation }, exposed in Rust, Python, Node and WASM
with lead-detection/streaming tests and a pair fuzz driver.
* feat(core): add Cointegration (Engle-Granger + ADF) indicator
Rolling pairs-trading screen: an OLS hedge ratio of a on b, the spread
(residual) a - (alpha + beta*b), and an augmented Dickey-Fuller t-statistic
on the spread with configurable lags. A strongly negative statistic flags a
mean-reverting, tradeable spread. Includes a small Gaussian-elimination
solver for the augmented regression.
Struct output { hedge_ratio, spread, adf_stat }, exposed in Rust, Python,
Node and WASM with stationarity/hedge-ratio/streaming tests and a pair fuzz
driver.
* feat(core): add RelativeStrengthAB cross-asset indicator
Comparative relative strength of two assets: the ratio line a/b together
with its moving average and its RSI, the classic asset-vs-asset /
asset-vs-index rotation screen. Composes the existing Sma and Rsi over the
ratio; a zero denominator or non-finite price is skipped.
Struct output { ratio, ratio_ma, ratio_rsi }, exposed in Rust, Python, Node
and WASM with flat/rising-ratio/streaming tests and a pair fuzz driver.
* test(cointegration): cover ADF guard branches
The ADF helper's short-series and degrees-of-freedom guards and the
zero-dispersion (perfect AR) path are unreachable through the public
Cointegration API (period >= 2*adf_lags + 4), so exercise them with direct
unit tests on adf_no_constant. The second linear solve cannot be singular
once the coefficient solve on the same matrix has succeeded, so it now uses
expect() instead of a dead error branch.
This commit is contained in:
Vendored
+100
@@ -5,6 +5,34 @@
|
||||
|
||||
/** Library version (matches the Rust crate version). */
|
||||
export declare function version(): string
|
||||
/** Lead/lag result: the offset that maximises correlation, and that correlation. */
|
||||
export interface LeadLagValue {
|
||||
/** Offset that maximises `|corr(a, b shifted)|`. Positive ⇒ `a` leads `b`. */
|
||||
lag: number
|
||||
/** Signed correlation at that lag, in `[-1, 1]`. */
|
||||
correlation: number
|
||||
}
|
||||
/** Cointegration result: hedge ratio, current spread, and the ADF statistic. */
|
||||
export interface CointegrationValue {
|
||||
/** Engle–Granger hedge ratio (OLS slope of `a` on `b`). */
|
||||
hedgeRatio: number
|
||||
/** Current spread (regression residual) `a - (alpha + beta*b)`. */
|
||||
spread: number
|
||||
/**
|
||||
* Augmented Dickey–Fuller statistic on the spread; more negative ⇒ more
|
||||
* strongly mean-reverting.
|
||||
*/
|
||||
adfStat: number
|
||||
}
|
||||
/** Relative-strength triple: the a/b ratio, its moving average, and its RSI. */
|
||||
export interface RelativeStrengthValue {
|
||||
/** Raw ratio `a / b`. */
|
||||
ratio: number
|
||||
/** Moving average of the ratio. */
|
||||
ratioMa: number
|
||||
/** RSI of the ratio. */
|
||||
ratioRsi: number
|
||||
}
|
||||
/** MACD triple: macd line, signal line, histogram. */
|
||||
export interface MacdValue {
|
||||
macd: number
|
||||
@@ -628,6 +656,19 @@ export declare class Beta {
|
||||
isReady(): boolean
|
||||
warmupPeriod(): number
|
||||
}
|
||||
export type PairwiseBetaNode = PairwiseBeta
|
||||
export declare class PairwiseBeta {
|
||||
constructor(period: number)
|
||||
update(x: number, y: number): number | null
|
||||
/**
|
||||
* Batch over two equally-sized arrays. Returns a length-`n` array
|
||||
* with `NaN` for warmup positions.
|
||||
*/
|
||||
batch(x: Array<number>, y: Array<number>): Array<number>
|
||||
reset(): void
|
||||
isReady(): boolean
|
||||
warmupPeriod(): number
|
||||
}
|
||||
export type SpearmanCorrelationNode = SpearmanCorrelation
|
||||
export declare class SpearmanCorrelation {
|
||||
constructor(period: number)
|
||||
@@ -641,6 +682,65 @@ export declare class SpearmanCorrelation {
|
||||
isReady(): boolean
|
||||
warmupPeriod(): number
|
||||
}
|
||||
export type PairSpreadZScoreNode = PairSpreadZScore
|
||||
/**
|
||||
* Pair spread z-score: two ctor params (`betaPeriod`, `zPeriod`), one `(a, b)`
|
||||
* price pair per update, a single z-score out.
|
||||
*/
|
||||
export declare class PairSpreadZScore {
|
||||
constructor(betaPeriod: number, zPeriod: number)
|
||||
update(a: number, b: number): number | null
|
||||
/**
|
||||
* Batch over two equally-sized arrays of prices. Returns a length-`n`
|
||||
* array with `NaN` for warmup positions.
|
||||
*/
|
||||
batch(a: Array<number>, b: Array<number>): Array<number>
|
||||
reset(): void
|
||||
isReady(): boolean
|
||||
warmupPeriod(): number
|
||||
}
|
||||
export type LeadLagCrossCorrelationNode = LeadLagCrossCorrelation
|
||||
export declare class LeadLagCrossCorrelation {
|
||||
constructor(window: number, maxLag: number)
|
||||
update(a: number, b: number): LeadLagValue | null
|
||||
/**
|
||||
* Batch over two equally-sized arrays. Returns a flat array of length
|
||||
* `2 * n`, interleaved per row as `[lag0, corr0, lag1, corr1, ...]`. Read
|
||||
* column `j` of row `i` as `result[i * 2 + j]`. Warmup rows are `NaN`.
|
||||
*/
|
||||
batch(a: Array<number>, b: Array<number>): Array<number>
|
||||
reset(): void
|
||||
isReady(): boolean
|
||||
warmupPeriod(): number
|
||||
}
|
||||
export type CointegrationNode = Cointegration
|
||||
export declare class Cointegration {
|
||||
constructor(period: number, adfLags: number)
|
||||
update(a: number, b: number): CointegrationValue | null
|
||||
/**
|
||||
* Batch over two equally-sized arrays. Returns a flat array of length
|
||||
* `3 * n`, interleaved per row as `[hedgeRatio0, spread0, adfStat0, ...]`.
|
||||
* Read column `j` of row `i` as `result[i * 3 + j]`. Warmup rows are `NaN`.
|
||||
*/
|
||||
batch(a: Array<number>, b: Array<number>): Array<number>
|
||||
reset(): void
|
||||
isReady(): boolean
|
||||
warmupPeriod(): number
|
||||
}
|
||||
export type RelativeStrengthAbNode = RelativeStrengthAB
|
||||
export declare class RelativeStrengthAB {
|
||||
constructor(maPeriod: number, rsiPeriod: number)
|
||||
update(a: number, b: number): RelativeStrengthValue | null
|
||||
/**
|
||||
* Batch over two equally-sized arrays. Returns a flat array of length
|
||||
* `3 * n`, interleaved per row as `[ratio0, ratioMa0, ratioRsi0, ...]`.
|
||||
* Read column `j` of row `i` as `result[i * 3 + j]`. Warmup rows are `NaN`.
|
||||
*/
|
||||
batch(a: Array<number>, b: Array<number>): Array<number>
|
||||
reset(): void
|
||||
isReady(): boolean
|
||||
warmupPeriod(): number
|
||||
}
|
||||
export type MacdNode = MACD
|
||||
export declare class MACD {
|
||||
constructor(fast: number, slow: number, signal: number)
|
||||
|
||||
Reference in New Issue
Block a user