Back

McClellan Oscillator - An attempt to recreate NYSE

So, i have been trying to code mcclellan oscillator in quantconnect. Here is what the formula looks like, but i dont know why does quant connect show discrepancy in data. Is it that i can intrepreting advancing and declining stocks incorrect?

In my initialization section:

if MO_QC500:
self.SetUniverseSelection(QC500UniverseSelectionModel())
else:
self.AddUniverse(self.CoarseSelectionFunction,self.FineSelectionFunction)

I made the following code on OnData section.

if self.Time.microsecond == 0 and self.Time.second == 0:
# Update McClellan Oscillator
self.OnDataMO(slice)
def OnDataMO(self, slice):
"""Event handler for new McClellan Oscillator data."""
# Loop through universe and count advances/declines
up = 0
down = 0

# Loop through all stocks in universe
for stock in slice.Keys:
# Use try/except block to handle possible future data in slice
try:
if slice.Bars[stock].Close > slice.Bars[stock].Open:
up += 1
elif slice.Bars[stock].Close < slice.Bars[stock].Open:
down += 1
else:
up += .5
down += .5

# if self.Time.microsecond == 0 and self.Time.minute == 0 and 'AAPL' in str(stock):
# self.Debug('{} {} O:{} C:{} up:{} down:{}'.format(str(self.Time),str(stock),slice.Bars[stock].Open,slice.Bars[stock].Close,up,down))

except:
continue

# Check for invalid calculation. When writing this comment, each minute would contain
# at least 490 stocks. However, if the market does not produce an uptick or downtick
# we would have to terminate MO calculation.
if up + down < 10:
#self.Log('invalid MO calculation')
return

# Calculate if valid calculation
elif up != 0 or down != 0:
# Calculate ad and append it to list
net_advances = up-down

The only reason i did add .5 to unchanged tick stocks is to test different concepts downstream. Then i calculated EMA 19 and EMA 39 - something like as follows:

if self.ad_fast_ema:
prev_ema = self.ad_fast_ema
multiplier = 2.0 / (AD_FAST + 1)
self.ad_fast_ema = (net_advances - prev_ema) * multiplier + prev_ema
# Check for enough data for first calculation
elif len(self.ad_list) >= AD_FAST:
self.ad_fast_ema = self.ad_list[-1] / AD_FAST

The part i am questioning is up ticks vs down ticks calculation.

I have been comparing upticks vs downticks with TOS,QC500 and QCNYSE.  Here is Advance Decline [ $ADVN ] $DECN in TOS, 1 min data from 26th of July.

TOSTOS
Advances Declines Net Advances 19-day EMA 39-day EMA McClellan Oscillator Excel Calculation TOS Actual Values
1 1649 583 1066
2 1679 621 1058
3 1721 638 1083
4 1707 703 1004
5 1730 721 1009
6 1713 778 935
7 1693 813 880
8 1667 854 813
9 1598 928 670
10 1596 935 661
11 1647 889 758
12 1699 845 854
13 1729 823 906
14 1747 817 930
15 1718 852 866
16 1674 903 771
17 1641 934 707
18 1672 909 763
19 1690 896 794 870
20 1708 882 826 866
21 1732 870 862 865
22 1772 842 930 872
23 1793 827 966 881
24 1810 815 995 892
25 1811 813 998 903
26 1790 836 954 908
27 1781 847 934 911
28 1781 847 934 913
29 1767 871 896 911
30 1777 863 914 912
31 1761 885 876 908
32 1774 885 889 906
33 1742 924 818 897
34 1714 944 770 885
35 1737 919 818 878
36 1733 920 813 871
37 1713 961 752 859
38 1711 960 751 849
39 1722 947 775 841 872 -30 -43
40 1721 951 770 834 867 -33 -41

 


Each entries correspond from 9:30 AM EST Market Open, 1 minute data.In QC however, i am seeing bunch of stocks with no change in ticks.Here is what QC NYSE version looks like when .5 is added to advance and declines for unchanged issues: QC NYSE
Advances Declines Net Advances 19-day EMA 39-day EMA McClellan Oscillator
1 1165 1102 63
2 1151.5 1144.5 7
3 1177.5 1137.5 40
4 1158 1181 -23
5 1197 1155 42
6 1079 1294 -215
7 1208 1169 39
8 998.5 1379.5 -381
9 933.5 1445.5 -512
10 1267 1116 151
11 1426 959 467
12 1278.5 1111.5 167
13 1253.5 1136.5 117
14 1178 1212 -34
15 976 1416 -440
16 985.5 1408.5 -423
17 1114 1282 -168
18 1410 990 420
19 1240 1161 79 -32
20 1208.5 1192.5 16 -27
21 1363 1039 324 8
22 1356.5 1045.5 311 38
23 1278 1125 153 50
24 1250.5 1153.5 97 55
25 1187.5 1216.5 -29 46
26 1088 1317 -229 19
27 1151 1254 -103 7
28 1147 1259 -112 -5
29 1091.5 1315.5 -224 -27
30 1265 1143 122 -12
31 1114 1295 -181 -29
32 1269.5 1140.5 129 -13
33 1019.5 1391.5 -372 -49
34 1147 1264 -117 -56
35 1266 1145 121 -38
36 1229.5 1181.5 48 -30
37 1042.5 1369.5 -327 -59
38 1215 1197 18 -52
39 1166.5 1245.5 -79 -54 -27 -28
40 1283.5 1128.5 155 -33 -18 -16
41 1342 1070 272 -3 -3 0
42 1163.5 1248.5 -85 -11 -7 -4

It is my understanding that slice.Bars[stock].Close > slice.Bars[stock].Open captures close and open prices 

for the bar. Could this be a data related issue or the way i intrepret slice.Bars object?

self.UniverseSettings.Resolution = Resolution.Minute is what i have set in program. 

Any help would be greatly appreciated.        
Update Backtest







0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


I was able to I believe fix it. Bar uses 1 min bar resolution at the minimum. As such when a stock goes up a minute, doesn't mean it did an uptick.

10:00:00.00001 - AAPL - 140.00

10:00:00.04001 - AAPL - 139.50

10:00:51.00300 - AAPL - 139.75

Bar consolidation considers the above scenario as a downtick. Coz close price is higher than the open price. Tick would consider downtick between 10.00:00.04001 and 10:00:51:00300 and uptick between 10:00:51:00300 and 10:01:00:000000

But I am amazed by latency issues. 1 min tick data takes approx 3 sec to process.  

 

for key in slice.Keys:
try:

if slice.ContainsKey(self.future_symbols[-1]):
continue

ticks_mo = slice[key]
if IGNORE_SUSPICIOUS:
trade_ticks_mo = [x for x in ticks_mo if x.TickType == 0 and not x.Suspicious]
else:
trade_ticks_mo = [x for x in ticks_mo if x.TickType == 0]

for tick in trade_ticks_mo:
if tick.Value > 0:
tick_value_mo = round(tick.Value,2)
tick_value_prev_mo = round(float(self.mo_stock_price_dict.get(str(key), 0)),2)
if tick_value_mo > tick_value_prev_mo:
self.mo_stock_dict[str(key)]='up'
self.mo_stock_price_dict[str(key)]=tick.Value
elif tick_value_mo < tick_value_prev_mo:
self.mo_stock_dict[str(key)]='down'
self.mo_stock_price_dict[str(key)]=tick.Value
else:
self.mo_stock_dict[str(key)]='neutral'
except:
continue

 

0

If you have better way of doing this, let me know.

0

Update Backtest





0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Loading...

This discussion is closed