RSI (Relative Strenghth Index) formula calculation

TeeChart for Microsoft Visual Studio .NET, Xamarin Studio (Android, iOS & Forms) & Monodevelop.
Post Reply
Quant
Advanced
Posts: 142
Joined: Tue Dec 30, 2014 12:00 am

RSI (Relative Strenghth Index) formula calculation

Post by Quant » Tue Jun 16, 2015 10:33 am

Hi Steema,

Based on our comparison study we found calculation mismatch in RSI Financial Function of TeeChart. Please have a look on attched file and kindly let us know resolution and reason of mismatch.

It would be a great feature, if RSI has following properties separately:
1] Series
2] Values like (Close, High, Low, Open)
3] Period
RSI.zip
(7.12 KiB) Downloaded 890 times
Please share us the formula of Weighted Moving Average (WMA) that Teechart is currently using for calculation.

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: RSI (Relative Strenghth Index) formula calculation

Post by Christopher » Tue Jun 16, 2015 1:56 pm

Quant wrote:Based on our comparison study we found calculation mismatch in RSI Financial Function of TeeChart. Please have a look on attched file and kindly let us know resolution and reason of mismatch.
The following code:

Code: Select all

    private void InitializeChart()
    {
      tChart1.Aspect.View3D = false;

      Candle candle = new Candle(tChart1.Chart);

      candle.Add(DateTime.Parse("07/11/1994"), 1283, 1283, 1283, 1283);
      candle.Add(DateTime.Parse("08/11/1994"), 1281, 1281, 1281, 1281);
      candle.Add(DateTime.Parse("09/11/1994"), 1259, 1259, 1259, 1259);
      candle.Add(DateTime.Parse("10/11/1994"), 1241, 1241, 1241, 1241);
      candle.Add(DateTime.Parse("11/11/1994"), 1223, 1223, 1223, 1223);
      candle.Add(DateTime.Parse("14/11/1994"), 1210, 1210, 1210, 1210);
      candle.Add(DateTime.Parse("15/11/1994"), 1208, 1208, 1208, 1208);
      candle.Add(DateTime.Parse("16/11/1994"), 1232, 1232, 1232, 1232);
      candle.Add(DateTime.Parse("17/11/1994"), 1247, 1247, 1247, 1247);
      candle.Add(DateTime.Parse("21/11/1994"), 1248, 1248, 1248, 1248);
      candle.Add(DateTime.Parse("22/11/1994"), 1236, 1236, 1236, 1236);
      candle.Add(DateTime.Parse("23/11/1994"), 1221, 1221, 1221, 1221);
      candle.Add(DateTime.Parse("24/11/1994"), 1230, 1230, 1230, 1230);
      candle.Add(DateTime.Parse("25/11/1994"), 1246, 1246, 1246, 1246);
      candle.Add(DateTime.Parse("29/11/1994"), 1252, 1252, 1252, 1252);
      candle.Add(DateTime.Parse("30/11/1994"), 1246, 1246, 1246, 1246);
      candle.Add(DateTime.Parse("01/12/1994"), 1240, 1240, 1240, 1240);
      candle.Add(DateTime.Parse("02/12/1994"), 1233, 1233, 1233, 1233);
      candle.Add(DateTime.Parse("05/12/1994"), 1229, 1229, 1229, 1229);
      candle.Add(DateTime.Parse("06/12/1994"), 1215, 1215, 1215, 1215);
      candle.Add(DateTime.Parse("07/12/1994"), 1194, 1194, 1194, 1194);
      candle.Add(DateTime.Parse("08/12/1994"), 1177, 1177, 1177, 1177);
      candle.Add(DateTime.Parse("09/12/1994"), 1182, 1182, 1182, 1182);
      candle.Add(DateTime.Parse("12/12/1994"), 1153, 1153, 1153, 1153);
      candle.Add(DateTime.Parse("13/12/1994"), 1136, 1136, 1136, 1136);
      candle.Add(DateTime.Parse("14/12/1994"), 1147, 1147, 1147, 1147);
      candle.Add(DateTime.Parse("15/12/1994"), 1161, 1161, 1161, 1161);

      FastLine fast = new FastLine(tChart1.Chart);
      fast.VertAxis = VerticalAxis.Right;
      tChart1.Axes.Right.Grid.Visible = false;
      RSIFunction rsi = new RSIFunction(tChart1.Chart);
      rsi.Style = RSIStyle.Close;
      rsi.PeriodStyle = PeriodStyles.NumPoints;
      rsi.Period = 12;
      fast.Function = rsi;
      fast.DataSource = candle;
      fast.CheckDataSource();
    }

    private void button4_Click_1(object sender, EventArgs e)
    {
      Steema.TeeChart.Export.TextFormat text = tChart1.Export.Data.Text;

      text.IncludeHeader = true;
      text.IncludeIndex = true;
      text.IncludeLabels = true;
      text.IncludeSeriesTitle = true;
      text.Save(@"D:\tmp\testData.txt");
    }
