UNPKG

@railpath/finance-toolkit

Version:

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

92 lines (91 loc) 2.48 kB
"use strict"; /** * Matrix Utility Functions for Machine Learning * * Provides numerically stable operations for ML algorithms */ Object.defineProperty(exports, "__esModule", { value: true }); exports.logSumExp = logSumExp; exports.normalizeRows = normalizeRows; exports.normalizeArray = normalizeArray; exports.addNoise = addNoise; /** * Log-Sum-Exp trick for numerical stability * * Computes log(sum(exp(logValues))) in a numerically stable way * * @param logValues - Array of log values * @returns log(sum(exp(logValues))) * * @example * ```typescript * const result = logSumExp([-1000, -999, -1001]); // ≈ -998.59 * ``` */ function logSumExp(logValues) { if (logValues.length === 0) { return -Infinity; } const maxLogValue = Math.max(...logValues); if (!isFinite(maxLogValue)) { return maxLogValue; } let sum = 0; for (const logValue of logValues) { sum += Math.exp(logValue - maxLogValue); } return maxLogValue + Math.log(sum); } /** * Normalize rows of a matrix (each row sums to 1) * * @param matrix - Input matrix * @returns Matrix with normalized rows * * @example * ```typescript * const matrix = [[1, 2, 3], [4, 5, 6]]; * const normalized = normalizeRows(matrix); * // [[0.167, 0.333, 0.5], [0.267, 0.333, 0.4]] * ``` */ function normalizeRows(matrix) { return matrix.map(row => { const sum = row.reduce((acc, val) => acc + val, 0); if (sum === 0 || !isFinite(sum)) { // If sum is 0, return uniform distribution (maximum entropy) return row.map(() => 1 / row.length); } return row.map(val => val / sum); }); } /** * Normalize an array (values sum to 1) * * @param arr - Input array * @returns Normalized array * * @example * ```typescript * const arr = [1, 2, 3, 4]; * const normalized = normalizeArray(arr); // [0.1, 0.2, 0.3, 0.4] * ``` */ function normalizeArray(arr) { const sum = arr.reduce((acc, val) => acc + val, 0); if (sum === 0) { // If sum is 0, return uniform distribution return arr.map(() => 1 / arr.length); } return arr.map(val => val / sum); } /** * Add small noise to break symmetry * * @param matrix - Input matrix * @param noiseLevel - Level of noise (default: 1e-4) * @returns Matrix with added noise */ function addNoise(matrix, noiseLevel = 1e-4) { return matrix.map(row => row.map(val => val + (Math.random() - 0.5) * noiseLevel)); }