Search code examples
pythonpandasstock

Can't calculate the total return correctly (pandas_datareader.get_data_yahoo)


I am trying to get a baseline, where there is a starting balance, and assuming we just hold and never trade, what the final total balance will be. But when I calculate it, the baseline Return is not correct.

Here is what I have so far and I'm using pandas_datareader to get the stock info

import matplotlib.pyplot as plt
import pandas_datareader as pdr
from datetime import datetime
import numpy as np

# defining variables
period = 30
start_balance = 10_000

# defining date range
start_date = datetime(2012, 1, 1)
end_date = datetime(2021, 12, 31)
years = (end_date - start_date).days / 365.25 # .25 to account for leap years

stock = pdr.get_data_yahoo('^GSPC', start_date, end_date)

# will only be using the open and close prices
stock.drop(['High', 'Low', 'Volume', 'Adj Close'], axis = 1, inplace = True)

# get the daily return %
stock['Return'] = stock['Close'] / stock['Open']

# get the baseline (What is giving me the issue)
stock['Baseline'] = stock['Return'].cumprod() * start_balance

When I check the baseline, it is almost half of what it should be

print(stock['Close'][-1]/ stock['Open'][0])
print(stock['Baseline'][-1] / stock['Baseline'][0])

3.7861082497194447
1.9666766862422043


Is there something I am missing? I even made a quick loop where I would multiply the daily return to the balance of the day before, but I am still getting the same answer.

balance = 10_000
for i in stock['Return']:
    balance *= i
    
print(balance)

19951.10078477877

df of what I have so far


Solution

  • I think I maybe got something. Instead of getting the daily Return by doing
    stock['Return'] = stock['Close'] / stock['Open']

    I got the close price from the day before and used that to calculate the daily Return
    stock['Return'] = stock['Close'] / stock['Close'].shift(1)
    as (I'm assuming) prices can change outside of the market so this is taking that into account. The percentage change is now a lot closer to what it should be!

    print(stock['Close'][-1]/ stock['Open'][1])
    print(stock['Baseline'][-1] / stock['Baseline'][1])
    

    3.732
    3.731