1
\$\begingroup\$

This is an Relative Strength Index algorithm able to buy and sell stock based on values from basic stock CSVs. It works correctly and well, but I'm not sure if it can be better optimized as it basically repeats itself twice to operate on the two stock values it's given. I can only use python itself, no numpy or anything.

def alg_rsi(filename_1, filename_2):
 lookback = 21
 cash_balance = 10000
 stocks_owned = 0
 column_choice = 4
 day = 1
 file1 = open(filename_1).readlines()
 file2 = open(filename_2).readlines()
 file1_length = sum(1 for line in file1)
 file2_length = sum(1 for line in file2)
 if file1_length >= file2_length:
 length = file2_length
 else:
 length = file1_length
 for i in range(length - lookback - 1):
 tday = day + lookback
 gains = []
 losses = []
 for i in range(lookback):
 today = float(file1[tday][:-1].split(',')[column_choice])
 yesterday = float(file1[tday - 1][:-1].split(',')[column_choice])
 if today > yesterday:
 gain = today - yesterday
 gains.append(gain)
 else:
 loss = yesterday - today
 losses.append(loss)
 tday = tday - 1
 totalgain1 = sum(gains)
 totalloss1 = sum(losses)
 averagegain1 = totalgain1 / lookback
 averageloss1 = totalloss1 / lookback
 rsi1 = 100 - (100 / (1 + (averagegain1 / averageloss1)))
 gains.clear()
 losses.clear()
 tday = day + lookback
 for i in range(lookback):
 today = float(file2[tday][:-1].split(',')[column_choice])
 yesterday = float(file2[tday - 1][:-1].split(',')[column_choice])
 if today > yesterday:
 gain = today - yesterday
 gains.append(gain)
 else:
 loss = yesterday - today
 losses.append(loss)
 tday = tday - 1
 totalgain2 = sum(gains)
 totalloss2 = sum(losses)
 averagegain2 = totalgain2 / lookback
 averageloss2 = totalloss2 / lookback
 rsi2 = 100 - (100 / (1 + (averagegain2 / averageloss2)))
 gains.clear()
 losses.clear()
 stocks_per = 10
 price1 = float(file1[day + lookback][:-1].split(',')[column_choice])
 price2 = float(file2[day + lookback][:-1].split(',')[column_choice])
 try:
 if rsi1 <= 30:
 cash_balance, stocks_owned = transact(cash_balance,
 stocks_owned,
 stocks_per,
 price1, buy=True,
 sell=False)
 elif rsi1 >= 70:
 cash_balance, stocks_owned = transact(cash_balance,
 stocks_owned,
 stocks_per,
 price1, buy=False,
 sell=True)
 else:
 pass
 except ValueError:
 pass
 try:
 if rsi2 <= 30:
 cash_balance, stocks_owned = transact(cash_balance,
 stocks_owned,
 stocks_per,
 price2, buy=True,
 sell=False)
 elif rsi2 >= 70:
 cash_balance, stocks_owned = transact(cash_balance,
 stocks_owned,
 stocks_per,
 price2, buy=False,
 sell=True)
 else:
 pass
 except ValueError:
 pass
 day = day + 1
 if price1 > price2:
 cash_balance, stocks_owned = transact(cash_balance,
 stocks_owned,
 stocks_owned,
 price1, buy=False,
 sell=True)
 else:
 cash_balance, stocks_owned = transact(cash_balance,
 stocks_owned,
 stocks_owned,
 price2, buy=False,
 sell=True)
 return stocks_owned, cash_balance

Overall I'm not super pressed if this is how it has to be, as it still works quickly; it just seems to me like there's too many redundant parts.

Toby Speight
87.2k14 gold badges104 silver badges322 bronze badges
asked May 11, 2021 at 15:14
\$\endgroup\$
1
  • \$\begingroup\$ The indentation looked wrong - I believe I've corrected it, but do please check that I got it right! \$\endgroup\$ Commented May 11, 2021 at 15:48

2 Answers 2

1
\$\begingroup\$
if file1_length >= file2_length:
 length = file2_length
else:
 length = file1_length

Or more succinctly as length = max(file1_length, file2_length)


tday

What is tday? It does not look like typo for today


for i in range(lookback):
 today = float(file1[tday][:-1].split(',')[column_choice])
 yesterday = float(file1[tday - 1][:-1].split(',')[column_choice])
 if today > yesterday:
 gain = today - yesterday
 gains.append(gain)
 else:
 loss = yesterday - today
 losses.append(loss)
 tday = tday - 1
totalgain1 = sum(gains)
totalloss1 = sum(losses)
averagegain1 = totalgain1 / lookback
averageloss1 = totalloss1 / lookback

This whole chunk is duplicated. I suggest making a function to remove duplicate code

There are more duplicated chunks, and it looks like an array of size 2 would be useful

answered May 11, 2021 at 17:59
\$\endgroup\$
1
\$\begingroup\$
  • Computation of rsi1 (and rsi2) are a bit more complicated as necessary. Gains and losses are accumulated in their respective lists, only to be summed later on. Get rid of the lists:

     if today > yesterday:
     gain += today - yesterday
     else:
     loss += yesterday - today
    

    Computing averages is also redundant.

     averagegain1 = totalgain1 / lookback
     averageloss1 = totalloss1 / lookback
     rsi1 = 100 - (100 / (1 + (averagegain1 / averageloss1)))
    

    is a very long way to say

     rsi1 = 100 - (100 / (1 + (totalgain1 / totalloss1)))
    

    Math guarantees that the result will be the same. lookback just cancels.

    Also you have to be very careful with division by totalloss. It is quite possible that it is zero. BTW, I would simplify the formula to 100 * gain/(gain + loss).

  • You didn't show transact. From what I see, passing both buy and sell seems redundant. They are always opposite to each other.

    If setting them both to False results in no transaction, consider

     buy, sell = False, False
     if rsi <= 30:
     buy = True
     if rsi >= 70:
     sell = True
     cash_balance, stocks_owned = transact(cash_balance,
     stocks_owned,
     stocks_per,
     price,
     buy, sell)
    
  • You may achieve a certain performance increase by not recomputing gains and losses over the entire lookback period. Using a sliding window.

  • As noted in another answer, factor the repeated code into a function.

answered May 11, 2021 at 22:37
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.