package backtest import ( "math" "testing" ) func TestComputeMetrics_Empty(t *testing.T) { m := ComputeMetrics(nil) if m.TradeDays != 0 { t.Errorf("expected 0 trade days, got %d", m.TradeDays) } } func TestComputeMetrics_SinglePoint(t *testing.T) { curve := []EquityPoint{{Date: "2020-01-02", Value: 100000, Return: 0}} m := ComputeMetrics(curve) if m.TotalReturn != 0 { t.Errorf("expected 0 total return, got %f", m.TotalReturn) } } func TestComputeMetrics_SteadyGrowth(t *testing.T) { // 10 个交易日,每天涨 1% curve := make([]EquityPoint, 11) curve[0] = EquityPoint{Date: "2020-01-02", Value: 100000, Return: 0} for i := 1; i <= 10; i++ { val := curve[i-1].Value * 1.01 curve[i] = EquityPoint{ Date: "2020-01-02", Value: val, Return: val/100000 - 1, } } m := ComputeMetrics(curve) expectedReturn := 100000*math.Pow(1.01, 10)/100000 - 1 if math.Abs(m.TotalReturn-expectedReturn) > 0.0001 { t.Errorf("total return: expected %f, got %f", expectedReturn, m.TotalReturn) } if m.WinRatio != 1.0 { t.Errorf("win ratio: expected 1.0, got %f", m.WinRatio) } if m.MaxDrawdown > 0.0001 { t.Errorf("max drawdown: expected 0, got %f", m.MaxDrawdown) } if m.TradeDays != 11 { t.Errorf("trade days: expected 11, got %d", m.TradeDays) } } func TestComputeMetrics_Drawdown(t *testing.T) { // 先涨后跌:100000 → 110000 → 99000 curve := []EquityPoint{ {Date: "2020-01-02", Value: 100000, Return: 0}, {Date: "2020-01-03", Value: 110000, Return: 0.1}, {Date: "2020-01-06", Value: 99000, Return: -0.01}, } m := ComputeMetrics(curve) if m.TotalReturn != -0.01 { t.Errorf("total return: expected -0.01, got %f", m.TotalReturn) } // 峰值 110000, 谷 99000, 回撤 = (110000-99000)/110000 = 0.1 expectedDD := 0.1 if math.Abs(m.MaxDrawdown-expectedDD) > 0.0001 { t.Errorf("max drawdown: expected %f, got %f", expectedDD, m.MaxDrawdown) } } func TestComputeMetrics_MixedPerformance(t *testing.T) { // 模拟实际场景:混合涨跌 curve := []EquityPoint{ {Date: "2020-01-02", Value: 100000, Return: 0}, {Date: "2020-01-03", Value: 101000, Return: 0.01}, // +1% {Date: "2020-01-06", Value: 100500, Return: 0.005}, // -0.5% {Date: "2020-01-07", Value: 102000, Return: 0.02}, // +1.5% {Date: "2020-01-08", Value: 101500, Return: 0.015}, // -0.5% {Date: "2020-01-09", Value: 103000, Return: 0.03}, // +1.5% } m := ComputeMetrics(curve) if m.TotalReturn != 0.03 { t.Errorf("total return: expected 0.03, got %f", m.TotalReturn) } if m.TradeDays != 6 { t.Errorf("trade days: expected 6, got %d", m.TradeDays) } // 3 个正收益日 / 5 个交易日 if math.Abs(m.WinRatio-0.6) > 0.0001 { t.Errorf("win ratio: expected 0.6, got %f", m.WinRatio) } // 年化收益应 > 0 if m.AnnualReturn <= 0 { t.Errorf("annual return should be positive, got %f", m.AnnualReturn) } // 波动率应 > 0 if m.Volatility <= 0 { t.Errorf("volatility should be positive, got %f", m.Volatility) } }