Hi,
I found out about 2 weeks ago that EMA calculations on Quantopian are markedly different than those on other trading platforms. At first, I thought it was because I am new to Quantopian. I might have missed something in my code. So, I checked my code again, but my code looks right. Then, I thought it could be talib. I ported MultiCharts EMA to Quantopian to see if that was the case. talib.EMA and the ported MultiCharts EMA calculations do match. So, there is nothing wrong with talib after all. I compared Quantopian data with Yahoo EOD data that I use on MultiCharts. They are both very similar. At this point, I have reasons to believe that there could be a bug in Quantopian backtesting engine or calculation.
Here is the talib.EMA code:
"""
Quantopian EMA calculation is markedly different from other EMA implementations (MultiCharts, TradingView, OptionsXpress, Yahoo, etc.).
"""
import talib
def initialize(context):
context.bar_interval = '1d'
context.bar_count = 120
context.slow_ema_length = 22
context.fast_ema_length = 12
context.spy = sid(8554)
def before_trading_start(context, data):
test_function(context, data)
def test_function(context, data):
slow_ema = talib.EMA(data.history(context.spy, 'high', context.bar_count, context.bar_interval), timeperiod = context.slow_ema_length)
fast_ema = talib.EMA(data.history(context.spy, 'high', context.bar_count, context.bar_interval), timeperiod = context.fast_ema_length)
trend_is_down = []
i = 0
while i < context.bar_count:
if fast_ema[i] < slow_ema[i]:
trend_is_down.append(True)
else:
trend_is_down.append(False)
i += 1
print slow_ema[context.bar_count - 10:]
print fast_ema[context.bar_count - 10:]
print trend_is_down[context.bar_count - 10:]
Here is the ported MultiCharts EMA code:
"""
MultiCharts EMA calculation test.
"""
def initialize(context):
context.bar_interval = '1d'
context.bar_count = 120
context.slow_ema_length = 22
context.fast_ema_length = 12
context.spy = sid(8554)
def before_trading_start(context, data):
test_function(context, data)
def test_function(context, data):
slow_ema = EMA(data.history(context.spy, 'high', context.bar_count, context.bar_interval), context.slow_ema_length)
fast_ema = EMA(data.history(context.spy, 'high', context.bar_count, context.bar_interval), context.fast_ema_length)
trend_is_down = []
for i in range(context.bar_count):
if fast_ema[i] < slow_ema[i]:
trend_is_down.append(True)
else:
trend_is_down.append(False)
print slow_ema[context.bar_count - 10:]
print fast_ema[context.bar_count - 10:]
print trend_is_down[context.bar_count - 10:]
def EMA(price, length):
"""
MultiCharts EMA implementation.
"""
var0 = 2.0 / (length + 1)
ema = 0.0
ema_list = []
for i in range(len(price)):
if i == 0:
ema = price[i]
ema_list.append(ema)
else:
ema = ema + var0 * (price[i] - ema)
ema_list.append(ema)
return ema_list
If you build and run them on 2016-10-07 to 2016-10-10, they should have produced lists consisting all True values like other trading or charting platforms (MultiCharts, TradingView, OptionsXpress, Yahoo, etc.). But, that is not the case. You can change 'high' to 'close', it does not matter at all.
Can the Quantopian community validate my findings? I would also appreciate if you could check the following talib indicators: PLUS_DI, MINUS_DI, SAR and BBANDS calculations on Quantopian and compare them on other trading platforms as well. If something as simple as EMA is different, other more complex indicators can be different as well. If you think the difference is caused by Quantopian's fixed trailing data, I can tell you that MultiCharts uses the same fixed trailing data. This post clearly explains that given enough fixed trailing data, the difference in trailing data will not matter at all.
There are also other posts that tried to highlight this issue using other indicators: this and this. I think it is best to address this issue right now rather than later. This could be a big bug not yet discovered. I hate to see this issue blows up big time in the future. Can Quantopian validate my findings as well?
Thanks,
Hengki