Hold many numbers in one array and do maths on all of them at once, without writing a loop.
A numpy array holds many numbers and does maths on all of them at once. Multiply an array of prices by a share count and every price gets multiplied, with no loop.
In this lesson I build arrays of prices, run arithmetic straight on them, show that a plain list does something else entirely, and turn prices into returns in one line.
Step 1. Maths on a whole row of prices
np.array() turns a list into an array. From then on, the operators work on every element.
import numpy as npprices = np.array([185.40, 187.20, 184.90]) # three closesprint(prices) # -> [185.4 187.2 184.9]print(type(prices)) # -> <class 'numpy.ndarray'>print(prices.shape) # -> (3,) <- 3 numbers, in one dimension
[185.4 187.2 184.9]
<class 'numpy.ndarray'>
(3,)
shape is a tuple, so (3,) means one row of three. Multiply by a number and each price is multiplied:
value = prices *10# 10 shares held on each of the three daysprint(value) # -> [1854. 1872. 1849.]
[1854. 1872. 1849.]
Two arrays of the same shape combine position by position: the first with the first, the second with the second.
aapl = np.array([185.40, 187.20, 184.90]) # three closes for one tickermsft = np.array([410.00, 408.50, 415.20]) # same three days, second tickerprint(aapl + msft) # -> [595.4 595.7 600.1] <- one share of each, per dayprint(msft - aapl) # -> [224.6 221.3 230.3] <- the gap between the two
[595.4 595.7 600.1]
[224.6 221.3 230.3]
Step 2. A list does not do this
The same two expressions on a list mean something else. * repeats the list and + joins two lists end to end.
print([1, 2] *2) # -> [1, 2, 1, 2] <- the list repeatedprint(np.array([1, 2]) *2) # -> [2 4] <- every element doubledprint([1, 2] + [3, 4]) # -> [1, 2, 3, 4] <- the two lists joinedprint(np.array([1, 2]) + np.array([3, 4])) # -> [4 6] <- added position by position
[1, 2, 1, 2]
[2 4]
[1, 2, 3, 4]
[4 6]
[1, 2] * 2 gives four items. np.array([1, 2]) * 2 gives two items, each doubled. To double every number in a list you write a loop. To double every number in an array you write * 2.
Step 3. Prices to returns in one line
Slicing an array works the way it did on lists in Lesson 5. closes[1:] is every price from the second onwards, and closes[:-1] is every price except the last.
Line those two up and the pairs are today and yesterday. Dividing one by the other divides every pair, so the whole set of returns comes out at once.
returns = closes[1:] / closes[:-1] -1# today over yesterday, minus 1print(np.round(returns, 4)) # -> [ 0.0097 -0.0123 0.0173 0.0128] <- rounded for reading onlyprint(closes.shape, returns.shape) # -> (5,) (4,) <- one return lost to the first day
[ 0.0097 -0.0123 0.0173 0.0128]
(5,) (4,)
Five prices, four returns, the same count as in Lesson 8.
Step 4. Three things to ask an array
.shape is an attribute, so no brackets. .mean() and .sum() are methods, so brackets.
print(f"mean: {returns.mean():.4%}") # -> mean: 0.6872%print(f"sum: {returns.sum():.6f}") # -> sum: 0.027488 <- not the weekly returnprint(returns.shape) # -> (4,)
mean: 0.6872%
sum: 0.027488
(4,)
.sum() adds the four returns. That is not the return for the week, because simple returns do not add across time. Multiply the growth factors instead:
print(f"compounded: {(1+ returns).prod() -1:.4%}") # -> compounded: 2.7508%print(f"last / first: {closes[-1] / closes[0] -1:.4%}") # -> last / first: 2.7508% <- same figure without the returns
compounded: 2.7508%
last / first: 2.7508%
1 + returns adds 1 to all four returns and .prod() multiplies them together.
Your turn
Take closes = np.array([50.0, 55.0, 55.0, 44.0]). Get the returns without a loop, print their shape, and compound them into a total.
TipShow answer
import numpy as npcloses = np.array([50.0, 55.0, 55.0, 44.0]) # four closes, one flat day, one dropreturns = closes[1:] / closes[:-1] -1# three returns from the four closesprint(returns) # -> [ 0.1 0. -0.2]print(returns.shape) # -> (3,)print(f"{(1+ returns).prod() -1:.4%}") # -> -12.0000%
NoteOne dtype per array
Every element of an array shares one dtype. np.array([1, 2]).dtype is int64 and np.array([185.4, 187.2]).dtype is float64. Mix an integer into a float array and it becomes a float.