67 lines
1.9 KiB
TypeScript
67 lines
1.9 KiB
TypeScript
/**
|
|
* Financial calculation utilities
|
|
*/
|
|
export const financialUtils = {
|
|
/**
|
|
* Calculate the Sharpe ratio
|
|
* @param returns Array of period returns
|
|
* @param riskFreeRate The risk-free rate (e.g. 0.02 for 2%)
|
|
*/
|
|
calculateSharpeRatio(returns: number[], riskFreeRate: number = 0.02): number {
|
|
if (returns.length < 2) {
|
|
return 0;
|
|
}
|
|
|
|
// Calculate average return
|
|
const avgReturn = returns.reduce((sum, val) => sum + val, 0) / returns.length;
|
|
|
|
// Calculate standard deviation
|
|
const squaredDiffs = returns.map(val => Math.pow(val - avgReturn, 2));
|
|
const avgSquaredDiff = squaredDiffs.reduce((sum, val) => sum + val, 0) / squaredDiffs.length;
|
|
const stdDev = Math.sqrt(avgSquaredDiff);
|
|
|
|
// Avoid division by zero
|
|
if (stdDev === 0) return 0;
|
|
|
|
// Calculate Sharpe ratio
|
|
return (avgReturn - riskFreeRate) / stdDev;
|
|
},
|
|
|
|
/**
|
|
* Calculate the maximum drawdown
|
|
* @param equityCurve Array of equity values over time
|
|
*/
|
|
calculateMaxDrawdown(equityCurve: number[]): number {
|
|
if (equityCurve.length < 2) {
|
|
return 0;
|
|
}
|
|
|
|
let maxDrawdown = 0;
|
|
let peak = equityCurve[0];
|
|
|
|
for (let i = 1; i < equityCurve.length; i++) {
|
|
if (equityCurve[i] > peak) {
|
|
peak = equityCurve[i];
|
|
} else {
|
|
const drawdown = (peak - equityCurve[i]) / peak;
|
|
maxDrawdown = Math.max(maxDrawdown, drawdown);
|
|
}
|
|
}
|
|
|
|
return maxDrawdown;
|
|
},
|
|
|
|
/**
|
|
* Calculate the Compound Annual Growth Rate (CAGR)
|
|
* @param startValue Initial investment value
|
|
* @param endValue Final investment value
|
|
* @param years Number of years
|
|
*/
|
|
calculateCAGR(startValue: number, endValue: number, years: number): number {
|
|
if (years <= 0 || startValue <= 0 || endValue <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
return Math.pow(endValue / startValue, 1 / years) - 1;
|
|
}
|
|
};
|