avatar of 发明者量化-小小梦 发明者量化-小小梦
fokus pada mesej peribadi
4
fokus pada
1271
Pengikut

Analisis nisbah Sharpe, pengeluaran maksimum, kadar pulangan dan algoritma penunjuk lain dalam ujian balik strategi

Dicipta dalam: 2022-11-26 15:13:17, dikemas kini pada: 2023-09-18 20:21:39
comments   0
hits   2054

Analisis nisbah Sharpe, pengeluaran maksimum, kadar pulangan dan algoritma penunjuk lain dalam ujian balik strategi

Analisis nisbah Sharpe, pengeluaran maksimum, kadar pulangan dan algoritma penunjuk lain dalam ujian balik strategi

Ahli kumpulan sering membincangkan beberapa algoritma penunjuk prestasi strategi, dan algoritma juga didedahkan dalam dokumentasi API FMZ. Walau bagaimanapun, ia adalah sedikit sukar untuk memahami tanpa komen Dalam artikel ini, saya akan membawa anda untuk menganalisis algoritma ini Saya percaya bahawa selepas membaca artikel ini, anda harus mempunyai pemahaman yang lebih baik tentang konsep dan logik pengiraan nisbah Sharpe. pengeluaran, dan kadar pulangan Setiap orang mempunyai pemahaman yang lebih jelas.

Kami pergi terus ke kod sumber, yang ditulis dalam JavaScript. Sistem ujian belakang FMZ juga menggunakan algoritma ini untuk menjana data prestasi ujian belakang secara automatik.

fungsi returnAnalyze

function returnAnalyze(totalAssets, profits, ts, te, period, yearDays)

https://www.fmz.com/api#%E5%9B%9E%E6%B5%8B%E7%B3%BB%E7%BB%9F%E5%A4%8F%E6%99%AE%E7%AE%97%E6%B3%95

Oleh kerana ia adalah fungsi pengiraan, ia mesti mempunyai input dan output. Mari kita lihat dahulu input fungsi:

totalAssets, profits, ts, te, period, yearDays
  • totalAssets Parameter ini ialah jumlah aset awal apabila strategi mula dijalankan.

  • profits Parameter ini merupakan parameter yang agak penting kerana satu siri pengiraan penunjuk prestasi adalah berdasarkan data mentah ini. Parameter ini ialah tatasusunan dua dimensi, formatnya adalah seperti berikut:[[timestamp1, profit1], [timestamp2, profit2], [timestamp3, profit3], ....., [timestampN, profitN]], kita dapat melihat bahawa fungsi returnAnalyze memerlukan struktur data yang merekodkan susunan kronologi pulangan pada setiap saat. timestamp1 ke timestampN adalah mengikut urutan dari masa yang jauh ke dekat. Pada setiap masa terdapat nilai keuntungan. Jadi, sebagai contoh, titik kali ketiga dalam rekod pendapatan ialah[cap masa3, untung3]. Dalam sistem ujian belakang pada baris FMZ, data tatasusunan keuntungan disediakan kepada fungsi ini oleh sistem ujian belakang Sudah tentu, jika anda merekodkan data keuntungan sendiri untuk membentuk struktur tatasusunan, anda juga boleh memberikannya kepada fungsi pengiraan ini. hitung hasilnya.

  • ts Cap masa mula ujian belakang.

  • te Cap masa tamat ujian belakang.

  • period Kitaran pengiraan dalam milisaat.

  • yearDays Hari dagangan dalam setahun.

Seterusnya, mari kita lihat output fungsi ini:

return {
        totalAssets: totalAssets,
        yearDays: yearDays,
        totalReturns: totalReturns,
        annualizedReturns: annualizedReturns,
        sharpeRatio: sharpeRatio,
        volatility: volatility,
        maxDrawdown: maxDrawdown,
        maxDrawdownTime: maxDrawdownTime,
        maxAssetsTime: maxAssetsTime,
        maxDrawdownStartTime: maxDrawdownStartTime,
        winningRate: winningRate
    }
  • totalAssets: Nilai bersih awal
  • tahunHari: hari dagangan
  • jumlahPulangan: kadar pulangan terkumpul
  • annualizedReturns: pulangan tahunan
  • sharpeNisbah: Nisbah tajam
  • Kemeruapan: turun naik
  • maxDrawdown: Anjakan maksimum
  • maxDrawdownTime: Cap masa pengeluaran maksimum
  • maxAssetsTime: cap masa nilai bersih maksimum
  • maxDrawdownStartTime: Masa mula anjakan maksimum
  • winningRate: kadar kemenangan

Analisis nisbah Sharpe, pengeluaran maksimum, kadar pulangan dan algoritma penunjuk lain dalam ujian balik strategi

Mengetahui input dan output, kini kita faham untuk apa fungsi ini digunakan. Ringkasnya, berikan fungsi ini beberapa rekod mentah, seperti susunan statistik hasil. Fungsi ini akan mengira hasil untuk anda menunjukkan prestasi ujian belakang.

Seterusnya, mari lihat bagaimana kod dikira:

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
    }
}

Algoritma ini tidak rumit secara keseluruhan, tetapi mungkin terdapat beberapa konsep yang perlu difahami terlebih dahulu.

  • varians: Ia boleh difahami sebagai satu set data hasil: Purata bagi set sampel 1, 2, 3, 4, 5 ialah (1+2+3+4+5)/5=3, dan varians ialah jumlah kuasa dua perbezaan antara setiap titik data dan min. Purata daripada ialah:[(1-3)^2+(2-3)^2+(3-3)^2+(4-3)^2+(5-3)^2]/5=2, dan varians ialah 2 .

  • Sisihan Piawai: Ambil punca kuasa dua varians, iaitu sisihan piawai.

  • Kemeruapan: Apabila skala pengiraan disetahunkan, turun naik ialah sisihan piawai.

Sebaik sahaja anda memahami konsep dan formula pengiraan ini, bahagian pengiraan Sharpe fungsi akan menjadi jelas sepintas lalu. Formula pengiraan nisbah tajam: (pulangan tahunan - kadar bebas risiko) / sisihan piawai

Adakah anda telah mempelajarinya?