Do you want to get informed about new posts via Email?

RSI.Series ignores FirstValidValue

Author: kribel

Creation Date: 8/11/2015 6:47 AM

Hi there!

I discovered that when giving a DataSeries to RSI.Series() prefilled with zeros before actual data and the FirstValidValue set to the correct value, the RIS.Series() indicator starts calculating with the prefilled zeros. That leads to incorrect RSI values.

__Here is an example how to reproduce:__

01. Open historical data of the FB symbol

02. Click on Indicators

03. Choose RSI from standard indicators

04. Set look back period to 7 bars

05. Click OK

06. Copy and Save the price data from the chart

07. Create a new strategy from code

08. Set data range to 01.01.2008 - 31.12.2014

09. Load FB historical data with Bars fbBars = GetExternalSymbol("FB", true);

10. Calculate RSI on fbBars with DataSeries fbRSI = RSI.Series(fbBars.Close, 7);

11. Plot fbRSI

12. Run the strategy on AAPL historical data

13. Copy the price data from the chart and save it

Now compare the RSI results from 6 and 13.

I can see that all the way from 01.01.2008 until 17.05.2012 the fbBars were filled with zeros. The RSI value is during this period for some reason 50. Then is obviously starts to calculate with real data based on previous data and the results are not usable.

In any case if we compare the the results from step 6 with the results from step 13 for the date 30.05.2012 we get the following:

Step 6, RSI = 14.297

Step 13, RSI = 66.416

This is a huge difference.

Is it possible to make RSI.Series() calculate from the FirstValidValue instead from bar 0?

Cheers

Konstantin

I discovered that when giving a DataSeries to RSI.Series() prefilled with zeros before actual data and the FirstValidValue set to the correct value, the RIS.Series() indicator starts calculating with the prefilled zeros. That leads to incorrect RSI values.

01. Open historical data of the FB symbol

02. Click on Indicators

03. Choose RSI from standard indicators

04. Set look back period to 7 bars

05. Click OK

06. Copy and Save the price data from the chart

07. Create a new strategy from code

08. Set data range to 01.01.2008 - 31.12.2014

09. Load FB historical data with Bars fbBars = GetExternalSymbol("FB", true);

10. Calculate RSI on fbBars with DataSeries fbRSI = RSI.Series(fbBars.Close, 7);

11. Plot fbRSI

12. Run the strategy on AAPL historical data

13. Copy the price data from the chart and save it

Now compare the RSI results from 6 and 13.

I can see that all the way from 01.01.2008 until 17.05.2012 the fbBars were filled with zeros. The RSI value is during this period for some reason 50. Then is obviously starts to calculate with real data based on previous data and the results are not usable.

In any case if we compare the the results from step 6 with the results from step 13 for the date 30.05.2012 we get the following:

Step 6, RSI = 14.297

Step 13, RSI = 66.416

This is a huge difference.

Is it possible to make RSI.Series() calculate from the FirstValidValue instead from bar 0?

Cheers

Konstantin

Hi Konstantin,

RSI is an unstable indicator. You should not rely on Facebook's RSI value on May 30, 2012 because its IPO took place on May 18, 2012 only. That's just 7 bars of Daily data whereas a 7-period RSI requires at least 21 bars of data to begin stabilizing. In other words,*middle to late June 2012* is the earliest date when you can start looking at FB's RSI values which would start making sense. Please review the WealthScript Programming Guide > Indicators > *Stability of Indicators* for a complete explanation.

P.S. While I'm at it, the (rather) new addition to Community Components called GetAllDataForSymbol can be helpful in related cases of building indicators using external symbol's data.

QUOTE:

In any case if we compare the the results from step 6 with the results from step 13 for the date 30.05.2012 we get the following:

RSI is an unstable indicator. You should not rely on Facebook's RSI value on May 30, 2012 because its IPO took place on May 18, 2012 only. That's just 7 bars of Daily data whereas a 7-period RSI requires at least 21 bars of data to begin stabilizing. In other words,

P.S. While I'm at it, the (rather) new addition to Community Components called GetAllDataForSymbol can be helpful in related cases of building indicators using external symbol's data.

