80 lines
3.1 KiB
TypeScript
80 lines
3.1 KiB
TypeScript
/**
|
||
* 分析投资数据并计算关键指标
|
||
* @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);
|