RSI.Series ignores FirstValidValue
Author: kribel
Creation Date: 8/11/2015 6:47 AM
profile picture

kribel

#1
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
profile picture

Eugene

#2
Hi Konstantin,

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, 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.
profile picture

kribel

#3
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.

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.
profile picture

Eugene

#4
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 standard indicator. Changing one requires adding a formal issue (bug report) to Fidelity's bug tracker, prioritizing (or rejecting) it by Fidelity in a team review at some future point, assigning resources, ... you get the picture. At this time I do not admit that any issue exists.

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. PrintDebug(fbBars.FirstValidValue) correctly reports the value of 7. Obviously, synchronization to the primary symbol has to take place since FB usually has less bars than symbols with a much longer history of trading like AAPL. 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.
profile picture

kribel

#5
Hi Eugene,

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?
profile picture

Eugene

#6
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:

CODE:
Please log in to see this code.


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

kribel

#7
Hi Eugene!

Thanks for your idea! I will have a look at that. It looks promising.