2025-06-27 09:18:00 +08:00

80 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 分析投资数据并计算关键指标
* @param fundAmounts 资金量数组每15分钟记录一次
* @returns 投资分析结果
*/
export function analyzeInvestment(fundAmounts: number[]): {
maxDrawdown: number; // 最大回撤 (百分比)
maxDrawdownPeriod: [number, number]; // 最大回撤区间 [开始索引, 结束索引]
volatility: number; // 波动率 (标准差)
averageReturn: number; // 平均收益率 (百分比)
cumulativeReturn: number; // 累计收益率 (百分比)
winRate: number; // 盈利率 (百分比)
sharpeRatio: number; // 夏普比率 (假设无风险利率为0)
} {
if (fundAmounts.length < 2) {
throw new Error("需要至少两个数据点来计算投资指标");
}
// 计算每个时间点的收益率
const returns: number[] = [];
for (let i = 1; i < fundAmounts.length; i++) {
const returnRate = (fundAmounts[i] - fundAmounts[i - 1]) / fundAmounts[i - 1];
returns.push(returnRate);
}
// 计算最大回撤
let maxDrawdown = 0;
let peak = fundAmounts[0];
let maxDrawdownStartIndex = 0;
let maxDrawdownEndIndex = 0;
let currentPeakIndex = 0;
for (let i = 1; i < fundAmounts.length; i++) {
if (fundAmounts[i] > peak) {
peak = fundAmounts[i];
currentPeakIndex = i;
}
const drawdown = (peak - fundAmounts[i]) / peak;
if (drawdown > maxDrawdown) {
maxDrawdown = drawdown;
maxDrawdownStartIndex = currentPeakIndex;
maxDrawdownEndIndex = i;
}
}
// 计算波动率 (收益率的标准差)
const avgReturn = returns.reduce((sum, r) => sum + r, 0) / returns.length;
const variance = returns.reduce((sum, r) => sum + Math.pow(r - avgReturn, 2), 0) / returns.length;
const volatility = Math.sqrt(variance);
// 计算累计收益率
const cumulativeReturn = (fundAmounts[fundAmounts.length - 1] - fundAmounts[0]) / fundAmounts[0];
// 计算盈利率 (正收益率的比例)
const winCount = returns.filter(r => r > 0).length;
const winRate = (winCount / returns.length) * 100;
// 计算夏普比率 (假设无风险利率为5%)
const riskFreeRate = 0.05; // 无风险利率5%
const annualizedReturn = avgReturn * (250 * 16) - riskFreeRate; // 调整为年化收益率减去无风险利率
const annualizedVolatility = volatility * Math.sqrt(250 * 16);
const sharpeRatio = annualizedVolatility === 0 ? 0 : annualizedReturn / annualizedVolatility;
return {
maxDrawdown: maxDrawdown * 100, // 转换为百分比
maxDrawdownPeriod: [maxDrawdownStartIndex, maxDrawdownEndIndex],
volatility: volatility * 100, // 转换为百分比
averageReturn: avgReturn * 100, // 转换为百分比
cumulativeReturn: cumulativeReturn * 100, // 转换为百分比
winRate,
sharpeRatio
};
}
// 使用示例:
// const fundAmounts = [10000, 8844.4, 9200, 9100, 9500, 9300, 9200, 8800, 9000, 9400];
// const analysis = analyzeInvestment(fundAmounts);
// console.log(analysis);