Gives me the values in the attached file. I believe these to be correct, expected values.
RSI_2.zip
(5.62 KiB) Downloaded 908 times
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

Quant
Advanced
Posts: 142
Joined: Tue Dec 30, 2014 12:00 am

Re: RSI (Relative Strenghth Index) formula calculation

Post by Quant » Wed Jun 17, 2015 5:51 am

Dear Steema,

We checked your sample code with our sample values, but we still find value mismatch. FYI we have attached excel file with new values. Following is the source code we used:

Code: Select all

        public Form2()
        {
            InitializeComponent();
            InitializeChart();
        }

        private void InitializeChart()
        {
            tChart1.Aspect.View3D = false;

            Candle candle = new Candle(tChart1.Chart);

            candle.Add(DateTime.Parse("11/07/1994"), 1283, 1283, 1283, 1283);
            candle.Add(DateTime.Parse("11/08/1994"), 1281, 1281, 1281, 1281);
            candle.Add(DateTime.Parse("11/09/1994"), 1259, 1259, 1259, 1259);
            candle.Add(DateTime.Parse("11/10/1994"), 1241, 1241, 1241, 1241);
            candle.Add(DateTime.Parse("11/11/1994"), 1223, 1223, 1223, 1223);
            candle.Add(DateTime.Parse("11/14/1994"), 1210, 1210, 1210, 1210);
            candle.Add(DateTime.Parse("11/15/1994"), 1208, 1208, 1208, 1208);
            candle.Add(DateTime.Parse("11/16/1994"), 1232, 1232, 1232, 1232);
            candle.Add(DateTime.Parse("11/17/1994"), 1247, 1247, 1247, 1247);
            candle.Add(DateTime.Parse("11/21/1994"), 1248, 1248, 1248, 1248);
            candle.Add(DateTime.Parse("11/22/1994"), 1236, 1236, 1236, 1236);
            candle.Add(DateTime.Parse("11/23/1994"), 1221, 1221, 1221, 1221);
            candle.Add(DateTime.Parse("11/24/1994"), 1230, 1230, 1230, 1230);
            candle.Add(DateTime.Parse("11/25/1994"), 1246, 1246, 1246, 1246);
            candle.Add(DateTime.Parse("11/29/1994"), 1252, 1252, 1252, 1252);
            candle.Add(DateTime.Parse("11/30/1994"), 1246, 1246, 1246, 1246);
            candle.Add(DateTime.Parse("12/01/1994"), 1240, 1240, 1240, 1240);
            candle.Add(DateTime.Parse("12/02/1994"), 1233, 1233, 1233, 1233);
            candle.Add(DateTime.Parse("12/05/1994"), 1229, 1229, 1229, 1229);
            candle.Add(DateTime.Parse("12/06/1994"), 1215, 1215, 1215, 1215);
            candle.Add(DateTime.Parse("12/07/1994"), 1194, 1194, 1194, 1194);
            candle.Add(DateTime.Parse("12/08/1994"), 1177, 1177, 1177, 1177);
            candle.Add(DateTime.Parse("12/09/1994"), 1182, 1182, 1182, 1182);
            candle.Add(DateTime.Parse("12/12/1994"), 1153, 1153, 1153, 1153);
            candle.Add(DateTime.Parse("12/13/1994"), 1136, 1136, 1136, 1136);
            candle.Add(DateTime.Parse("12/14/1994"), 1147, 1147, 1147, 1147);
            candle.Add(DateTime.Parse("12/15/1994"), 1161, 1161, 1161, 1161);

            FastLine fast = new FastLine(tChart1.Chart);
            fast.VertAxis = VerticalAxis.Right;
            tChart1.Axes.Right.Grid.Visible = false;
            RSIFunction rsi = new RSIFunction(tChart1.Chart);
            rsi.Style = RSIStyle.Close;
            rsi.PeriodStyle = PeriodStyles.NumPoints;
            rsi.Period = 14;
            fast.Function = rsi;
            fast.DataSource = candle;
            fast.CheckDataSource();

            tChart1.MouseDoubleClick += new MouseEventHandler(tChart1_MouseDoubleClick);
        }

        void tChart1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            tChart1.ShowEditor();
        }

        private void button4_Click_1(object sender, EventArgs e)
        {
            Steema.TeeChart.Export.TextFormat text = tChart1.Export.Data.Text;

            text.IncludeHeader = true;
            text.IncludeIndex = true;
            text.IncludeLabels = true;
            text.IncludeSeriesTitle = true;
            text.Save(@"D:\tmp\testData.txt");
        }

