fix: de-duplicate four indicators by correcting their definitions (#300)
* fix(core): de-duplicate 3 indicators by correcting their definitions Behavioral audit found these computed identically to another indicator: - AverageDrawdown was the mean per-bar under-water fraction = PainIndex. Now the conventional average drawdown: mean of the maximum depths of the distinct drawdown episodes in the window. - IntradayIntensity was a cumulative line = the A/D Line (Adl); its normalized form is the Chaikin Money Flow (Cmf). Now the raw per-bar Bostian intensity volume*(2c-h-l)/(h-l), distinct from both. - AwesomeOscillatorHistogram was AO - SMA(AO, n) = AcceleratorOscillator. Now the AO momentum AO[t] - AO[t-lookback] (the histogram delta); the 3rd parameter is reinterpreted from sma_period to lookback (default 1). Constructor signatures are unchanged, so the bindings keep their API. Core unit tests rewritten with the new reference values; workspace tests + clippy green. Binding value-tests and deep-dive docs are updated separately. * fix(core): redefine AdOscillator as the A/D Oscillator (was a Wad duplicate) AdOscillator computed the cumulative volume-free Williams A/D line, identical to the Wad indicator. Redefine it as the Williams A/D *Oscillator*: the same line minus its 13-bar SMA, so it oscillates around zero (mean-reverting) while Wad stays the drifting cumulative line for divergence analysis. The canonical name AdOscillator is now accurate; the trait name() becomes "ADOSC". Constructor stays no-arg (internal 13-bar signal). Unit tests rewritten and cross-checked against Wad - SMA(Wad, 13). The native bindings' "WilliamsAD" alias is renamed to "ADOSC" separately. * fix(bindings): rename WilliamsAD alias to ADOSC and update value tests Follows the core de-duplication: the native bindings exposed the Williams A/D line as 'WilliamsAD', which is now the A/D Oscillator. Rename the Python / Node.js / WASM alias to 'ADOSC' (regenerated node index.js / index.d.ts) and update the binding value-tests for the four redefined indicators (AverageDrawdown episode mean, AwesomeOscillatorHistogram momentum warmup, the Wad-line reference test now uses ta.Wad()). Python suite and node suite both pass (pytest all green, node 584/584). * docs: record indicator de-duplication in README and CHANGELOG README volume family: 'Williams A/D' -> 'Williams A/D Oscillator', 'Intraday Intensity Index' -> 'Intraday Intensity'. CHANGELOG [Unreleased] documents the four redefinitions and the native WilliamsAD -> ADOSC rename as breaking. * test(core): cover Default impl and drop dead match arm Codecov flagged AdOscillator::default() (never exercised) and the unreachable _ => panic!() arm in the AwesomeOscillatorHistogram test. Exercise Default in the accessors test and rewrite the histogram check as an if-let, removing the dead arm.
This commit is contained in:
@@ -259,7 +259,7 @@ const candleScalar = {
|
||||
VolumeOscillator: { make: () => new wickra.VolumeOscillator(14, 28), step: (ind, i) => ind.update(volume[i]), batch: (ind) => ind.batch(volume) },
|
||||
NVI: { make: () => new wickra.NVI(), step: (ind, i) => ind.update(close[i], volume[i]), batch: (ind) => ind.batch(close, volume) },
|
||||
PVI: { make: () => new wickra.PVI(), step: (ind, i) => ind.update(close[i], volume[i]), batch: (ind) => ind.batch(close, volume) },
|
||||
WilliamsAD: { make: () => new wickra.WilliamsAD(), step: (ind, i) => ind.update(high[i], low[i], close[i]), batch: (ind) => ind.batch(high, low, close) },
|
||||
ADOSC: { make: () => new wickra.ADOSC(), step: (ind, i) => ind.update(high[i], low[i], close[i]), batch: (ind) => ind.batch(high, low, close) },
|
||||
AnchoredVWAP: { make: () => new wickra.AnchoredVWAP(), step: (ind, i) => ind.update(high[i], low[i], close[i], volume[i]), batch: (ind) => ind.batch(high, low, close, volume) },
|
||||
DemandIndex: { make: () => new wickra.DemandIndex(10), step: (ind, i) => ind.update(high[i], low[i], close[i], volume[i]), batch: (ind) => ind.batch(high, low, close, volume) },
|
||||
TSV: { make: () => new wickra.TSV(18), step: (ind, i) => ind.update(close[i], volume[i]), batch: (ind) => ind.batch(close, volume) },
|
||||
@@ -1009,8 +1009,8 @@ test('AwesomeOscillatorHistogram on a flat median converges to zero', () => {
|
||||
Array(n).fill(11),
|
||||
Array(n).fill(9),
|
||||
);
|
||||
// warmup = 5 + 3 - 1 = 7.
|
||||
for (let i = 6; i < n; i++) assert.ok(Math.abs(out[i]) < 1e-12);
|
||||
// AO momentum; warmup = slow + lookback = 5 + 3 = 8.
|
||||
for (let i = 7; i < n; i++) assert.ok(Math.abs(out[i]) < 1e-12);
|
||||
});
|
||||
|
||||
test('STC on a flat series stays at zero', () => {
|
||||
|
||||
Vendored
+2
-2
@@ -2505,8 +2505,8 @@ export declare class KVO {
|
||||
isReady(): boolean
|
||||
warmupPeriod(): number
|
||||
}
|
||||
export type AdOscillatorNode = WilliamsAD
|
||||
export declare class WilliamsAD {
|
||||
export type AdOscillatorNode = ADOSC
|
||||
export declare class ADOSC {
|
||||
constructor()
|
||||
update(high: number, low: number, close: number): number | null
|
||||
batch(high: Array<number>, low: Array<number>, close: Array<number>): Array<number>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -5926,7 +5926,7 @@ impl KvoNode {
|
||||
|
||||
// ============================== Williams A/D ==============================
|
||||
|
||||
#[napi(js_name = "WilliamsAD")]
|
||||
#[napi(js_name = "ADOSC")]
|
||||
pub struct AdOscillatorNode {
|
||||
inner: wc::AdOscillator,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user