UNPKG

@c9up/technical-indicators-napi

Version:

A Rust-based indicator and Charts library compiled to napi.

137 lines (122 loc) 4.84 kB
import { test } from '@japa/runner' import pkg from '../../index.js' const { regimeLeverage } = pkg import { generateTestData } from './lib.mjs' /** * Generate a synthetic VIX-like series of `n` values around a realistic mean. * @param {number} n * @param {number} base - baseline VIX level (default 20) * @returns {number[]} */ function makeVix(n, base = 20) { const values = [] let seed = 31 for (let i = 0; i < n; i++) { seed = (seed * 1664525 + 1013904223) & 0xffffffff values.push(base + ((seed >>> 0) / 0xffffffff) * 15 - 7) } return values } test.group('RegimeLeverage', (group) => { const VALID_REGIMES = new Set([-1, 0, 1, 2, 3]) const VALID_LEVERAGES = new Set([0.0, 1.0, 2.0, 3.0]) test('all output arrays have the same length as input data', ({ assert }) => { const data = generateTestData(300) const result = regimeLeverage(data) assert.equal(result.oscillator.length, data.length) assert.equal(result.yzVolatility.length, data.length) assert.equal(result.volPercentile.length, data.length) assert.equal(result.regime.length, data.length) assert.equal(result.leverage.length, data.length) }) test('vixRatio array has the same length as input when vixValues provided', ({ assert }) => { const data = generateTestData(300) const vix = makeVix(300) const result = regimeLeverage(data, vix) assert.equal(result.vixRatio.length, data.length) }) test('regime values are only -1, 0, 1, 2, or 3 (ignoring NaN)', ({ assert }) => { const data = generateTestData(300) const result = regimeLeverage(data) for (let i = 0; i < result.regime.length; i++) { const r = result.regime[i] if (!isNaN(r)) { assert.isTrue(VALID_REGIMES.has(r), `regime[${i}] = ${r} is not in {-1, 0, 1, 2, 3}`) } } }) test('leverage values are NaN, 0.0, 1.0, 2.0, or 3.0', ({ assert }) => { const data = generateTestData(300) const result = regimeLeverage(data) for (let i = 0; i < result.leverage.length; i++) { const l = result.leverage[i] if (!isNaN(l)) { assert.isTrue(VALID_LEVERAGES.has(l), `leverage[${i}] = ${l} is not in {0.0, 1.0, 2.0, 3.0}`) } } }) test('yzVolatility non-NaN values are >= 0', ({ assert }) => { const data = generateTestData(300) const result = regimeLeverage(data) for (let i = 0; i < result.yzVolatility.length; i++) { const v = result.yzVolatility[i] if (!isNaN(v)) { assert.isTrue(v >= 0, `yzVolatility[${i}] = ${v} is negative`) } } }) test('result has all expected output fields', ({ assert }) => { const data = generateTestData(300) const result = regimeLeverage(data) assert.properties(result, [ 'oscillator', 'yzVolatility', 'volPercentile', 'regime', 'leverage', 'vixRatio', ]) }) test('volPercentile non-NaN values are between 0 and 100', ({ assert }) => { const data = generateTestData(300) const result = regimeLeverage(data) for (let i = 0; i < result.volPercentile.length; i++) { const p = result.volPercentile[i] if (!isNaN(p)) { assert.isTrue(p >= 0 && p <= 100, `volPercentile[${i}] = ${p} is outside [0, 100]`) } } }) test('custom yzWindow produces same-length output', ({ assert }) => { const data = generateTestData(300) const result = regimeLeverage(data, undefined, undefined, 30) assert.equal(result.yzVolatility.length, data.length) }) test('providing both vixValues and vix3mValues works correctly', ({ assert }) => { const data = generateTestData(300) const vix = makeVix(300, 20) const vix3m = makeVix(300, 22) const result = regimeLeverage(data, vix, vix3m) assert.equal(result.vixRatio.length, data.length) // vixRatio non-NaN values should be positive ratios for (let i = 0; i < result.vixRatio.length; i++) { const r = result.vixRatio[i] if (!isNaN(r)) { assert.isTrue(r > 0, `vixRatio[${i}] = ${r} should be positive`) } } }) test('not enough data throws', ({ assert }) => { const data = generateTestData(2) try { regimeLeverage(data) assert.fail('Expected an error to be thrown') } catch (error) { assert.isTrue(error instanceof Error) } }) })