UNPKG

@railpath/finance-toolkit

Version:

Production-ready finance library for portfolio construction, risk analytics, quantitative metrics, and ML-based regime detection

123 lines (122 loc) 4.47 kB
"use strict"; /** * Validation Utility Functions for Machine Learning * * Provides input validation helpers for ML algorithms */ Object.defineProperty(exports, "__esModule", { value: true }); exports.validatePriceArray = validatePriceArray; exports.validateFeatureMatrix = validateFeatureMatrix; exports.validateHMMParameters = validateHMMParameters; exports.validateNumStates = validateNumStates; /** * Validate price array * * @param prices - Array of prices * @throws Error if validation fails */ function validatePriceArray(prices) { if (!Array.isArray(prices)) { throw new Error('Prices must be an array'); } if (prices.length < 2) { throw new Error('At least 2 prices required'); } if (!prices.every(p => typeof p === 'number' && isFinite(p))) { throw new Error('All prices must be finite numbers'); } if (!prices.every(p => p > 0)) { throw new Error('All prices must be positive'); } } /** * Validate feature matrix * * @param features - T x D matrix of features * @throws Error if validation fails */ function validateFeatureMatrix(features) { if (!Array.isArray(features)) { throw new Error('Features must be an array'); } if (features.length === 0) { throw new Error('Features array cannot be empty'); } const numFeatures = features[0].length; if (numFeatures === 0) { throw new Error('Each observation must have at least one feature'); } for (let t = 0; t < features.length; t++) { if (!Array.isArray(features[t])) { throw new Error(`Observation at index ${t} is not an array`); } if (features[t].length !== numFeatures) { throw new Error(`All observations must have the same number of features. Expected ${numFeatures}, got ${features[t].length} at index ${t}`); } if (!features[t].every(f => typeof f === 'number' && isFinite(f))) { throw new Error(`All features must be finite numbers at observation ${t}`); } } } /** * Validate HMM parameters * * @param model - HMM model to validate * @throws Error if validation fails */ function validateHMMParameters(model) { const { numStates, transitionMatrix, emissionParams, initialProbs } = model; // Validate dimensions if (transitionMatrix.length !== numStates) { throw new Error(`Transition matrix must have ${numStates} rows`); } if (!transitionMatrix.every(row => row.length === numStates)) { throw new Error(`All rows in transition matrix must have ${numStates} columns`); } if (emissionParams.length !== numStates) { throw new Error(`Must have ${numStates} emission parameter sets`); } if (initialProbs.length !== numStates) { throw new Error(`Initial probabilities must have ${numStates} elements`); } // Validate probability constraints const validateProbabilities = (probs, name) => { if (!probs.every(p => p >= 0 && p <= 1)) { throw new Error(`${name} must be between 0 and 1`); } const sum = probs.reduce((acc, p) => acc + p, 0); if (Math.abs(sum - 1) > 1e-6) { throw new Error(`${name} must sum to 1 (sum = ${sum})`); } }; // Validate transition matrix rows sum to 1 transitionMatrix.forEach((row, i) => { validateProbabilities(row, `Transition matrix row ${i}`); }); // Validate initial probabilities sum to 1 validateProbabilities(initialProbs, 'Initial probabilities'); // Validate emission parameters emissionParams.forEach((params, i) => { if (params.means.length !== params.variances.length) { throw new Error(`Emission params ${i}: means and variances must have same length`); } if (!params.variances.every(v => v > 0)) { throw new Error(`Emission params ${i}: all variances must be positive`); } }); } /** * Validate number of states * * @param numStates - Number of states * @param observations - Observation matrix * @throws Error if validation fails */ function validateNumStates(numStates, observations) { if (!Number.isInteger(numStates) || numStates < 2) { throw new Error('Number of states must be an integer >= 2'); } if (numStates > observations.length) { throw new Error(`Number of states (${numStates}) cannot exceed number of observations (${observations.length})`); } }