Ambil anda untuk menganalisis nisbah Sharpe, pengeluaran maksimum, kadar pulangan dan algoritma penunjuk lain dalam strategi backtesting

Penulis:Lydia, Dicipta: 2022-11-28 16:44:25, Dikemas kini: 2023-09-13 19:42:38

img

Ambil anda untuk menganalisis nisbah Sharpe, pengeluaran maksimum, kadar pulangan dan algoritma penunjuk lain dalam strategi backtesting

Beberapa algoritma penunjuk prestasi strategi sering dibincangkan oleh ahli kumpulan, dan algoritma juga telah didedahkan dalam dokumen API FMZ. Walau bagaimanapun, ia tidak mudah difahami tanpa komen. Dalam artikel ini, saya akan membawa anda untuk menganalisis algoritma. Saya percaya bahawa anda akan mempunyai pemahaman yang jelas tentang konsep nisbah Sharpe, pengeluaran maksimum, kadar pulangan dan logik pengiraan selepas membaca artikel ini. Kami akan mulakan dengan kod sumber, yang ditulis dalam bahasa JavaScript. Sistem backtesting FMZ juga menggunakan algoritma ini untuk menjana data prestasi backtesting secara automatik.

returnFungsi Analisis

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

https://www.fmz.com/api#BacktestingSistem Algoritma Sharpe

Oleh kerana ia adalah fungsi pengiraan, mesti ada input dan output.

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

  • keuntungan Parameter ini adalah penting, kerana satu siri penunjuk prestasi dikira berdasarkan data asal ini. Parameter ini adalah array dua dimensi dalam format berikut:[[timestamp1, profit1], [timestamp2, profit2], [timestamp3, profit3],..., [timestampN, profitN]]. Ia dapat dilihat bahawa fungsi returnAnalyze memerlukan struktur data seperti yang merekodkan susunan kronologi pulangan pada setiap masa. Timestamp1 ke timestampN adalah dalam susunan kronologi dari jauh ke dekat. Terdapat nilai keuntungan pada setiap titik masa. Sebagai contoh, titik masa ketiga dalam rekod pulangan adalah [timestamp 3, keuntungan3]. Dalam sistem backtesting dalam talian FMZ, data array keuntungan disediakan kepada fungsi ini oleh sistem backtesting. Sudah tentu, jika anda merekodkan data pulangan sendiri dan membentuk struktur array seperti itu, anda juga boleh memberikannya kepada fungsi pengiraan untuk mengira hasilnya.

  • ts Stempel waktu permulaan backtest.

  • te Stempel masa akhir ujian belakang.

tempoh Tempoh pengiraan pada tahap milidetik.

  • tahunHari Berdagang hari dalam setahun.

Seterusnya, mari kita lihat output fungsi ini bersama-sama:

return {
        totalAssets: totalAssets,
        yearDays: yearDays,
        totalReturns: totalReturns,
        annualizedReturns: annualizedReturns,
        sharpeRatio: sharpeRatio,
        volatility: volatility,
        maxDrawdown: maxDrawdown,
        maxDrawdownTime: maxDrawdownTime,
        maxAssetsTime: maxAssetsTime,
        maxDrawdownStartTime: maxDrawdownStartTime,
        winningRate: winningRate
    }
  • Jumlah aset: jumlah aset
  • tahunHari: hari dagangan
  • Jumlah pulangan: jumlah pulangan
  • AnnualisedReturn: pulangan tahunan
  • sharpeRatio: Nisbah Sharpe
  • Volatiliti: Volatiliti
  • MaxDrawdown: pengambilan maksimum
  • maxDrawdownTime: cap masa pada pengambilan maksimum
  • maxAssetsTime: cap masa pada aset maksimum
  • maxDrawdownStartTime: masa permulaan pengeluaran maksimum
  • winningRate: kadar kemenangan

Mengetahui input dan output, kita boleh memahami apa fungsi digunakan untuk. Untuk meletakkannya dengan mudah, ia memberikan fungsi beberapa rekod asal, seperti array statistik pulangan. Fungsi akan memberikan anda hasil untuk menunjukkan prestasi backtest.

Seterusnya, mari kita lihat bagaimana kod dikira:

