24e723fa7d
* feat(rvi): add Relative Vigor Index
Dorsey's RVI = SMA(close - open, period) / SMA(high - low, period) over
a rolling window of period candles. Candle input, single parameter
period (default 10). Positive on average-bullish windows, negative on
average-bearish. Holds the previous value if the entire window has
zero range (denominator undefined).
Reference: Donald Dorsey, also pandas-ta rvi.
Touchpoints: rvi.rs + mod.rs + lib.rs re-export, PyRvi + __init__.py
+ test_new_indicators CANDLE_SCALAR + test_known_values reference,
RviNode (4-column OHLC batch) + index.d.ts/index.js + indicators.test
.js factory + reference, WasmRvi + make_candle_ohlc helper, candle-fuzz
target + criterion bench, README + CHANGELOG.
* feat(pgo): add Pretty Good Oscillator
Mark Johnson's PGO = (close - SMA(close, period)) / EMA(TR, period).
Counts roughly how many ATR-equivalents the close sits from its
period-bar mean. Candle input, single parameter period (default 14).
Johnson's heuristic uses +3/-3 crossings as entry signals.
Touchpoints: pgo.rs + mod.rs + lib.rs re-export, PyPgo + __init__.py
+ test_new_indicators CANDLE_SCALAR + test_known_values flat-close
reference, PgoNode (h/l/c) + index.d.ts/index.js + indicators.test.js
factory + reference, WasmPgo, candle-fuzz target + bench, README +
CHANGELOG.
* feat(kst): add Know Sure Thing (Pring)
Pring's long-horizon momentum oscillator: weighted sum of four
SMA-smoothed ROC series with fixed weights 1, 2, 3, 4, plus an SMA
signal line. Nine parameters (four ROC periods, four SMA periods, one
signal period); classic() applies Pring's recommended defaults.
Multi-output indicator emitting KstOutput { kst, signal }.
Touchpoints: kst.rs + mod.rs + lib.rs re-export, PyKst + __init__.py
+ test_new_indicators MULTI + test_known_values flat-input reference,
KstNode + KstValue + index.d.ts/index.js + indicators.test.js multi
factory + reference, WasmKst (manual JsValue object), scalar-fuzz
target (handled outside the f64-output drive helper), README +
CHANGELOG.
* feat(smi): add Stochastic Momentum Index (Blau)
Blau's doubly-EMA-smoothed bounded oscillator: measures the close's
displacement from the centre of the recent high-low range, scaled by
the smoothed range. Candle input, three parameters (period, d_period,
d2_period) with defaults 5 / 3 / 3.
Internally feeds both the displacement-EMA stack and the range-EMA
stack on every candle so they warm up in parallel (gating either
behind the other starves the second by one input).
Touchpoints: smi.rs + mod.rs + lib.rs re-export, PySmi + __init__.py
+ test_new_indicators CANDLE_SCALAR + test_known_values flat-input
reference, SmiNode + index.d.ts/index.js + indicators.test.js factory
+ reference, WasmSmi, candle-fuzz target, README + CHANGELOG.
* feat(laguerre-rsi): add Ehlers Laguerre RSI
Four-stage Laguerre polynomial filter wrapped in an RSI-style up/down
accumulator. Single gamma in [0, 1] (default 0.5) trades lag for
smoothness. State is seeded by setting all four L_i to the first input
so a constant series stays at the neutral 50. Output clamped to
[0, 100] to absorb floating-point rounding.
Reference: Ehlers, Time Warp - Without Space Travel, 2002.
Touchpoints: laguerre_rsi.rs + mod.rs + lib.rs re-export, PyLaguerreRsi
+ __init__.py + test_new_indicators SCALAR + test_known_values neutral
reference, LaguerreRsiNode + index.d.ts/index.js + indicators.test.js
factory + reference, WasmLaguerreRsi via scalar macro, scalar-fuzz
target, README + CHANGELOG.
* feat(connors-rsi): add Connors RSI (CRSI)
Larry Connors' 3-component aggregate: RSI(close), RSI(streak), and
PercentRank of the 1-period return over the last period_rank returns.
Each component is bounded in [0, 100] so the aggregate is too.
Three parameters (period_rsi, period_streak, period_rank) with
defaults 3 / 2 / 100. Streak tracks consecutive up/down runs (resets
to 0 on unchanged close).
Touchpoints: connors_rsi.rs + mod.rs + lib.rs re-export, PyConnorsRsi
+ __init__.py + test_new_indicators SCALAR + test_known_values bounded
reference, ConnorsRsiNode + index.d.ts/index.js + indicators.test.js
factory + reference, WasmConnorsRsi via scalar macro, scalar-fuzz
target, README + CHANGELOG.
* feat(inertia): add Dorsey Inertia (RVI + LinReg)
Donald Dorsey's Inertia — a LinearRegression smoothing of the RVI
series. Endpoint of an n-bar least-squares fit of RVI is the indicator
reading. Preserves trend direction while damping the ratio. Candle
input, two parameters (rvi_period, linreg_period) with defaults 14 / 20.
Touchpoints: inertia.rs + mod.rs + lib.rs re-export, PyInertia +
__init__.py + test_new_indicators CANDLE_SCALAR + test_known_values
constant reference, InertiaNode (4-column OHLC batch) + index.d.ts /
index.js + indicators.test.js factory + reference, WasmInertia,
candle-fuzz target, README + CHANGELOG.
* test(kst): Move KST out of MULTI dict (it is scalar-input)
KST sits in the MULTI dict (candle-input, multi-output) but its
update() takes a single f64, not a candle tuple. The shared streaming
loop in test_multi_streaming_matches_batch fed the OHLCV tuple in,
which crashed with `TypeError: argument 'value': must be real number,
not tuple` on every Python matrix entry.
Split into a new MULTI_SCALAR_INPUT dict with its own test function
that feeds the close-price stream as floats. KST is currently the
only such indicator; structure is ready for future scalar-input
multi-output additions (e.g. some MACD-shaped indicators).
* test(coverage): Cover SMI zero-range and ConnorsRsi zero-prev cold paths
codecov/patch on PR 40 flagged two uncovered defensive branches:
- SMI returns self.current early when the smoothed range collapses to
zero (`r2 <= 0.0`) so the formula stays defined. Exercised by feeding
bars where high == low.
- ConnorsRsi skips the ROC ring-buffer update when the previous price
is exactly zero so the divide-by-zero in `(input - prev) / prev` is
impossible. Exercised by seeding the first bar at 0.0.
402 lines
13 KiB
JavaScript
402 lines
13 KiB
JavaScript
/* tslint:disable */
|
|
/* eslint-disable */
|
|
/* prettier-ignore */
|
|
|
|
/* auto-generated by NAPI-RS */
|
|
|
|
const { existsSync, readFileSync } = require('fs')
|
|
const { join } = require('path')
|
|
|
|
const { platform, arch } = process
|
|
|
|
let nativeBinding = null
|
|
let localFileExisted = false
|
|
let loadError = null
|
|
|
|
function isMusl() {
|
|
// For Node 10
|
|
if (!process.report || typeof process.report.getReport !== 'function') {
|
|
try {
|
|
const lddPath = require('child_process').execSync('which ldd').toString().trim()
|
|
return readFileSync(lddPath, 'utf8').includes('musl')
|
|
} catch (e) {
|
|
return true
|
|
}
|
|
} else {
|
|
const { glibcVersionRuntime } = process.report.getReport().header
|
|
return !glibcVersionRuntime
|
|
}
|
|
}
|
|
|
|
switch (platform) {
|
|
case 'android':
|
|
switch (arch) {
|
|
case 'arm64':
|
|
localFileExisted = existsSync(join(__dirname, 'wickra.android-arm64.node'))
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.android-arm64.node')
|
|
} else {
|
|
nativeBinding = require('wickra-android-arm64')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
break
|
|
case 'arm':
|
|
localFileExisted = existsSync(join(__dirname, 'wickra.android-arm-eabi.node'))
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.android-arm-eabi.node')
|
|
} else {
|
|
nativeBinding = require('wickra-android-arm-eabi')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
break
|
|
default:
|
|
throw new Error(`Unsupported architecture on Android ${arch}`)
|
|
}
|
|
break
|
|
case 'win32':
|
|
switch (arch) {
|
|
case 'x64':
|
|
localFileExisted = existsSync(
|
|
join(__dirname, 'wickra.win32-x64-msvc.node')
|
|
)
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.win32-x64-msvc.node')
|
|
} else {
|
|
nativeBinding = require('wickra-win32-x64-msvc')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
break
|
|
case 'ia32':
|
|
localFileExisted = existsSync(
|
|
join(__dirname, 'wickra.win32-ia32-msvc.node')
|
|
)
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.win32-ia32-msvc.node')
|
|
} else {
|
|
nativeBinding = require('wickra-win32-ia32-msvc')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
break
|
|
case 'arm64':
|
|
localFileExisted = existsSync(
|
|
join(__dirname, 'wickra.win32-arm64-msvc.node')
|
|
)
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.win32-arm64-msvc.node')
|
|
} else {
|
|
nativeBinding = require('wickra-win32-arm64-msvc')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
break
|
|
default:
|
|
throw new Error(`Unsupported architecture on Windows: ${arch}`)
|
|
}
|
|
break
|
|
case 'darwin':
|
|
localFileExisted = existsSync(join(__dirname, 'wickra.darwin-universal.node'))
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.darwin-universal.node')
|
|
} else {
|
|
nativeBinding = require('wickra-darwin-universal')
|
|
}
|
|
break
|
|
} catch {}
|
|
switch (arch) {
|
|
case 'x64':
|
|
localFileExisted = existsSync(join(__dirname, 'wickra.darwin-x64.node'))
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.darwin-x64.node')
|
|
} else {
|
|
nativeBinding = require('wickra-darwin-x64')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
break
|
|
case 'arm64':
|
|
localFileExisted = existsSync(
|
|
join(__dirname, 'wickra.darwin-arm64.node')
|
|
)
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.darwin-arm64.node')
|
|
} else {
|
|
nativeBinding = require('wickra-darwin-arm64')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
break
|
|
default:
|
|
throw new Error(`Unsupported architecture on macOS: ${arch}`)
|
|
}
|
|
break
|
|
case 'freebsd':
|
|
if (arch !== 'x64') {
|
|
throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
|
|
}
|
|
localFileExisted = existsSync(join(__dirname, 'wickra.freebsd-x64.node'))
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.freebsd-x64.node')
|
|
} else {
|
|
nativeBinding = require('wickra-freebsd-x64')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
break
|
|
case 'linux':
|
|
switch (arch) {
|
|
case 'x64':
|
|
if (isMusl()) {
|
|
localFileExisted = existsSync(
|
|
join(__dirname, 'wickra.linux-x64-musl.node')
|
|
)
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.linux-x64-musl.node')
|
|
} else {
|
|
nativeBinding = require('wickra-linux-x64-musl')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
} else {
|
|
localFileExisted = existsSync(
|
|
join(__dirname, 'wickra.linux-x64-gnu.node')
|
|
)
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.linux-x64-gnu.node')
|
|
} else {
|
|
nativeBinding = require('wickra-linux-x64-gnu')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
}
|
|
break
|
|
case 'arm64':
|
|
if (isMusl()) {
|
|
localFileExisted = existsSync(
|
|
join(__dirname, 'wickra.linux-arm64-musl.node')
|
|
)
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.linux-arm64-musl.node')
|
|
} else {
|
|
nativeBinding = require('wickra-linux-arm64-musl')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
} else {
|
|
localFileExisted = existsSync(
|
|
join(__dirname, 'wickra.linux-arm64-gnu.node')
|
|
)
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.linux-arm64-gnu.node')
|
|
} else {
|
|
nativeBinding = require('wickra-linux-arm64-gnu')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
}
|
|
break
|
|
case 'arm':
|
|
if (isMusl()) {
|
|
localFileExisted = existsSync(
|
|
join(__dirname, 'wickra.linux-arm-musleabihf.node')
|
|
)
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.linux-arm-musleabihf.node')
|
|
} else {
|
|
nativeBinding = require('wickra-linux-arm-musleabihf')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
} else {
|
|
localFileExisted = existsSync(
|
|
join(__dirname, 'wickra.linux-arm-gnueabihf.node')
|
|
)
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.linux-arm-gnueabihf.node')
|
|
} else {
|
|
nativeBinding = require('wickra-linux-arm-gnueabihf')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
}
|
|
break
|
|
case 'riscv64':
|
|
if (isMusl()) {
|
|
localFileExisted = existsSync(
|
|
join(__dirname, 'wickra.linux-riscv64-musl.node')
|
|
)
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.linux-riscv64-musl.node')
|
|
} else {
|
|
nativeBinding = require('wickra-linux-riscv64-musl')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
} else {
|
|
localFileExisted = existsSync(
|
|
join(__dirname, 'wickra.linux-riscv64-gnu.node')
|
|
)
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.linux-riscv64-gnu.node')
|
|
} else {
|
|
nativeBinding = require('wickra-linux-riscv64-gnu')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
}
|
|
break
|
|
case 's390x':
|
|
localFileExisted = existsSync(
|
|
join(__dirname, 'wickra.linux-s390x-gnu.node')
|
|
)
|
|
try {
|
|
if (localFileExisted) {
|
|
nativeBinding = require('./wickra.linux-s390x-gnu.node')
|
|
} else {
|
|
nativeBinding = require('wickra-linux-s390x-gnu')
|
|
}
|
|
} catch (e) {
|
|
loadError = e
|
|
}
|
|
break
|
|
default:
|
|
throw new Error(`Unsupported architecture on Linux: ${arch}`)
|
|
}
|
|
break
|
|
default:
|
|
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
|
|
}
|
|
|
|
if (!nativeBinding) {
|
|
if (loadError) {
|
|
throw loadError
|
|
}
|
|
throw new Error(`Failed to load native binding`)
|
|
}
|
|
|
|
const { version, SMA, EMA, WMA, RSI, DEMA, TEMA, HMA, ROC, TRIX, SMMA, TRIMA, ZLEMA, MOM, CMO, DPO, StdDev, UlcerIndex, VerticalHorizontalFilter, ZScore, MACD, BollingerBands, ATR, Stochastic, OBV, ADX, CCI, WilliamsR, MFI, PSAR, Keltner, Donchian, VWAP, RollingVWAP, AwesomeOscillator, Aroon, KAMA, RVI, PGO, KST, SMI, LaguerreRSI, ConnorsRSI, Inertia, ALMA, McGinleyDynamic, FRAMA, VIDYA, JMA, Alligator, EVWMA, T3, TSI, PMO, ADL, VolumePriceTrend, ChaikinMoneyFlow, ChaikinOscillator, ForceIndex, EaseOfMovement, SuperTrend, ChandelierExit, ChandeKrollStop, AtrTrailingStop, TypicalPrice, MedianPrice, WeightedClose, LinearRegression, LinRegSlope, AcceleratorOscillator, BalanceOfPower, ChoppinessIndex, TrueRange, ChaikinVolatility, LinRegAngle, BollingerBandwidth, PercentB, NATR, HistoricalVolatility, AroonOscillator, Vortex, MassIndex, StochRSI, UltimateOscillator, PPO, Coppock, VWMA } = nativeBinding
|
|
|
|
module.exports.version = version
|
|
module.exports.SMA = SMA
|
|
module.exports.EMA = EMA
|
|
module.exports.WMA = WMA
|
|
module.exports.RSI = RSI
|
|
module.exports.DEMA = DEMA
|
|
module.exports.TEMA = TEMA
|
|
module.exports.HMA = HMA
|
|
module.exports.ROC = ROC
|
|
module.exports.TRIX = TRIX
|
|
module.exports.SMMA = SMMA
|
|
module.exports.TRIMA = TRIMA
|
|
module.exports.ZLEMA = ZLEMA
|
|
module.exports.MOM = MOM
|
|
module.exports.CMO = CMO
|
|
module.exports.DPO = DPO
|
|
module.exports.StdDev = StdDev
|
|
module.exports.UlcerIndex = UlcerIndex
|
|
module.exports.VerticalHorizontalFilter = VerticalHorizontalFilter
|
|
module.exports.ZScore = ZScore
|
|
module.exports.MACD = MACD
|
|
module.exports.BollingerBands = BollingerBands
|
|
module.exports.ATR = ATR
|
|
module.exports.Stochastic = Stochastic
|
|
module.exports.OBV = OBV
|
|
module.exports.ADX = ADX
|
|
module.exports.CCI = CCI
|
|
module.exports.WilliamsR = WilliamsR
|
|
module.exports.MFI = MFI
|
|
module.exports.PSAR = PSAR
|
|
module.exports.Keltner = Keltner
|
|
module.exports.Donchian = Donchian
|
|
module.exports.VWAP = VWAP
|
|
module.exports.RollingVWAP = RollingVWAP
|
|
module.exports.AwesomeOscillator = AwesomeOscillator
|
|
module.exports.Aroon = Aroon
|
|
module.exports.KAMA = KAMA
|
|
module.exports.RVI = RVI
|
|
module.exports.PGO = PGO
|
|
module.exports.KST = KST
|
|
module.exports.SMI = SMI
|
|
module.exports.LaguerreRSI = LaguerreRSI
|
|
module.exports.ConnorsRSI = ConnorsRSI
|
|
module.exports.Inertia = Inertia
|
|
module.exports.ALMA = ALMA
|
|
module.exports.McGinleyDynamic = McGinleyDynamic
|
|
module.exports.FRAMA = FRAMA
|
|
module.exports.VIDYA = VIDYA
|
|
module.exports.JMA = JMA
|
|
module.exports.Alligator = Alligator
|
|
module.exports.EVWMA = EVWMA
|
|
module.exports.T3 = T3
|
|
module.exports.TSI = TSI
|
|
module.exports.PMO = PMO
|
|
module.exports.ADL = ADL
|
|
module.exports.VolumePriceTrend = VolumePriceTrend
|
|
module.exports.ChaikinMoneyFlow = ChaikinMoneyFlow
|
|
module.exports.ChaikinOscillator = ChaikinOscillator
|
|
module.exports.ForceIndex = ForceIndex
|
|
module.exports.EaseOfMovement = EaseOfMovement
|
|
module.exports.SuperTrend = SuperTrend
|
|
module.exports.ChandelierExit = ChandelierExit
|
|
module.exports.ChandeKrollStop = ChandeKrollStop
|
|
module.exports.AtrTrailingStop = AtrTrailingStop
|
|
module.exports.TypicalPrice = TypicalPrice
|
|
module.exports.MedianPrice = MedianPrice
|
|
module.exports.WeightedClose = WeightedClose
|
|
module.exports.LinearRegression = LinearRegression
|
|
module.exports.LinRegSlope = LinRegSlope
|
|
module.exports.AcceleratorOscillator = AcceleratorOscillator
|
|
module.exports.BalanceOfPower = BalanceOfPower
|
|
module.exports.ChoppinessIndex = ChoppinessIndex
|
|
module.exports.TrueRange = TrueRange
|
|
module.exports.ChaikinVolatility = ChaikinVolatility
|
|
module.exports.LinRegAngle = LinRegAngle
|
|
module.exports.BollingerBandwidth = BollingerBandwidth
|
|
module.exports.PercentB = PercentB
|
|
module.exports.NATR = NATR
|
|
module.exports.HistoricalVolatility = HistoricalVolatility
|
|
module.exports.AroonOscillator = AroonOscillator
|
|
module.exports.Vortex = Vortex
|
|
module.exports.MassIndex = MassIndex
|
|
module.exports.StochRSI = StochRSI
|
|
module.exports.UltimateOscillator = UltimateOscillator
|
|
module.exports.PPO = PPO
|
|
module.exports.Coppock = Coppock
|
|
module.exports.VWMA = VWMA
|