I am trying to obtain the MACD, MACD signal and MACD difference lines for stock prices given certain input. below is the custom code that I am using.
def create_MACD(long_term,short_term,dataframe,signal_ema_length):
#obtain the SMA data that we need to obtain the MACD ema values
short_sma = create_sma(short_term,dataframe)
long_sma = create_sma(long_term,dataframe)
#create the EMAs that will be subtracted to obtain the MACD line
short_ema = create_ema(short_term,2,dataframe)
long_ema = create_ema(long_term,2,dataframe)
#calculate length of MACD array and starting indicies for line and signal
length = len(dataframe)
#calculate the starting index of the line
start_line = long_term
#calculate the starting index of the signal line
start_signal = long_term+signal_ema_length
#create the smoothing variables for the signal line
smoothing = 2/(signal_ema_length+1)
smoothing_minus = 1-smoothing
#calculate number of iterations for macd and macd signal
num_iters_macd = len(dataframe)-long_term
num_iters_signal = num_iters_macd - signal_ema_length
#create the MACD dataframe change dataframe to array for iterations
macd = np.zeros(length)
macd_signal = np.zeros(length)
array = dataframe.to_numpy()
#for loop for MACD data
for i in range(num_iters_macd):
index = start_line+i
macd[index] = short_ema[index]-long_ema[index]
#for loop for MACD signal
for i in range(num_iters_signal):
index = start_signal+i
macd_signal[index] = macd[index]*smoothing + macd_signal[index-1]*smoothing_minus
#create sma of first X days of MACD
sma_MACD = sum(macd[:signal_ema_length])/signal_ema_length
#insert the first value into the MACD signal array
macd_signal[start_signal-1] = macd[start_signal-1]*smoothing +sma_MACD*smoothing_minus
#create array for MACD difference
macd_diff = np.zeros(length)
#create starting index for MACD difference
start_diff = start_signal
num_iters_diff = num_iters_signal
for i in range(num_iters_diff):
index = i+start_diff
macd_diff[index] = macd[index]-macd_signal[index]
#send all array's to pandas dataframe
MACD_line = pd.DataFrame(data=macd)
MACD_signal = pd.DataFrame(data=macd_signal)
MACD_difference = pd.DataFrame(data=macd_diff)
return MACD_line, MACD_signal, MACD_difference
macd_av,signal_av,diff_av = create_MACD(26,12,price,9)
The error that I get is
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
~/opt/anaconda3/envs/tensorflow/lib/python3.7/site-packages/pandas/core/indexes/range.py in get_loc(self, key, method, tolerance)
354 try:
--> 355 return self._range.index(new_key)
356 except ValueError as err:
ValueError: 26 is not in range
The above exception was the direct cause of the following exception:
KeyError Traceback (most recent call last)
<ipython-input-20-a1e7f9a89bbb> in <module>
----> 1 macd_av,signal_av,diff_av = create_MACD(26,12,price,9)
<ipython-input-19-78834be35c60> in create_MACD(long_term, short_term, dataframe, signal_ema_length)
35 for i in range(num_iters_macd):
36 index = start_line+i
---> 37 macd[index] = short_ema[index]-long_ema[index]
38
39 #for loop for MACD signal
~/opt/anaconda3/envs/tensorflow/lib/python3.7/site-packages/pandas/core/frame.py in __getitem__(self, key)
2900 if self.columns.nlevels > 1:
2901 return self._getitem_multilevel(key)
-> 2902 indexer = self.columns.get_loc(key)
2903 if is_integer(indexer):
2904 indexer = [indexer]
~/opt/anaconda3/envs/tensorflow/lib/python3.7/site-packages/pandas/core/indexes/range.py in get_loc(self, key, method, tolerance)
355 return self._range.index(new_key)
356 except ValueError as err:
--> 357 raise KeyError(key) from err
358 raise KeyError(key)
359 return super().get_loc(key, method=method, tolerance=tolerance)
KeyError: 26
I have tested the custom SMA and EMA functions so those are outputting the correct array's. I know that this error means that my for loop range is not correct but I am unsure of why this is wrong.
The problem seems to be that the short and long ema/sma array's at the beginning are in pandas dataframes. To index those correctly you need to use .iloc function. However, this doesn't work well when you use loops as you need to convert to numpy arrays and then the loop should work as intended.