我很难得到一个平滑的RSI。下图来自freestockcharts.com。计算使用此代码。
public static double CalculateRsi(IEnumerable<double> closePrices)
{
var prices = closePrices as double[] ?? closePrices.ToArray();
double sumGain = 0;
double sumLoss = 0;
for (int i = 1; i < prices.Length; i++)
{
var difference = prices[i] - prices[i - 1];
if (difference >= 0)
{
sumGain += difference;
}
else
{
sumLoss -= difference;
}
}
if (sumGain == 0) return 0;
if (Math.Abs(sumLoss) < Tolerance) return 100;
var relativeStrength = sumGain / sumLoss;
return 100.0 - (100.0 / (1 + relativeStrength));
}https://stackoverflow.com/questions/...th-index-using-some-programming-language-js-c
这似乎是没有平滑的纯RSI。如何计算平滑的RSI?我尝试更改它以适应这两个站点的定义,但是输出不正确。它几乎是不平滑的。
(我没有足够的代表来发布链接)
tc2000 -> Indicators -> RSI_and_Wilder_s_RSI (Wilder's smoothing = Previous MA value + (1/n periods * (Close - Previous MA)))
priceactionlab -> wilders-cutlers-and-harris-relative-strength-index (RS = EMA(Gain(n), n)/EMA(Loss(n), n))有人真的能用一些样本数据进行计算吗?

发布于 2018-04-27 04:54:53
为了计算RSI,您需要一个句号来计算它。As noted on Wikipedia, 14 is used quite often.
因此,计算步骤如下:
周期1- 13,RSI =0
第14期:
AverageGain = TotalGain / PeriodCount;
AverageLoss = TotalLoss / PeriodCount;
RS = AverageGain / AverageLoss;
RSI = 100 - 100 / (1 + RS);第15期-至第(N)期:
if (Period(N)Change > 0
AverageGain(N) = ((AverageGain(N - 1) * (PeriodCount - 1)) + Period(N)Change) / PeriodCount;
else
AverageGain(N) = (AverageGain(N - 1) * (PeriodCount - 1)) / PeriodCount;
if (this.Change < 0)
AverageLoss(N) = ((AverageLoss(N - 1) * (PeriodCount - 1)) + Math.Abs(Period(N)Change)) / PeriodCount;
else
AverageLoss(N) = (AverageLoss(N - 1) * (PeriodCount - 1)) / PeriodCount;
RS = AverageGain / AverageLoss;
RSI = 100 - (100 / (1 + RS));此后,为了平滑这些值,您需要对RSI值应用特定时间段的移动平均值。为此,请从最后一个索引到第一个索引遍历RSI值,并根据前面的x个平滑周期计算当前时段的平均值。
完成后,只需反转值列表即可获得预期的顺序:
List<double> SmoothedRSI(IEnumerable<double> rsiValues, int smoothingPeriod)
{
if (rsiValues.Count() <= smoothingPeriod)
throw new Exception("Smoothing period too large or too few RSI values passed.");
List<double> results = new List<double>();
List<double> reversedRSIValues = rsiValues.Reverse().ToList();
for (int i = 1; i < reversedRSIValues.Count() - smoothingPeriod - 1; i++)
results.Add(reversedRSIValues.Subset(i, i + smoothingPeriod).Average());
return results.Reverse().ToList();
}子集方法只是一个简单的扩展方法,如下所示:
public static List<double> Subset(this List<double> values, int start, int end)
{
List<double> results = new List<double>();
for (int i = start; i <= end; i++)
results.Add(values[i]);
return results;
}免责声明,我没有测试代码,但它应该让您了解平滑是如何应用的。
发布于 2021-03-17 07:49:00
如果没有缓冲区/全局变量来存储数据,就无法获得精确值。
这是一个平滑的指示器,这意味着它不只使用14个条块,而是所有的条块:这是一篇循序渐进的文章,如果价格和可用条块的数量相同,则工作和验证的源代码将生成完全相同的值(当然,您只需要从源中加载价格数据):
测试和验证:
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);
}
}
}有关详细的逐步说明,我写了一篇很长的文章,您可以在这里查看它:https://turmanauli.medium.com/a-step-by-step-guide-for-calculating-reliable-rsi-values-programmatically-a6a604a06b77
P.S.函数只适用于简单指标(简单移动平均),甚至指数移动平均,平均真实范围绝对需要全局变量来存储先前的值。
https://stackoverflow.com/questions/38481354
复制相似问题