value not in range in for loop for python

1.8k views Asked by At

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.

1

There are 1 answers

0
Brian E On

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.