Hi Eugene,

I can see your point. The question is rather why the RSI calculates some values before the FirstValidValue? Every RSI value before that is 50, which is simply incorrect. I would expect there zeros.

Does it mean you are changing the RSI indicator to start the calculation on the FirstValidValue?

P.S.:

I will have a look at GetAllDataForSymbol.

I can see your point. The question is rather why the RSI calculates some values before the FirstValidValue? Every RSI value before that is 50, which is simply incorrect. I would expect there zeros.

QUOTE:

P.S. While I'm at it...

Does it mean you are changing the RSI indicator to start the calculation on the FirstValidValue?

P.S.:

I will have a look at GetAllDataForSymbol.

QUOTE:

Does it mean you are changing the RSI indicator to start the calculation on the FirstValidValue?

Oh no. We (MS123 LLC) are not permitted to do that to a built-in

QUOTE:

Is it possible to make RSI.Series() calculate from the FirstValidValue instead from bar 0?

Having looked into the RSI code, I can not confirm the issue.

Hi Eugene,

this is not the point. The point is, that if I synchronize FB to AAPL, the Synchronize() method prefills fbBars with zeros and sets FirstValidValue and FirstActualBar accordingly. So far everything is fine.

As soon as I pass fbBars.Close to the RSI indicator it calculates the RSI from bar 0 to the end. I expect it to calculate from FirstValidValue.

Keeping that in mind and looking at the RSI formula here is my understanding of what happens.

-> RSI Formula = 100 - 100/(1 + RS) --> RS = AverageUps/AverageDowns

Now because of the prefilled zeros RS ends up being 0/0. That is a division by zero! It seems to me that the CPU treats this special case of division by zero different from everything else (where the numerator is larger than 0) and calculates 1. This results in the RSI formula being = 100 - 100/(1+1) = 50.

End this is not the end of the story. As soon as it gets to the real data it starts to calculate some with valid numbers, but because of the 50s in the prefilled data the RSI value at the beginning of the real data is simply invalid.

Is this somehow understandable?

QUOTE:

If the starting value is 50, then I'm sure this is required by the algorithm's implementation. In your script, you should be able to handle that by treating fbBars.FirstActualBar accordingly i.e. to not process the FB RSI before bar > fbBars.FirstActualBar.

this is not the point. The point is, that if I synchronize FB to AAPL, the Synchronize() method prefills fbBars with zeros and sets FirstValidValue and FirstActualBar accordingly. So far everything is fine.

As soon as I pass fbBars.Close to the RSI indicator it calculates the RSI from bar 0 to the end. I expect it to calculate from FirstValidValue.

Keeping that in mind and looking at the RSI formula here is my understanding of what happens.

-> RSI Formula = 100 - 100/(1 + RS) --> RS = AverageUps/AverageDowns

Now because of the prefilled zeros RS ends up being 0/0. That is a division by zero! It seems to me that the CPU treats this special case of division by zero different from everything else (where the numerator is larger than 0) and calculates 1. This results in the RSI formula being = 100 - 100/(1+1) = 50.

End this is not the end of the story. As soon as it gets to the real data it starts to calculate some with valid numbers, but because of the 50s in the prefilled data the RSI value at the beginning of the real data is simply invalid.

Is this somehow understandable?

Hi Konstantin,

Yes, this makes sense in general with one exception. It's not the CPU but the RS in RSI itself appears to be programmed to start with 1 when the divisor (AverageDowns) is less than 0.

By the time indicator stabilizes, the effect of the 50s*almost* goes off. Nevertheless, you can create an indicator from the secondary symbol's (FB) raw DataSeries and defer synchronization:

As you see, this time fbRSI starts with 0s rather than 50s. Hope this helps.

Yes, this makes sense in general with one exception. It's not the CPU but the RS in RSI itself appears to be programmed to start with 1 when the divisor (AverageDowns) is less than 0.

By the time indicator stabilizes, the effect of the 50s

CODE:

Please log in to see this code.

As you see, this time fbRSI starts with 0s rather than 50s. Hope this helps.