0

我正在尝试编写 RSI(这对我来说已经是学习 API 数据获取和算法的好方法)。

我从中获取数据的 API 来自信誉良好的交易所,所以我知道我的算法正在分析的值是正确的,这是一个好的开始。

我遇到的问题是,我的计算结果与我在该特定交易所可以读取的结果完全不同,并且还提供了 RSI 指标(我假设他们分析自己的数据,因此数据与我的数据相同)。

我使用完全相同的 API 将 Ichimoku 指标转换为代码,这次一切都正确!我相信我的 RSI 计算可能以某种方式出错,但我已经检查并重新检查了很多次。

我还有一个“文字”版本的代码,其中每一步都像 Excel 表一样计算。它在代码中非常愚蠢,但它验证了计算的逻辑,结果与以下代码相同。

这是我计算 RSI 的代码:

    let period = 14

    // Upward Movements and Downward Movements
    var upwardMovements : [Double] = []
    var downwardMovements : [Double] = []

    for idx in 0..<15 {
        let diff = items[idx + 1].close - items[idx].close
        upwardMovements.append(max(diff, 0))
        downwardMovements.append(max(-diff, 0))
    }

    // Average Upward Movements and Average Downward Movements
    let averageUpwardMovement1 = upwardMovements[0..<period].reduce(0, +) / Double(period)
    let averageDownwardMovement1 = downwardMovements[0..<period].reduce(0, +) / Double(period)

    let averageUpwardMovement2 = (averageUpwardMovement1 * Double(period - 1) + upwardMovements[period]) / Double(period)
    let averageDownwardMovement2 = (averageDownwardMovement1 * Double(period - 1) + downwardMovements[period]) / Double(period)

    // Relative Strength
    let relativeStrength1 = averageUpwardMovement1 / averageDownwardMovement1
    let relativeStrength2 = averageUpwardMovement2 / averageDownwardMovement2

    // Relative Strength Index
    let rSI1 = 100 - (100 / (relativeStrength1 + 1))
    let rSI2 = 100 - (100 / (relativeStrength2 + 1))

    // Relative Strength Index Average
    let relativeStrengthAverage = (rSI1 + rSI2) / 2

    BitcoinRelativeStrengthIndex.bitcoinRSI = relativeStrengthAverage

今天下午 3:23 的读数给出73.93了我的算法和18.74交易所。由于市场现在正在崩溃,我可以在不同的交易所访问不同的 RSI,它们都在下面显示一个 RSI,20所以我的计算是错误的。

你们有什么想法吗?

4

1 回答 1

2

两年后我会回答这个问题,但希望它对某人有所帮助。

您输入的数据点越多,RSI 就越精确。对于 14 的默认 RSI 周期,您应该至少有 200 个以前的数据点。越多越好!

假设您有一组给定市场的收盘价。以下函数将返回每根蜡烛的 RSI 值。您应该始终忽略第一个数据点,因为它们不够精确,或者蜡烛的数量不是 14(或任何您的periods数字)。

func computeRSI(on prices: [Double], periods: Int = 14, minimumPoints: Int = 200) -> [Double] {
    precondition(periods > 1 && minimumPoints > periods && prices.count >= minimumPoints)

    return Array(unsafeUninitializedCapacity: prices.count) { (buffer, count) in
        buffer.initialize(repeating: 50)
        
        var (previousPrice, gain, loss) = (prices[0], 0.0, 0.0)
        for p in stride(from: 1, through: periods, by: 1) {
            let price = prices[p]

            let value = price - previousPrice
            if value > 0 {
                gain += value
            } else {
                loss -= value
            }

            previousPrice = price
        }

        let (numPeriods, numPeriodsMinusOne) = (Double(periods), Double(periods &- 1))
        var avg = (gain: gain / numPeriods, loss: loss /numPeriods)
        buffer[periods] = (avg.loss > .zero) ? 100 - 100 / (1 + avg.gain/avg.loss) : 100

        for p in stride(from: periods &+ 1, to: prices.count, by: 1) {
            let price = prices[p]
            avg.gain *= numPeriodsMinusOne
            avg.loss *= numPeriodsMinusOne

            let value = price - previousPrice
            if value > 0 {
                avg.gain += value
            } else {
                avg.loss -= value
            }

            avg.gain /= numPeriods
            avg.loss /= numPeriods

            if avgLoss > .zero {
                buffer[p] = 100 - 100 / (1 + avg.gain/avg.loss)
            } else {
                buffer[p] = 100
            }
            
            previousPrice = price
        }

        count = prices.count
    }
}

请注意,代码对于减少操作/循环的数量并获得最大的编译器优化是非常必要的。不过,您也许可以使用 Accelerate 框架来提高性能。我们也在处理极端情况,您可能会在一个周期范围内获得所有收益或损失。

如果您想要运行 RSI 计算。只需存储最后一个 RSI 值并执行新价格的 RSI 方程。

于 2020-10-16T20:27:23.023 回答