我希望完全镜像cryptowatch.de上的RSI值(在我的情况下为LTC-EUR),我使用了网站stockcharts.com,它解释了如何计算RSI,用Javascript编写计算器(节点)。
到目前为止我的代码:
// data is an array of open-prices in descending date order (the current price is the last element)
function calculateRSI(data) {
data = data.reverse(); // Reverse to handle it better
let avgGain = 0;
let aveLoss = 0;
// Calculate first 14 periods
for (let i = 0; i < 14; i++) {
const ch = data[i] - data[i + 1];
if (ch >= 0) {
avgGain += ch;
} else {
aveLoss -= ch;
}
}
avgGain /= 14;
aveLoss /= 14;
// Smooth values 250 times
for (let i = 14; i < 264; i++) {
const ch = data[i] - data[i + 1];
if (ch >= 0) {
avgGain = (avgGain * 13 + ch) / 14;
aveLoss = (aveLoss * 13) / 14;
} else {
avgGain = (avgGain * 13) / 14;
aveLoss = (aveLoss * 13 - ch) / 14;
}
}
// Calculate relative strength index
const rs = avgGain / aveLoss;
return 100 - 100 / (1 + rs);
}
但结果总是远离cryptowatch.de上显示的值,这有什么不对?如何正确计算? (其他编程语言的帖子也可以)
谢谢@jingx但结果仍然错误
答案 0 :(得分:0)
当你获得收益时,你可能会错过平滑avgLoss
,而当它失去时,你可能错过avgGain
,即顺利循环:
if (ch >= 0) {
avgGain = (avgGain * 13 + ch) / 14;
aveLoss = (aveLoss * 13) / 14;
} else {
avgGain = (avgGain * 13) / 14;
aveLoss = (aveLoss * 13 - ch) / 14;
}
答案 1 :(得分:0)
如何正确计算? (其他编程语言中的帖子也可以)
QuantFX
模块中添加一个可能会遇到很多配方,有些带有示例,有些带有验证数据集,所以让我选择一个这样的,使用numba.jit
装饰的python代码,并使用一些numpy
矢量化招数:
def RSI_func( priceVEC, RSI_period = 14 ):
"""
__doc__
USE:
RSI_func( priceVEC, RSI_period = 14 )
Developed by J. Welles Wilder and introduced in his 1978 book,
New Concepts in Technical Trading Systems, the Relative Strength Index
(RSI) is an extremely useful and popular momentum oscillator.
The RSI compares the magnitude of a stock's recent gains
to the magnitude of its recent losses and turns that information
into a number that ranges from 0 to 100.
It takes a single parameter, the number of time periods to use
in the calculation. In his book, Wilder recommends using 14 periods.
The RSI's full name is actually rather unfortunate as it is easily
confused with other forms of Relative Strength analysis such as
John Murphy's "Relative Strength" charts and IBD's "Relative Strength"
rankings.
Most other kinds of "Relative Strength" stuff involve using
more than one stock in the calculation. Like most true indicators,
the RSI only needs one stock to be computed.
In order to avoid confusion,
many people avoid using the RSI's full name and just call it "the RSI."
( Written by Nicholas Fisher)
PARAMS:
pricesVEC - a vector of price-DOMAIN-alike data in natural order
RSI_period - a positive integer for an RSI averaging period
RETURNS:
a vector of RSI values
EXAMPLE:
>>> RSI_func( np.asarray( [ 46.1250, 47.1250, 46.4375, 46.9375, 44.9375,
44.2500, 44.6250, 45.7500, 47.8125, 47.5625,
47.0000, 44.5625, 46.3125, 47.6875, 46.6875,
45.6875, 43.0625, 43.5625, 44.8750, 43.6875
]
),
RSI_period = 14
)
array( [ 51.77865613, 51.77865613, 51.77865613, 51.77865613, 51.77865613, 51.77865613, 51.77865613,
51.77865613, 51.77865613, 51.77865613, 51.77865613, 51.77865613, 51.77865613,
51.77865613, 48.47708511, 41.07344947, 42.86342911, 47.38184958, 43.99211059
]
)
OUGHT BE:
51.779, 48.477, 41.073, 42.863, 47.382, 43.992
[PASSED]
Ref.s:
>>> http://cns.bu.edu/~gsc/CN710/fincast/Technical%20_indicators/Relative%20Strength%20Index%20(RSI).htm
"""
deltas = np.diff( priceVEC )
seed = deltas[:RSI_period]
up = seed[seed >= 0].sum() / RSI_period
down = -seed[seed < 0].sum() / RSI_period
rs = up / down
rsi = 50. * np.ones_like( priceVEC ) # NEUTRAL VALUE PRE-FILL
rsi[:RSI_period] = 100. - ( 100. / ( 1. + rs ) )
for i in np.arange( RSI_period, len( priceVEC )-1 ):
delta = deltas[i]
if delta > 0:
upval = delta
downval = 0.
else:
upval = 0.
downval = -delta
up = ( up * ( RSI_period - 1 ) + upval ) / RSI_period
down = ( down * ( RSI_period - 1 ) + downval ) / RSI_period
rs = up / down
rsi[i] = 100. - ( 100. / ( 1. + rs ) )
return rsi[:-1]
鉴于您希望“完全镜像”其他人的图表,有一种最安全的模式可以交叉检查他们实际用于RSI计算的配方。通常会看到差异,因此“完全”匹配需要调查他们实际用于生成数据的内容(如果使用D1,还会注意相应的管理UTC偏移差异) -time-frame)。
答案 2 :(得分:0)
我知道这是一个日志记录时间,但是我只是遇到了这个问题并获得了正确的技术。我花了很长时间才弄清楚在C#中的乐趣。
第1步。您正在从API接收从过去[0]到现在[x]的值。对于“ Close / 14”,您必须计算“ Close”值(利润/亏损)的差异,如下所示:
var profitAndLoss = new List<double>();
for (int i = 0; i < values.Count - 1; i++)
profitAndLoss.Add(values[i + 1] - values[i]); //newer - older value will give you negative values for losses and positiv values for profits
步骤2。计算您的初始rsi值(通常简称为RSI StepOne),请注意我没有反转接收到的值。初始计算是使用“最早的”值完成的。 _samples是您最初用于计算RSI的值的数量,在我的情况下,默认值为'Close / 14'_samples = 14:
var avgGain = 0.0;
var avgLoss = 0.0;
//initial
for (int i = 0; i < _samples; i++)
{
var value = profitAndLoss[i];
if (value >= 0)
avgGain += value;
else
avgLoss += value * -1; //here i multiply -1 so i only have positive values
}
avgGain /= _samples;
avgLoss /= _samples;
第3步。用从API获得的剩余值平滑平均值:
//smooth with given values
for (int i = _samples; i < profitAndLoss.Count; i++)
{
var value = profitAndLoss[i];
if (value >= 0)
{
avgGain = (avgGain * (_samples - 1) + value) / _samples;
avgLoss = (avgLoss * (_samples - 1)) / _samples;
}
else
{
value *= -1;
avgLoss = (avgLoss * (_samples - 1) + value) / _samples;
avgGain = (avgGain * (_samples - 1)) / _samples;
}
}
第4步。计算RSI的时间:
var rs = avgGain / avgLoss;
var rsi = 100 - (100 / (1 + rs));
这将为您提供RSI图表中与Kraken相同的值(+/- 0.05,具体取决于您的更新频率)
结果图片1
答案 3 :(得分:0)
您需要缓冲区来存储先前的值,换句话说,您需要全局变量,而不仅仅是函数(除非您正在为简单的指标(如 SMA)创建函数)。
关于详细的分步说明,我写了一篇很长的文章,你可以在这里查看: https://turmanauli.medium.com/a-step-by-step-guide-for-calculating-reliable-rsi-values-programmatically-a6a604a06b77
在你下面看到一个最终类 (C#),它经过测试和验证,以 100% 的准确度生成 RSI 值:
using System;
using System.Data;
using System.Globalization;
namespace YourNameSpace
{
class PriceEngine
{
public static DataTable data;
public static double[] positiveChanges;
public static double[] negativeChanges;
public static double[] averageGain;
public static double[] averageLoss;
public static double[] rsi;
public static double CalculateDifference(double current_price, double previous_price)
{
return current_price - previous_price;
}
public static double CalculatePositiveChange(double difference)
{
return difference > 0 ? difference : 0;
}
public static double CalculateNegativeChange(double difference)
{
return difference < 0 ? difference * -1 : 0;
}
public static void CalculateRSI(int rsi_period, int price_index = 5)
{
for(int i = 0; i < PriceEngine.data.Rows.Count; i++)
{
double current_difference = 0.0;
if (i > 0)
{
double previous_close = Convert.ToDouble(PriceEngine.data.Rows[i-1].Field<string>(price_index));
double current_close = Convert.ToDouble(PriceEngine.data.Rows[i].Field<string>(price_index));
current_difference = CalculateDifference(current_close, previous_close);
}
PriceEngine.positiveChanges[i] = CalculatePositiveChange(current_difference);
PriceEngine.negativeChanges[i] = CalculateNegativeChange(current_difference);
if(i == Math.Max(1,rsi_period))
{
double gain_sum = 0.0;
double loss_sum = 0.0;
for(int x = Math.Max(1,rsi_period); x > 0; x--)
{
gain_sum += PriceEngine.positiveChanges[x];
loss_sum += PriceEngine.negativeChanges[x];
}
PriceEngine.averageGain[i] = gain_sum / Math.Max(1,rsi_period);
PriceEngine.averageLoss[i] = loss_sum / Math.Max(1,rsi_period);
}else if (i > Math.Max(1,rsi_period))
{
PriceEngine.averageGain[i] = ( PriceEngine.averageGain[i-1]*(rsi_period-1) + PriceEngine.positiveChanges[i]) / Math.Max(1, rsi_period);
PriceEngine.averageLoss[i] = ( PriceEngine.averageLoss[i-1]*(rsi_period-1) + PriceEngine.negativeChanges[i]) / Math.Max(1, rsi_period);
PriceEngine.rsi[i] = PriceEngine.averageLoss[i] == 0 ? 100 : PriceEngine.averageGain[i] == 0 ? 0 : Math.Round(100 - (100 / (1 + PriceEngine.averageGain[i] / PriceEngine.averageLoss[i])), 5);
}
}
}
public static void Launch()
{
PriceEngine.data = new DataTable();
//load {date, time, open, high, low, close} values in PriceEngine.data (6th column (index #5) = close price) here
positiveChanges = new double[PriceEngine.data.Rows.Count];
negativeChanges = new double[PriceEngine.data.Rows.Count];
averageGain = new double[PriceEngine.data.Rows.Count];
averageLoss = new double[PriceEngine.data.Rows.Count];
rsi = new double[PriceEngine.data.Rows.Count];
CalculateRSI(14);
}
}
}