A vector is a list of numbers with rules
A vector is an ordered list of numbers of a fixed length, such as the weights of a portfolio [0.5, 0.3, 0.2] or one day's returns for three assets [0.02, -0.01, 0.03]. In Python a list of floats does the job. Vectors can be added, scaled and combined position by position, which is why so much of quantitative finance is written in their language. Two vectors can only be combined when they have the same length; mixing lengths is a bug you want to hear about loudly.
weights = [0.5, 0.3, 0.2]
returns = [0.02, -0.01, 0.03]
# Position by position: zip pairs the elements
products = [w * r for w, r in zip(weights, returns)]
print([round(p, 4) for p in products]) # [0.01, -0.003, 0.006]
# Scaling and adding vectors
print([2 * w for w in weights]) # [1.0, 0.6, 0.4]
print([a + b for a, b in zip(weights, returns)]) # [0.52, 0.29, 0.23]The dot product
The dot product multiplies two vectors position by position and adds the results: a1*b1 + a2*b2 + ... + an*bn. It returns a single number. It is the portfolio return when a holds the weights and b the returns: 0.5*0.02 + 0.3*(-0.01) + 0.2*0.03 = 0.013. It is also the value of a position list (quantities dot prices) and the building block of a regression. In Python: sum(x * y for x, y in zip(a, b)), after checking that len(a) == len(b), because zip silently stops at the shorter list.
def dot(a, b):
if len(a) != len(b):
raise ValueError("vectors must have the same length")
return sum(x * y for x, y in zip(a, b))
print(dot([1, 2, 3], [4, 5, 6])) # 32
print(round(dot([0.5, 0.3, 0.2], [0.02, -0.01, 0.03]), 6)) # 0.013 (portfolio return)
try:
dot([1, 2], [1, 2, 3])
except ValueError as error:
print(error) # vectors must have the same lengthLength, direction and similarity
A vector dotted with itself gives its squared length, so the norm (length) is math.sqrt(dot(a, a)): for [3, 4] it is 5.0. Dividing a vector by its norm gives a unit vector of length 1 that keeps only the direction (but a zero vector has no direction, so refuse it with ValueError). The cosine similarity dot(a, b) / (norm(a) * norm(b)) measures how aligned two vectors are, from -1 (opposite) through 0 (unrelated, at right angles) to 1 (same direction, whatever the scale). Applied to demeaned return series it is the correlation, a central quantity in portfolio risk.
import math
def dot(a, b):
return sum(x * y for x, y in zip(a, b))
def norm(a):
return math.sqrt(dot(a, a))
print(norm([3, 4])) # 5.0
def normalize(a):
length = norm(a)
if length == 0:
raise ValueError("a zero vector has no direction")
return [x / length for x in a]
print(normalize([3, 4])) # [0.6, 0.8]
def cosine_similarity(a, b):
return dot(a, b) / (norm(a) * norm(b))
print(round(cosine_similarity([1, 2], [2, 4]), 6)) # 1.0 (same direction)
print(cosine_similarity([1, 0], [0, 1])) # 0.0 (perpendicular)
print(round(cosine_similarity([1, 2], [-1, -2]), 6)) # -1.0 (opposite)import math
def dot(a, b):
return sum(x * y for x, y in zip(a, b))
def mean(values):
return sum(values) / len(values)
# Correlation is the cosine of the demeaned series
a = [0.01, 0.02, -0.01, 0.03]
b = [0.02, 0.04, -0.02, 0.06] # always twice a
da = [x - mean(a) for x in a]
db = [x - mean(b) for x in b]
corr = dot(da, db) / math.sqrt(dot(da, da) * dot(db, db))
print(round(corr, 6)) # 1.0
# Value of a book: quantities dot prices
quantities = [100, -50, 20]
prices = [184.0, 410.0, 171.0]
print(dot(quantities, prices)) # 1320.0zip, or you will silently drop data. And never test float results with ==: a cosine of two identical directions may come out as 0.9999999999999999. Compare with math.isclose(...), as the lab tests do. In practice you will soon use NumPy, whose np.dot and np.linalg.norm do all of this fast; knowing what they compute lets you check them.- Dot product: multiply position by position and add; check the lengths first.
- Norm
sqrt(dot(a, a)); unit vectora / norm(a)(refuse the zero vector). - Cosine similarity
dot(a, b) / (norm(a) * norm(b))runs from -1 to 1; compare floats withisclose.
Next up: matrices and linear systems, tables of numbers that act on vectors and solve many equations at once.
Lab · what's graded
- Combine weights and returns with
dot25 pts - Measure the length of a vector with
norm25 pts - Compare directions with
cosine_similarity25 pts - Scale a vector to length 1 with
normalize25 pts