pythonlistmathtechnical-indicator

Python sum() is calculating same value for two different lists


I'm trying to do technical analysis using RSI which involves having 2 lists of gains and losses then getting the average of the 2 lists. For some reason, when using sum(), I receive the same value for the 2 lists. When manually adding the sum of the lists I see different results. This is what I have:

def calculate_avg_gain(in_list : list) -> tuple:
gain_list = []
loss_list = []
for i, close in enumerate(in_list):
    try:
        change = close - in_list[i-1]
    except IndexError:
        change = 0.0
    if change >= 0.0:
        gain_list.append(change)
        loss_list.append(0.0)
    else:
        gain_list.append(0.0)
        loss_list.append(abs(change))
avg_gain = sum(gain_list) / 14
avg_loss = sum(loss_list) / 14
return avg_gain, avg_loss

I stepped in the code when I had 14 entries for each:

gain_list = [1.1800000000000068, 0.0, 0.0, 0.10000000000002274, 0.0, 0.44999999999998863, 0.030000000000001137, 0.0, 0.160000000000025, 0.0, 0.0, 0.15000000000000568, 0.0, 0.05000000000001137]
loss_list = [0.0, 0.19999999999998863, 0.10999999999998522, 0.0, 0.0, 0.0, 0.5, 0.3299999999999841, 0.0, 0.47999999999998977, 0.0, 0.10000000000002274, 0.25, 0.0]

avg_gain = 0.15142857142857583
avg_loss = 0.1407142857142836

The sum for both comes out to 2.12, which is what I get for the sum of loss_list, while I get 2.1799 for gain_list. Am I missing something?


Solution

  • If you see the problem here is that, whenever you do in_list[-1] it will not throw IndexError, but it will use the last element that is in_list[len(list)-1]

    In [4]: def calculate_avg_gain(in_list : list) -> tuple:
       ...:     gain_list = []
       ...:     loss_list = []
       ...:     for i, close in enumerate(in_list):
       ...:         try:
       ...:             change = close - in_list[i-1]
       ...:         except IndexError:
       ...:             change = 0.0
       ...:         if change >= 0.0:
       ...:             gain_list.append(change)
       ...:             loss_list.append(0.0)
       ...:         else:
       ...:             gain_list.append(0.0)
       ...:             loss_list.append(abs(change))
       ...:         print(gain_list, loss_list, change)
       ...:     avg_gain = sum(gain_list) / 14
       ...:     avg_loss = sum(loss_list) / 14
       ...:     return avg_gain, avg_loss
       ...:
    
    In [5]: calculate_avg_gain(a)
    [0.0] [4] -4
    [0.0, 1] [4, 0.0] 1
    [0.0, 1, 1] [4, 0.0, 0.0] 1
    [0.0, 1, 1, 1] [4, 0.0, 0.0, 0.0] 1
    [0.0, 1, 1, 1, 1] [4, 0.0, 0.0, 0.0, 0.0] 1
    Out[5]: (0.2857142857142857, 0.2857142857142857)
    

    You can update the code to the following:

    In [6]: def calculate_avg_gain(in_list : list) -> tuple:
       ...:     gain_list = []
       ...:     loss_list = []
       ...:     for i, close in enumerate(in_list):
       ...:         if i == 0:
       ...:             continue
       ...:         change = close - in_list[i-1]
       ...:         if change >= 0.0:
       ...:             gain_list.append(change)
       ...:             loss_list.append(0.0)
       ...:         else:
       ...:             gain_list.append(0.0)
       ...:             loss_list.append(abs(change))
       ...:         print(gain_list, loss_list, change)
       ...:     avg_gain = sum(gain_list) / 14
       ...:     avg_loss = sum(loss_list) / 14
       ...:     return avg_gain, avg_loss
       ...:
    
    In [7]: calculate_avg_gain(a)
    [1] [0.0] 1
    [1, 1] [0.0, 0.0] 1
    [1, 1, 1] [0.0, 0.0, 0.0] 1
    [1, 1, 1, 1] [0.0, 0.0, 0.0, 0.0] 1
    Out[7]: (0.2857142857142857, 0.0)
    

    If you want a one-liner for change, you can do the following

    >>> [j-i for i, j in zip(t[:-1], t[1:])]
    [2, 3]
    

    Then if change is > 0, you can add to gain, if not to loss.

    Other ways:

    for i in range(1, len(in_list)):
        change = in_list[i] - in_list[i-1]
    

    if you are already using NumPy in your project, you can do

    import numpy as np
    in_list = np.array([5, 4, 89, 12, 32, 45])
      
      
    # Calculating difference list
    diff_list = np.diff(in_list)