리소스 로딩... 로딩...

당신이 Sharpe 비율을 분석 할 수 있습니다, 최대 마감, 수익률 및 전략 백테스팅에서 다른 지표 알고리즘

저자:FMZ~리디아, 창작: 2022-11-28 16:44:25, 업데이트: 2023-09-13 19:42:38

img

당신이 Sharpe 비율을 분석 할 수 있습니다, 최대 마감, 수익률 및 전략 백테스팅에서 다른 지표 알고리즘

전략의 일부 성능 지표 알고리즘은 종종 그룹 구성원들에 의해 논의되고 있으며, FMZ의 API 문서에서도 알고리즘이 공개되었습니다. 그러나, 댓글없이 이해하는 것은 쉽지 않습니다. 이 기사에서는 알고리즘을 분석하도록 안내합니다. 이 기사를 읽은 후 샤프 비율, 최대 마감, 수익률 및 계산 논리의 개념을 명확하게 이해 할 것이라고 믿습니다. 자바스크립트 언어로 작성된 소스 코드부터 시작하겠습니다. FMZ의 백테스팅 시스템은 또한 이 알고리즘을 채택하여 백테스팅 성능 데이터를 자동으로 생성합니다.

return분석 함수

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

https://www.fmz.com/api#Backtesting시스템 샤프 알고리즘

계산 함수이기 때문에 입력과 출력이 있어야 합니다.

totalAssets, profits, ts, te, period, yearDays
  • 전체자산 이 매개 변수는 전략 실행 시작 시 초기 총 자산입니다.

  • 수익 이 매개 변수는 이 원본 데이터에 기초하여 일련의 성능 지표가 계산되기 때문에 중요한 매개 변수입니다. 이 매개 변수는 다음과 같은 형식의 2차원 배열입니다.[[timestamp1, profit1], [timestamp2, profit2], [timestamp3, profit3],..., [timestampN, profitN]]. returnAnalyze 함수는 매번 반환의 시간 순서를 기록하는 데이터 구조가 필요하다는 것을 알 수 있습니다. 타임 스탬프1에서 타임 스탬프N은 시간 순서로 멀리부터 가까이까지 있습니다. 각 시간 지점에서 이익 값이 있습니다. 예를 들어, 반환 기록의 세 번째 시간 지점은 [시간 스탬프 3, 이익]입니다. FMZ의 온라인 백테스팅 시스템에서 수익 배열의 데이터는 백테스팅 시스템에서이 이 함수에게 제공합니다. 물론, 귀환 데이터를 직접 기록하고 그러한 배열 구조를 형성하면 결과를 계산하기 위해 계산 함수에도 제공할 수 있습니다.

  • ts 백테스트의 시작 시간표

  • te 백테스트의 종료 시간표입니다.

기간 밀리 초 수준에서 계산 기간

  • 일일 1년 안에 거래하는 날

다음으로, 이 함수의 출력을 함께 살펴보겠습니다.

return {
        totalAssets: totalAssets,
        yearDays: yearDays,
        totalReturns: totalReturns,
        annualizedReturns: annualizedReturns,
        sharpeRatio: sharpeRatio,
        volatility: volatility,
        maxDrawdown: maxDrawdown,
        maxDrawdownTime: maxDrawdownTime,
        maxAssetsTime: maxAssetsTime,
        maxDrawdownStartTime: maxDrawdownStartTime,
        winningRate: winningRate
    }
  • 자산 총: 자산 총
  • 연일: 거래일
  • 전체 수익: 전체 수익
  • 연간 수익: 연간 수익
  • sharpeRatio: 샤프 비율
  • 변동성: 변동성
  • 최대 사용량: 최대 사용량
  • maxDrawdownTime: 최대 마이너다운의 시간표
  • maxAssetsTime: 최대 자산의 시간표
  • maxDrawdownStartTime: 최대 마이너다운의 시작 시간
  • 승률: 승률

입력과 출력을 알고, 우리는 함수가 무엇을 위해 사용되는지 이해할 수 있습니다. 간단히 말해서, 그것은 반환 통계 배열과 같은 함수 몇 가지 원래 기록을 제공합니다. 함수는 당신이 백테스트의 성능을 보여주기 위해 결과를 줄 것입니다.

다음으로, 코드를 계산하는 방법을 보자:

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

전체적으로, 알고리즘은 복잡하지 않으며, 미리 이해해야 할 몇 가지 개념이 있을 수 있습니다.

  • 오차: 그것은 반환 데이터의 집합으로 이해할 수 있습니다. 표본의 그룹, 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입니다.

  • 표준편차: 표준편차인 변수의 수학적 제곱근을 계산합니다.

  • 변동성: 계산 척도가 연간화되면 변동성은 표준편차입니다.

이러한 개념과 계산 공식을 이해하면 함수의 샤프 계산 부분은 한눈에 명확해질 것입니다. 샤르프 비율을 계산하는 샤르프 공식: (년화 수익률 - 위험 없는 비율) / 표준편차

이미 배웠어?


더 많은