Attachments
RSI2.zip
(10.95 KiB) Downloaded 822 times

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: RSI (Relative Strenghth Index) formula calculation

Post by Christopher » Wed Jun 17, 2015 10:57 am

Attached latest excel with TeeChart calculations in green, with the equivalent calculation in dark green.

As you can see, the difference is in the calculation of the averages. TeeChart calculates a correct Simple Moving Average, which is the average the RSI was originally designed to use, as you can read here. The calculation takes the previous n points and averages them. The calculation you use, on the other hand, does not do this. It takes the previous average, adds a single point to it, and recalculates, which does not give the same result.
RSI3.zip
(6.68 KiB) Downloaded 765 times
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

Quant
Advanced
Posts: 142
Joined: Tue Dec 30, 2014 12:00 am

Re: RSI (Relative Strenghth Index) formula calculation

Post by Quant » Wed Jun 17, 2015 12:13 pm

Dear Steema,

We used following excel sheet for RSI calculation :
http://stockcharts.com/education/indica ... is/RSI.xls

We are not saying that you have used errorneous formula for RSI Calculation, but its result is not expected as per our benchmark testing. We verified the values (computed using formula mentioned in above excel file) with other Financial Charting Software's values, and it matches perfectly. In previously attached excel files, we mentioned the benchmark values in a column named as "RSI Calculated from Other Software" which is taken from that financial charting software.

What we shared with you is verified from valid resources and most importantly it is currently expected by users. Because they gonna compare the same with other Financial Charting Software and if they find any major differences in those values or calculation, they definitely going to raise this issue.

So we would like to suggest to add new type of RSI calculation in TeeChart according to above excel formula.

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: RSI (Relative Strenghth Index) formula calculation

Post by Christopher » Wed Jun 17, 2015 12:32 pm

Quant wrote:So we would like to suggest to add new type of RSI calculation in TeeChart according to above excel formula.
Thank you for the suggestion.

TeeChart has tens of thousands of existing users, a proportion of whom will be already using the RSI function as it is - changing the function calculation would give these users unexpected results.

As I'm sure you understand, we at Steema prefer to use documented evidence of a function's algorithms, and you will also understand that the evidence you present in favour of your calculation is not clearly and transparently documented. The wikipedia article on RSI is quite clear, as I have already linked to here:

Code: Select all

