How do I turn prices into returns?

Build a list of returns in a loop, then compound them into the return for the whole stretch.

A return is the change from yesterday’s price to today’s price, divided by yesterday’s price. A list of prices becomes a list of returns one day at a time.

In this lesson I build that list with a loop, run it on a week of closing prices, and compound the daily returns into the return for the whole week.

Step 1. Three prices, two returns

Start with an empty list. Each pass through the loop computes one return and appends it to the end.

The loop starts at position 1, not 0, because position 0 has no day before it.

closes  = [100.0, 110.0, 99.0]                      # three closing prices in order
returns = []                                        # the list I am going to fill

for i in range(1, len(closes)):                     # i = 1, 2
    r = (closes[i] - closes[i - 1]) / closes[i - 1] # today minus yesterday, over yesterday
    returns.append(r)                               # put it on the end

print(returns)                                      # -> [0.1, -0.1]
print(len(closes), "prices ->", len(returns), "returns")
# -> 3 prices -> 2 returns
[0.1, -0.1]
3 prices -> 2 returns

The price went from 100 to 110, a gain of 10%, then from 110 to 99, a fall of 10%. Three prices give two returns.

Here is what position 0 would reach for:

i = 0                   # the one position with no day before it
print(closes[i - 1])    # -> 99.0    <- closes[-1] is the last price in the list
99.0

closes[-1] counts from the end of the list.

Step 2. A week of closes

Now the same loop on five closes with the dates they belong to. Each return sits on the later of the two days it was computed from, so dates[1:] drops Monday.

dates  = ["Mon", "Tue", "Wed", "Thu", "Fri"]                     # five weekday labels
closes = [185.40, 187.20, 184.90, 188.10, 190.50]                # one close per day

returns = []
for i in range(1, len(closes)):                                  # 1 to 4, Mon has no day before
    returns.append((closes[i] - closes[i - 1]) / closes[i - 1])  # today over yesterday

for d, r in zip(dates[1:], returns):                             # dates[1:] drops Mon
    print(f"{d}  {r:.2%}")
# -> Tue  0.97%
# -> Wed  -1.23%
# -> Thu  1.73%
# -> Fri  1.28%
Tue  0.97%
Wed  -1.23%
Thu  1.73%
Fri  1.28%

Five closes, four returns, and four days with a return attached.

Counting the up days is a loop over the list I just built.

up = 0                                      # the running count
for r in returns:
    if r > 0:
        up += 1                             # same as up = up + 1

print(up, "up days out of", len(returns))   # -> 3 up days out of 4
3 up days out of 4

Step 3. Compound the week into one number

To get the return for the whole week, multiply the growth factors 1 + r together and subtract 1 at the end.

growth = 1.0                                               # 1 is neutral for multiplying
for r in returns:
    growth = growth * (1 + r)                              # multiply the growth factors together

week = growth - 1                                          # take the starting 1 back off

print(f"compounded:  {week:.4%}")                          # -> compounded:  2.7508%
print(f"from prices: {closes[-1] / closes[0] - 1:.4%}")    # -> from prices: 2.7508%
compounded:  2.7508%
from prices: 2.7508%

The compounded figure equals the last close over the first close, minus 1.

Now the same four returns added instead of multiplied.

added = sum(returns)                # the four returns added, not compounded

print(f"added:      {added:.4%}")   # -> added:      2.7488%
print(f"compounded: {week:.4%}")    # -> compounded: 2.7508%
added:      2.7488%
compounded: 2.7508%

The prices moved 2.7508%. Adding gives 2.7488%.

Your turn

Take closes = [50.0, 55.0, 55.0, 44.0]. Build the list of returns, then compound them into a total. How many returns do four prices give?

closes  = [50.0, 55.0, 55.0, 44.0]
returns = []

for i in range(1, len(closes)):
    returns.append((closes[i] - closes[i - 1]) / closes[i - 1])

print([round(r, 4) for r in returns])   # -> [0.1, 0.0, -0.2]
print(len(returns), "returns")          # -> 3 returns

growth = 1.0
for r in returns:
    growth = growth * (1 + r)

print(f"{growth - 1:.4%}")                   # -> -12.0000%
print(f"{closes[-1] / closes[0] - 1:.4%}")   # -> -12.0000%