Initial commit: 可转债轮动分析系统
- 实时行情:东财push2主源 + 腾讯批量报价备用源(自动切换) - 历史K线:东财push2his主源 + 腾讯web子域备用源(含熔断机制) - 增量同步:支持 -incr/-since 参数按存档日期增量入库 - 策略回测:净值曲线/10指标/基准对比,含基本面过滤 - 用户认证:用户名密码 + 邮箱验证码双登录方式 - 前端:三Tab SPA(实时行情/策略回测/数据管理)
This commit is contained in:
85
internal/backtest/metrics.go
Normal file
85
internal/backtest/metrics.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package backtest
|
||||
|
||||
import "math"
|
||||
|
||||
// Metrics 回测绩效指标。
|
||||
type Metrics struct {
|
||||
TotalReturn float64 // 累计收益率
|
||||
AnnualReturn float64 // 年化收益率
|
||||
MaxDrawdown float64 // 最大回撤(正值)
|
||||
Sharpe float64 // 年化夏普比率(无风险利率为 0)
|
||||
Volatility float64 // 年化波动率
|
||||
WinRatio float64 // 正收益交易日占比
|
||||
TradeDays int // 回测交易日数
|
||||
}
|
||||
|
||||
const tradingDaysPerYear = 252.0
|
||||
|
||||
// ComputeMetrics 从净值曲线计算绩效指标。
|
||||
func ComputeMetrics(curve []EquityPoint) Metrics {
|
||||
m := Metrics{TradeDays: len(curve)}
|
||||
if len(curve) == 0 {
|
||||
return m
|
||||
}
|
||||
m.TotalReturn = curve[len(curve)-1].Return
|
||||
|
||||
// 日收益率序列。
|
||||
rets := make([]float64, 0, len(curve)-1)
|
||||
for i := 1; i < len(curve); i++ {
|
||||
if curve[i-1].Value > 0 {
|
||||
rets = append(rets, curve[i].Value/curve[i-1].Value-1)
|
||||
}
|
||||
}
|
||||
|
||||
// 最大回撤:遍历峰值。
|
||||
var peak, maxDD float64
|
||||
for _, p := range curve {
|
||||
if p.Value > peak {
|
||||
peak = p.Value
|
||||
}
|
||||
if dd := peak - p.Value; dd > maxDD {
|
||||
maxDD = dd
|
||||
}
|
||||
}
|
||||
if peak > 0 {
|
||||
m.MaxDrawdown = maxDD / peak
|
||||
}
|
||||
|
||||
n := len(rets)
|
||||
if n == 0 {
|
||||
return m
|
||||
}
|
||||
|
||||
// 年化收益率。
|
||||
years := float64(n) / tradingDaysPerYear
|
||||
if years > 0 && 1+m.TotalReturn > 0 {
|
||||
m.AnnualReturn = math.Pow(1+m.TotalReturn, 1/years) - 1
|
||||
}
|
||||
|
||||
// 波动率与夏普。
|
||||
mean := 0.0
|
||||
for _, r := range rets {
|
||||
mean += r
|
||||
}
|
||||
mean /= float64(n)
|
||||
|
||||
var variance float64
|
||||
for _, r := range rets {
|
||||
variance += (r - mean) * (r - mean)
|
||||
}
|
||||
variance /= float64(n - 1)
|
||||
m.Volatility = math.Sqrt(variance) * math.Sqrt(tradingDaysPerYear)
|
||||
if m.Volatility > 0 {
|
||||
m.Sharpe = mean * tradingDaysPerYear / m.Volatility
|
||||
}
|
||||
|
||||
// 正收益日占比。
|
||||
win := 0
|
||||
for _, r := range rets {
|
||||
if r > 0 {
|
||||
win++
|
||||
}
|
||||
}
|
||||
m.WinRatio = float64(win) / float64(n)
|
||||
return m
|
||||
}
|
||||
Reference in New Issue
Block a user