If the last close is the same as the previous, both U and D are zero. The average U and D are calculated using an n-period exponential moving average (EMA) in AIQ's version of RSI. Wilder's original version uses an n-period simple moving average (SMA).[3]
There is no doubt that Steema's present RSI algorithm uses the clearly documented SMA, and as such is what would be expected by a client wishing to use Wilder's original RSI formulation. On the other hand, there is a case to be made to expand Steema's RSI function to allow for the use of an EMA as well as the existing SMA, and I have added this as an enhancement at this ticket.
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

Quant
Advanced
Posts: 142
Joined: Tue Dec 30, 2014 12:00 am

Re: RSI (Relative Strenghth Index) formula calculation

Post by Quant » Thu Jun 18, 2015 4:08 am

Dear Steema,

Thanks for adding this type of RSI Calculation as an enhancement to your TeeChart. But we need to implement this at our side ASAP, and any help to achieve this would be greatly appreciated, since it is urgently required by our users.

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: RSI (Relative Strenghth Index) formula calculation

Post by Christopher » Thu Jun 18, 2015 9:13 am

Quant wrote:Thanks for adding this type of RSI Calculation as an enhancement to your TeeChart. But we need to implement this at our side ASAP, and any help to achieve this would be greatly appreciated, since it is urgently required by our users.
There is nothing to stop you deriving your own classes and making all the necessary calculations you need. Here is an example of the classes I mean:

