С помощью алгоритмов с показателями, такими как Sharp Rate, Maximum Retrograde, Rate of Return, которые помогут вам проанализировать ваши стратегии.

Автор:Маленькие мечты, Создан: 2022-11-26 15:13:17, Обновлено: 2023-09-18 20:21:39

img

С помощью алгоритмов с показателями, такими как Sharp Rate, Maximum Retrograde, Rate of Return, которые помогут вам проанализировать ваши стратегии.

Часто есть группы, которые обсуждают некоторые алгоритмы показателей эффективности стратегии, и один из них также опубликован в API-документации FMZ. Однако без комментариев есть некоторые недопонимания, и эта статья приведет вас к анализу алгоритма, и я уверен, что после прочтения этой статьи вы должны иметь более четкое понимание вычислений и логики концепций, таких как рейтинг Шарпа, максимальный отказ, уровень прибыли.

Мы прямо загружаем исходный код, который написан на языке JavaScript. FMZ также использует этот алгоритм для автоматической генерации данных о результатах рецензирования.

Функция returnAnalyze

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

https://www.fmz.com/api#回测系统夏普算法

Так как это вычислительная функция, то, безусловно, есть ввод, выход.

totalAssets, profits, ts, te, period, yearDays
  • Общие активы Этот параметр представляет собой начальную сумму активов при запуске стратегии.

  • прибыль Этот параметр является более важным параметром, поскольку ряд вычислений показателей производительности ведется вокруг этого исходного данного. Этот параметр является двумерным матричным набором, формат которого, например:[[timestamp1, profit1], [timestamp2, profit2], [timestamp3, profit3], ....., [timestampN, profitN]], можно увидеть, что функция returnAnalyze требует такой структуры данных, которая записывает временные последовательности, в которых получаются доходы в разные моменты; timestamp1 до timestampN в порядке времени от дальнего и близкого; в каждой точке времени есть значение дохода; profit. Так, например, третья точка времени в записи доходов является [timestamp3, profit3]; в системе обратной связи FMZ данные группы profits возвращаются этой функции с помощью контрольной системы, и, конечно, если вы сами записываете данные о доходах, формируя такую структуру, вы можете также предоставить этой функции вычислительный результат.

  • ts Начало проверки - время и место.

  • te Время окончания проверки .

  • период Цикл вычисления на уровне миллисекунд.

  • yearDays В этом году день торговли.

Теперь давайте посмотрим на результат этой функции:

return {
        totalAssets: totalAssets,
        yearDays: yearDays,
        totalReturns: totalReturns,
        annualizedReturns: annualizedReturns,
        sharpeRatio: sharpeRatio,
        volatility: volatility,
        maxDrawdown: maxDrawdown,
        maxDrawdownTime: maxDrawdownTime,
        maxAssetsTime: maxAssetsTime,
        maxDrawdownStartTime: maxDrawdownStartTime,
        winningRate: winningRate
    }
  • totalAssets: начальная чистая стоимость
  • yearDays: число дней, на которые происходит транзакция
  • TotalReturns: совокупная доходность
  • annualizedReturns: годовой доход в Китае
  • SharpeRatio: Отношение к Sharpe
  • volatility: уровень волатильности
  • maxDrawdown: Максимальное снижение
  • maxDrawdownTime: максимальное время вывода
  • maxAssetsTime: время, когда максимальная чистая стоимость
  • maxDrawdownStartTime: Максимальное время начала вывода
  • winningRate: вероятность победы

img

Зная вход и выход, мы понимаем, что эта функция делает. Проще говоря, дайте ей некоторые первичные записи, такие как статистические наборы доходов. Функция вычисляет вам результат, чтобы показать результаты ретроспекции.

В следующей статье мы рассмотрим, как код рассчитывается:

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

В целом алгоритм не сложный, и в нем могут быть несколько концепций, которые требуют предварительного понимания.

  • Разница: Это может быть понято как совокупность данных о доходах: 1, 2, 3, 4, 5 - это пример, среднее число которого (((1+2+3+4+5) /5) = 3, а дифференциал - это среднее число суммы квадратов разницы между средним числом и суммой этих данных: (((1-3) ^2 + ((2-3) ^2 + ((3-3) ^2 + ((4-3) ^2 + ((5-3) ^2) /5) = 2, дифференциал 2.

  • Склонность к нормам: Квадратный корень расчёта квадратического отклонения, то есть стандартный отклонение.

  • Например, в Нью-Йорке. При расчете шкалы на годовые значения, колебания являются стандартными.

Если вы понимаете эти понятия и формулы, то часть функций, касающаяся вычислений Шарпа, становится очевидной. Формула вычисления Шарпа для вычисления ставки Шарпа: ((Ежегодная китайская доходность - процентная ставка без риска) / стандартный отклонение)

Вы узнали?


Связанные

Больше