Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# RSI与Wilder';s-RSI计算问题_C#_Algorithm_Technical Indicator - Fatal编程技术网

C# RSI与Wilder';s-RSI计算问题

C# RSI与Wilder';s-RSI计算问题,c#,algorithm,technical-indicator,C#,Algorithm,Technical Indicator,我很难得到平滑的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

我很难得到平滑的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));
}
有人能用一些样本数据进行计算吗


为了计算RSI,您需要一个周期来计算RSI

因此,计算步骤如下:

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;
}
周期1-13,RSI=0

第14期:

AverageGain = TotalGain / PeriodCount;
AverageLoss = TotalLoss / PeriodCount;
RS = AverageGain / AverageLoss;
RSI = 100 - 100 / (1 + RS);
期间15-至期间(N):

if(时段(N)变化>0
AverageGain(N)=((AverageGain(N-1)*(PeriodCount-1))+周期(N)变化)/周期计数;
其他的
AverageGain(N)=(AverageGain(N-1)*(PeriodCount-1))/PeriodCount;
如果(此变化<0)
AverageLoss(N)=((AverageLoss(N-1)*(PeriodCount-1))+Math.Abs(Period(N)Change))/PeriodCount;
其他的
AverageLoss(N)=(AverageLoss(N-1)*(PeriodCount-1))/PeriodCount;
RS=平均收益/平均损失;
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();
}
List smoothDRSI(IEnumerable值,int smoothingPeriod)
{

如果(rsiValues.Count()没有缓冲区/全局变量来存储数据,则无法获得准确的值

这是一个平滑的指示器,意味着它不仅使用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);
          }
          
      }
  }
使用系统;
使用系统数据;
利用制度全球化;
名称空间YourNameSpace
{
类价格引擎
{
公共静态数据表数据;
公共静态双[]正变化;
公共静态双[]负变化;
公共静态双[]平均增益;
公共静态双[]平均损失;
公共静态双[]rsi;
公共静态双重计算差异(双重当前价格,双重先前价格)
{
返回当前价格-上一个价格;
}
公共静态双计算位置更改(双差)
{
返回差>0?差:0;
}
公共静态双计算gativeChange(双差)
{
返回差<0?差*-1:0;
}
公共静态无效计算器(周期内,价格指数=5)
{
对于(int i=0;i0)
{
double previous_close=Convert.ToDouble(PriceEngine.data.Rows[i-1]。字段(price_index));
double current_close=Convert.ToDouble(PriceEngine.data.Rows[i].字段(price_index));
当前差距=计算差距(当前差距、上一差距);
}
PriceEngine.positiveChanges[i]=计算位置变化(当前差值);
PriceEngine.negativeChanges[i]=计算出的负变化(当前值之差);
如果(i==数学最大值(1,rsi_周期))
{
双增益_和=0.0;
双损耗之和=0.0;
对于(int x=Math.Max(1,rsi_周期);x>0;x--)
{
增益_和+=价格引擎。正变化[x];
损失总和+=价格引擎。负变化[x];
}
PriceEngine.averageGain[i]=增益总和/数学最大值(1,rsi周期);
PriceEngine.averageLoss[i]=损失总和/数学最大值(1,rsi周期);
}否则如果(i>数学最大值(1,rsi_周期))
{
PriceEngine.averageGain[i]=(PriceEngine.averageGain[i-1]*(rsi_时段-1)+PriceEngine.positiveChanges[i])/Math.Max(1,rsi_时段);
PriceEngine.averageLoss[i]=(PriceEngine.averageLoss[i-1]*(rsi_期-1)+PriceEngine.negativeChanges[i])/Math.Max(1,rsi_期);
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);
}
}
}
公共静态无效启动()
{
PriceEngine.data=新数据表();
//在PriceEngine.data(第6列(索引#5)=收盘价)中加载{date,time,open,high,low,close}值
positiveChanges=newdouble[PriceEngine.data.Rows.Count];
negativeChanges=新的双精度[PriceEngine.data.Rows.Count];
averageGain=new double[PriceEngine.data.Rows.Count];
averageLoss=新的双精度[PriceEngine.data.Rows.Count];
rsi=newdouble[PriceEngine.data.Rows.Count];
计算器(14);
}
}
}
关于详细的分步说明,我写了一篇长篇文章,您可以在这里查看:


p.S.函数仅适用于简单指标(简单移动平均线),即使是指数移动平均值,平均真实范围也绝对需要全局变量来存储以前的值。

此答案没有解决问题中的Wilders平滑计算问题。@DonF-请查看更新的答案。我没有测试它的准确性,但它应该能让您了解平滑是通过使用x个周期的移动平均值。请停止发布
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;
}
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);
          }
          
      }
  }