Code: Select all

  public class MyRSIFunction : RSIFunction
  {
    private RSIAverageType fAverageType;
    private Steema.TeeChart.Styles.Series iSeries;
    private ValueList Closes, Opens, Lows, Highs;
    private double seedAverageUp, seedAverageDown;
    private MyRSIStyle fStyle;
    public MyRSIFunction(Chart c) : base(c)
    {
      fAverageType = RSIAverageType.SMA;
    }

    public MyRSIFunction() : this(null)
    {

    }

    /// <summary>
    /// Sets the RSI function to use either Open or Close values.
    /// </summary>
    public new MyRSIStyle Style
    {
      get { return fStyle; }
      set
      {
        if (fStyle != value)
        {
          fStyle = value;
          this.Recalculate();
        }
      }
    }

    public override void AddPoints(Array source)
    {
      seedAverageUp = double.NaN;
      seedAverageDown = double.NaN;
      base.AddPoints(source);
    }

    private ValueList GetYValueList(Series series, string AListName)
    {
      AListName = AListName.ToUpper();
      for (int t = 2; t < series.ValuesLists.Count; t++)
        if (AListName == series.ValuesLists[t].Name.ToUpper())
          return series.ValuesLists[t];
      return series.YValues;
    }

    public override double Calculate(Series source, int first, int last)
    {
      if(AverageType == RSIAverageType.EMA)
      {
        int NumPoints;
        double tmpClose, Ups, Downs, result;

        if (iSeries != source)
        {
          Closes = GetYValueList(source, Texts.ValuesClose);
          Opens = GetYValueList(source, Texts.ValuesOpen);
          Lows = GetYValueList(source, Texts.ValuesLow);
          Highs = GetYValueList(source, Texts.ValuesHigh);
          iSeries = source;
        }

        NumPoints = (last - first) + 1;

        Ups = 0;
        Downs = 0;

        if (double.IsNaN(seedAverageDown) || double.IsNaN(seedAverageUp))
        {
          switch (this.Style)
          {
            case MyRSIStyle.OpenClose:
              for (int t = first; t <= last; ++t)
              {
                tmpClose = Closes[t];
                if (Opens[t] > tmpClose) Downs = Downs + tmpClose;
                else Ups = Ups + tmpClose;
              }
              break;
            case MyRSIStyle.Close:
              for (int t = first + 1; t <= last; ++t)
              {
                tmpClose = Closes[t] - Closes[t - 1];
                if (tmpClose < 0) Downs = Downs - tmpClose;
                else Ups = Ups + tmpClose;
              }
              break;
            case MyRSIStyle.Open:
              for (int t = first + 1; t <= last; ++t)
              {
                tmpClose = Opens[t] - Opens[t - 1];
                if (tmpClose < 0) Downs = Downs - tmpClose;
                else Ups = Ups + tmpClose;
              }
              break;
            case MyRSIStyle.High:
              for (int t = first + 1; t <= last; ++t)
              {
                tmpClose = Highs[t] - Highs[t - 1];
                if (tmpClose < 0) Downs = Downs - tmpClose;
                else Ups = Ups + tmpClose;
              }
              break;
            case MyRSIStyle.Low:
              for (int t = first + 1; t <= last; ++t)
              {
                tmpClose = Lows[t] - Lows[t - 1];
                if (tmpClose < 0) Downs = Downs - tmpClose;
                else Ups = Ups + tmpClose;
              }
              break;
          }

          Downs = Downs / (NumPoints - 1);
          Ups = Ups / (NumPoints - 1);

          seedAverageDown = Downs;
          seedAverageUp = Ups;
        }
        else
        {
          switch (this.Style)
          {
            case MyRSIStyle.OpenClose:
              tmpClose = Closes[last];
              if (Opens[last] > tmpClose) Downs = tmpClose;
              else Ups = tmpClose;
              break;
            case MyRSIStyle.Close:
              tmpClose = Closes[last] - Closes[last - 1];
              if (tmpClose < 0) Downs = Math.Abs(tmpClose);
              else Ups = tmpClose;
              break;
            case MyRSIStyle.Open:
              tmpClose = Opens[last] - Opens[last - 1];
              if (tmpClose < 0) Downs = Math.Abs(tmpClose);
              else Ups = tmpClose;
              break;
            case MyRSIStyle.High:
              tmpClose = Highs[last] - Highs[last - 1];
              if (tmpClose < 0) Downs = Math.Abs(tmpClose);
              else Ups = tmpClose;
              break;
            case MyRSIStyle.Low:
              tmpClose = Lows[last] - Lows[last - 1];
              if (tmpClose < 0) Downs = Math.Abs(tmpClose);
              else Ups = tmpClose;
              break;
          }

          seedAverageDown = ((seedAverageDown * (NumPoints - 1)) + Downs) / NumPoints;
          seedAverageUp = ((seedAverageUp * (NumPoints - 1)) + Ups) / NumPoints;
        }

        if (seedAverageDown != 0)
        {
          result = 100.0 - (100.0 / (1.0 + Math.Abs(seedAverageUp / seedAverageDown)));
          if (result < 0) result = 0;
          else
          if (result > 100) result = 100;
        }
        else result = 100;

        return result;
      }
      else
      {
        return base.Calculate(source, first, last);
      }
    }

    /// <summary>
    /// Sets the RSI function to use either SMA or EMA as its averaging algorithm.
    /// </summary>
#if DESIGNATTRIBUTES
    [DefaultValue(typeof(RSIAverageType), "SMA")]
#endif
#if STORE || WINDOWS_PHONE
    public new RSIAverageType AverageType
#else
    public RSIAverageType AverageType
#endif
    {
      get { return fAverageType; }
      set
      {
        if (fAverageType != value)
        {
          fAverageType = value;
          this.Recalculate();
        }
      }
    }

  }

  /// <summary>
  /// Used in see cref="RSIFunction.Style"/> property. 
  /// </summary>
  public enum MyRSIStyle
  {
    /// <summary>
    /// Uses Close values comparative to their respective Open Values.
    /// </summary>
    OpenClose,
    /// <summary>
    /// Uses Close values comparative to prior Close values.
    /// </summary>
    Close,
    /// <summary>
    /// Uses Open values comparative to prior Open values.
    /// </summary>
    Open,
    /// <summary>
    /// Uses High values comparative to prior High values.
    /// </summary>
    High,
    /// <summary>
    /// Uses Low values comparative to prior Low values.
    /// </summary>
    Low
  }

  /// <summary>
  /// Used in see cref="RSIFunction.Style"/> property. 
  /// </summary>
  public enum RSIAverageType
  {
    /// <summary>
    /// Simple Moving Average.
    /// </summary>
    SMA,
    /// <summary>
    /// Exponential Moving Average.
    /// </summary>
    EMA
  }
