Một số thuật toán chỉ số hiệu suất thường được thảo luận về chiến lược, một thuật toán cũng được công bố trong tài liệu API của FMZ. Tuy nhiên, không có bình luận, có một số hiểu biết không tốt, bài viết này sẽ đưa bạn phân tích thuật toán này. Tôi tin rằng sau khi đọc bài viết này, bạn nên có một sự hiểu biết tương đối rõ ràng về các khái niệm tính toán, logic như tỷ lệ Sharpe, khước từ tối đa, tỷ lệ lợi nhuận.
Chúng ta tải trực tiếp mã nguồn, mã được viết bằng ngôn ngữ JavaScript. Hệ thống kiểm tra FMZ cũng sử dụng thuật toán này để tự động tạo dữ liệu về hiệu suất kiểm tra.
function returnAnalyze(totalAssets, profits, ts, te, period, yearDays)
Vì nó là một hàm tính toán, nó chắc chắn có đầu vào, đầu ra.
totalAssets, profits, ts, te, period, yearDays
TotalAssets Các tham số này là tổng tài sản ban đầu khi chiến lược bắt đầu hoạt động.
lợi nhuận
Đây là một tham số quan trọng hơn, bởi vì một loạt các tính toán chỉ số hiệu suất được thực hiện xung quanh dữ liệu nguyên liệu này.[[timestamp1, profit1], [timestamp2, profit2], [timestamp3, profit3], ....., [timestampN, profitN]]
, bạn có thể thấy rằng hàm returnAnalyze là một cấu trúc dữ liệu cần một thứ tự thời gian ghi lại các lợi nhuận từng thời điểm. Timestamp1 đến timestampN là theo thứ tự thời gian từ xa và gần. Mỗi thời điểm có một giá trị lợi nhuận. Ví dụ, thời điểm thứ ba trong hồ sơ lợi nhuận là [timestamp3, profit3]. Trong hệ thống trả về trên FMZ, bộ dữ liệu profits được cung cấp cho hàm bởi hệ thống kiểm tra, tất nhiên nếu bạn tự ghi lại dữ liệu lợi nhuận, tạo ra một cấu trúc matrix như vậy, bạn cũng có thể cung cấp cho hàm tính toán này để tính toán kết quả.
ts Thời gian bắt đầu kiểm tra lại là 2 giờ.
te
Thời gian kết thúc kiểm tra lại là
khoảng thời gian Các chu kỳ tính toán ở cấp độ millisecond.
yearDays Ngày giao dịch trong một năm.
Bây giờ chúng ta cùng xem kết quả của hàm này:
return {
totalAssets: totalAssets,
yearDays: yearDays,
totalReturns: totalReturns,
annualizedReturns: annualizedReturns,
sharpeRatio: sharpeRatio,
volatility: volatility,
maxDrawdown: maxDrawdown,
maxDrawdownTime: maxDrawdownTime,
maxAssetsTime: maxAssetsTime,
maxDrawdownStartTime: maxDrawdownStartTime,
winningRate: winningRate
}
Khi biết đầu vào đầu ra, chúng ta sẽ hiểu chức năng này làm gì. Nói đơn giản là cung cấp cho chức năng một số bản ghi nguyên bản, chẳng hạn như bảng thống kê thu nhập. Chức năng sẽ tính toán cho bạn một kết quả để hiển thị hiệu suất kiểm tra lại.
Sau đây, chúng ta sẽ xem các mã được tính như thế nào:
function returnAnalyze(totalAssets, profits, ts, te, period, yearDays) {
// force by days
period = 86400000 // 一天的毫秒数,即 60 * 60 * 24 * 1000
if (profits.length == 0) { // 如果参数profits数组长度为0,无法计算直接返回空值
return null
}
var freeProfit = 0.03 // 无风险利率 ,也可以根据需求设置,例如国债年化3%
var yearRange = yearDays * 86400000 // 一年所有累计的交易日的毫秒数
var totalReturns = profits[profits.length - 1][1] / totalAssets // 累计收益率
var annualizedReturns = (totalReturns * yearRange) / (te - ts) // 年华收益率,把收益统计的时间缩放到一年的尺度上得出的预期收益率
// MaxDrawDown
var maxDrawdown = 0 // 初始化最大回撤变量为0
var maxAssets = totalAssets // 以初始净值赋值初始化最大资产变量
var maxAssetsTime = 0 // 初始化最大资产时刻的时间戳
var maxDrawdownTime = 0 // 初始化最大回撤时刻的时间戳
var maxDrawdownStartTime = 0 // 初始化最大回撤开始时刻的时间戳
var winningRate = 0 // 初始化胜率为0
var winningResult = 0 // 记录赢的次数
for (var i = 0; i < profits.length; i++) { // 遍历收益数组
if (i == 0) {
if (profits[i][1] > 0) { // 如果第一个收益记录点,收益大于0,表示盈利
winningResult++ // 赢的次数累加1
}
} else { // 如果不是第一个收益记录点,只要当前的点的收益,大于前一个时刻(收益点)的收益,表示盈利,赢的次数累加1
if (profits[i][1] > profits[i - 1][1]) {
winningResult++
}
}
if ((profits[i][1] + totalAssets) > maxAssets) { // 如果该时刻的收益加初始净值大于记录出现过的最大资产,就更新最大资产数值,记录这个时刻的时间戳
maxAssets = profits[i][1] + totalAssets
maxAssetsTime = profits[i][0]
}
if (maxAssets > 0) { // 当记录的最大资产数值大于0时,计算回撤
var drawDown = 1 - (profits[i][1] + totalAssets) / maxAssets
if (drawDown > maxDrawdown) { // 如果当前回撤大于记录过的最大回撤,更新最大回撤、最大回撤时间等
maxDrawdown = drawDown
maxDrawdownTime = profits[i][0]
maxDrawdownStartTime = maxAssetsTime
}
}
}
if (profits.length > 0) { // 计算胜率
winningRate = winningResult / profits.length
}
// trim profits
var i = 0
var datas = []
var sum = 0
var preProfit = 0
var perRatio = 0
var rangeEnd = te
if ((te - ts) % period > 0) {
rangeEnd = (parseInt(te / period) + 1) * period // 把rangeEnd处理为period的整倍数
}
for (var n = ts; n < rangeEnd; n += period) {
var dayProfit = 0.0
var cut = n + period
while (i < profits.length && profits[i][0] < cut) { // 确保当时间戳不越界,数组长度也不越界
dayProfit += (profits[i][1] - preProfit) // 计算每天的收益
preProfit = profits[i][1] // 记录昨日的收益
i++ // 累加i用于访问下一个profits节点
}
perRatio = ((dayProfit / totalAssets) * yearRange) / period // 计算当时年华的收益率
sum += perRatio // 累计
datas.push(perRatio) // 放入数组 datas
}
var sharpeRatio = 0 // 初始夏普比率为0
var volatility = 0 // 初始波动率为0
if (datas.length > 0) {
var avg = sum / datas.length; // 求均值
var std = 0;
for (i = 0; i < datas.length; i++) {
std += Math.pow(datas[i] - avg, 2); // std用于计算后面的方差,后面的std / datas.length就是方差,求算数平方根就是标准差
}
volatility = Math.sqrt(std / datas.length); // 当按年时,波动率就是标准差
if (volatility !== 0) {
sharpeRatio = (annualizedReturns - freeProfit) / volatility // 夏普计算公式计算夏普率:(年华收益率 - 无风险利率) / 标准差
}
}
return {
totalAssets: totalAssets,
yearDays: yearDays,
totalReturns: totalReturns,
annualizedReturns: annualizedReturns,
sharpeRatio: sharpeRatio,
volatility: volatility,
maxDrawdown: maxDrawdown,
maxDrawdownTime: maxDrawdownTime,
maxAssetsTime: maxAssetsTime,
maxDrawdownStartTime: maxDrawdownStartTime,
winningRate: winningRate
}
}
Các thuật toán nói chung không phức tạp, có thể có một vài khái niệm cần được hiểu trước.
Phân biệt: Có thể hiểu như một tập hợp dữ liệu thu nhập: Một, hai, ba, bốn, năm mẫu có số trung bình là (((1 + 2 + 3 + 4 + 5) / 5 = 3 và chênh lệch là số trung bình của tổng số vuông của số trung bình của mỗi dữ liệu so với tổng số của chúng: (((1-3) ^ 2 + ((2-3) ^ 2 + ((3-3) ^ 2 + ((4-3) ^ 2 + ((5-3) ^ 2) / 5 = 2, chênh lệch là 2.
Tiêu chuẩn kém: Xét nghiệm này cho thấy các con số khác nhau của các con số khác nhau trong các con số khác nhau.
Tỷ lệ biến động: Khi tính theo tuổi, tỷ lệ biến động là sai tiêu chuẩn.
Với những khái niệm và công thức tính toán này, phần về tính toán Sharp trong hàm cũng được hiểu một cách rõ ràng. Công thức tính toán Sharp tính tỷ lệ Sharp: (tỷ lệ lợi nhuận hàng năm - tỷ lệ lãi suất không rủi ro) / sai tiêu chuẩn
Bạn đã học được chưa?