Индекс относительной силы в Swift
Я пытаюсь закодировать 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
Чтения в 15:23 сегодня днем дают 73.93
для моего алгоритма и 18.74
на обмен. Поскольку рынки сейчас терпят крах, и у меня есть доступ к различным RSI на разных биржах, все они показывают RSI ниже 20
так что мои расчеты выключены.
Ребята, у вас есть идеи?
0 ответов
Я отвечаю на это 2 года спустя, но, надеюсь, это кому-то поможет.
RSI становится тем точнее, чем больше точек данных вы вводите в него. Для периода RSI по умолчанию, равного 14, у вас должно быть не менее 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 для новой цены.