and this can be used:

Code: Select all

    private void InitializeChart()
    {
      tChart1.Aspect.View3D = false;

      Candle candle = new Candle(tChart1.Chart);

      candle.Add(DateTime.Parse("07/11/1994"), 1283, 1283, 1283, 1283);
      candle.Add(DateTime.Parse("08/11/1994"), 1281, 1281, 1281, 1281);
      candle.Add(DateTime.Parse("09/11/1994"), 1259, 1259, 1259, 1259);
      candle.Add(DateTime.Parse("10/11/1994"), 1241, 1241, 1241, 1241);
      candle.Add(DateTime.Parse("11/11/1994"), 1223, 1223, 1223, 1223);
      candle.Add(DateTime.Parse("14/11/1994"), 1210, 1210, 1210, 1210);
      candle.Add(DateTime.Parse("15/11/1994"), 1208, 1208, 1208, 1208);
      candle.Add(DateTime.Parse("16/11/1994"), 1232, 1232, 1232, 1232);
      candle.Add(DateTime.Parse("17/11/1994"), 1247, 1247, 1247, 1247);
      candle.Add(DateTime.Parse("21/11/1994"), 1248, 1248, 1248, 1248);
      candle.Add(DateTime.Parse("22/11/1994"), 1236, 1236, 1236, 1236);
      candle.Add(DateTime.Parse("23/11/1994"), 1221, 1221, 1221, 1221);
      candle.Add(DateTime.Parse("24/11/1994"), 1230, 1230, 1230, 1230);
      candle.Add(DateTime.Parse("25/11/1994"), 1246, 1246, 1246, 1246);
      candle.Add(DateTime.Parse("29/11/1994"), 1252, 1252, 1252, 1252);
      candle.Add(DateTime.Parse("30/11/1994"), 1246, 1246, 1246, 1246);
      candle.Add(DateTime.Parse("01/12/1994"), 1240, 1240, 1240, 1240);
      candle.Add(DateTime.Parse("02/12/1994"), 1233, 1233, 1233, 1233);
      candle.Add(DateTime.Parse("05/12/1994"), 1229, 1229, 1229, 1229);
      candle.Add(DateTime.Parse("06/12/1994"), 1215, 1215, 1215, 1215);
      candle.Add(DateTime.Parse("07/12/1994"), 1194, 1194, 1194, 1194);
      candle.Add(DateTime.Parse("08/12/1994"), 1177, 1177, 1177, 1177);
      candle.Add(DateTime.Parse("09/12/1994"), 1182, 1182, 1182, 1182);
      candle.Add(DateTime.Parse("12/12/1994"), 1153, 1153, 1153, 1153);
      candle.Add(DateTime.Parse("13/12/1994"), 1136, 1136, 1136, 1136);
      candle.Add(DateTime.Parse("14/12/1994"), 1147, 1147, 1147, 1147);
      candle.Add(DateTime.Parse("15/12/1994"), 1161, 1161, 1161, 1161);

      FastLine fast = new FastLine(tChart1.Chart);
      fast.VertAxis = VerticalAxis.Right;
      tChart1.Axes.Right.Grid.Visible = false;
      MyRSIFunction rsi = new MyRSIFunction(tChart1.Chart);
      rsi.Style = MyRSIStyle.Close;
      rsi.AverageType = RSIAverageType.EMA;
      rsi.PeriodStyle = PeriodStyles.NumPoints;
      rsi.Period = 14;
      fast.Function = rsi;
      fast.DataSource = candle;
      fast.CheckDataSource();
    }

    private void button4_Click(object sender, EventArgs e)
    {
      Steema.TeeChart.Export.TextFormat text = tChart1.Export.Data.Text;

      text.IncludeHeader = true;
      text.IncludeIndex = true;
      text.IncludeLabels = true;
      text.IncludeSeriesTitle = true;
      text.Save(@"C:\tmp\testData.txt");
    }
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

Post Reply