function returnAnalyze(totalAssets, profits, ts, te, period, yearDays) {
    // force by days
    period = 86400000                  // The number of milliseconds in a day, that is 60 * 60 * 24 * 1000
    if (profits.length == 0) {         // If the length of the array of profits is 0, it cannot be calculated and it will return to the null value directly
        return null
    }
    var freeProfit = 0.03              // Risk-free interest rate, which can also be set according to the demand, such as 3% annualized national debt
    var yearRange = yearDays * 86400000          // Milliseconds of all accumulated trading days in a year
    var totalReturns = profits[profits.length - 1][1] / totalAssets      // Total return rate
    var annualizedReturns = (totalReturns * yearRange) / (te - ts)       // The annualized rate of return, the expected rate of return obtained by scaling the time of profit statistics to the scale of one year

    // MaxDrawDown
    var maxDrawdown = 0           // Initialize the maximum drawdown variable to 0
    var maxAssets = totalAssets   // Initialize maximum asset variable with initial net value assignment
    var maxAssetsTime = 0         // Timestamp of the time when the maximum asset is initialized
    var maxDrawdownTime = 0       // Timestamp of the time when the maximum drawdown is initialized
    var maxDrawdownStartTime = 0  // Timestamp of the time when the maximum start time is initialized
    var winningRate = 0           // Initialized win rate is 0
    var winningResult = 0         // Record the number of win time
    for (var i = 0; i < profits.length; i++) {      // Traverse the return array
        if (i == 0) {
            if (profits[i][1] > 0) {                // If the first return record point, the return is greater than 0, it means the profit
                winningResult++                     // The number of win times accumulates 1 
            }
        } else {                                    // If it is not the first returns record point, as long as the returns of the current point is greater than the returns of the previous moment (return point), it means profit, and the number of win times accumulates 1 
            if (profits[i][1] > profits[i - 1][1]) {
                winningResult++
            }
        }
        if ((profits[i][1] + totalAssets) > maxAssets) {    // If the return plus the initial net value at that moment is greater than the largest asset recorded to have occurred, the value of the largest asset is updated and the timestamp of this moment is recorded
            maxAssets = profits[i][1] + totalAssets
            maxAssetsTime = profits[i][0]
        }
        if (maxAssets > 0) {                                // When the maximum asset value recorded is greater than 0, the drawdown is calculated
            var drawDown = 1 - (profits[i][1] + totalAssets) / maxAssets
            if (drawDown > maxDrawdown) {                   // If the current drawdown is greater than the recorded maximum drawdown, update the maximum drawdown, maximum drawdown time, etc
                maxDrawdown = drawDown
                maxDrawdownTime = profits[i][0]
                maxDrawdownStartTime = maxAssetsTime
            }
        }
    }
    if (profits.length > 0) {                            // Calculate the winning rate
        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     // Process rangeEnd as an integer multiple of 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) {    // Ensure that when the timestamp is not out of bounds, the array length is also not out of bounds
            dayProfit += (profits[i][1] - preProfit)           // Calculate the daily returns
            preProfit = profits[i][1]                          // Record yesterday's returns
            i++                                                // Accumulate i for accessing the next profits node
        }
        perRatio = ((dayProfit / totalAssets) * yearRange) / period   // Calculate the annualized rate of return at that time
        sum += perRatio                                               // Accumulation
        datas.push(perRatio)                                          // Put in the array datas
    }

    var sharpeRatio = 0                    // Initial Sharpe ratio is 0
    var volatility = 0                     // Initial volatility is 0
    if (datas.length > 0) {
        var avg = sum / datas.length;      // Find the mean value
        var std = 0;
        for (i = 0; i < datas.length; i++) {
            std += Math.pow(datas[i] - avg, 2);      // The std is used to calculate the following variance. The following std/datas.length is the variance, and the square root of the number is the standard deviation
        }
        volatility = Math.sqrt(std / datas.length);  // In terms of years, volatility is the standard deviation
        if (volatility !== 0) {
            sharpeRatio = (annualizedReturns - freeProfit) / volatility   // Sharpe formula to calculate Sharpe ratio: (annualized return rate - risk-free rate) / standard deviation
        }
    }

    return {
        totalAssets: totalAssets,
        yearDays: yearDays,
        totalReturns: totalReturns,
        annualizedReturns: annualizedReturns,
        sharpeRatio: sharpeRatio,
        volatility: volatility,
        maxDrawdown: maxDrawdown,
        maxDrawdownTime: maxDrawdownTime,
        maxAssetsTime: maxAssetsTime,
        maxDrawdownStartTime: maxDrawdownStartTime,
        winningRate: winningRate
    }
}

Secara keseluruhan, algoritma tidak rumit, dan mungkin terdapat beberapa konsep yang perlu difahami terlebih dahulu.

  • Varians: Ia boleh difahami sebagai satu set data pulangan. Kumpulan sampel, 1, 2, 3, 4 dan 5, mempunyai nilai purata (1+2+3+4+5)/5 = 3, manakala varians adalah nilai purata jumlah kuadrat perbezaan antara setiap data dan jumlahnya masing-masing, iaitu [(1-3) ^ 2 + (2-3) ^ 2 + (3-3) ^ 2 + (4-3) ^ 2 + (5-3) ^ 2) / 5 = 2, dan varians adalah 2.

  • Pengecualian standard: Hitung akar persegi aritmatika dari varians, yang merupakan penyimpangan standard.

  • Volatiliti: Apabila skala pengiraan adalah tahunan, volatiliti adalah penyimpangan standard.

Dengan pemahaman konsep dan formula pengiraan ini, bahagian pengiraan Sharpe fungsi akan jelas seketika. Formula Sharpe untuk mengira nisbah Sharpe: (tingkat pulangan tahunan - kadar bebas risiko) / penyimpangan standard

Sudahkah kamu belajar?


Lebih lanjut