Un vecteur est une liste de nombres avec des règles
Un vecteur est une liste ordonnée de nombres de longueur fixe, comme les poids d'un portefeuille [0.5, 0.3, 0.2] ou les rendements d'un jour pour trois actifs [0.02, -0.01, 0.03]. En Python, une liste de flottants fait l'affaire. On peut additionner, mettre à l'échelle et combiner des vecteurs position par position, ce qui explique pourquoi une grande part de la finance quantitative s'écrit dans leur langage. Deux vecteurs ne se combinent que s'ils ont la même longueur ; mélanger les longueurs est un bogue dont il faut être averti bruyamment.
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]Le produit scalaire
Le produit scalaire multiplie deux vecteurs position par position et additionne les résultats : a1*b1 + a2*b2 + ... + an*bn. Il renvoie un seul nombre. C'est le rendement du portefeuille quand a contient les poids et b les rendements : 0.5*0.02 + 0.3*(-0.01) + 0.2*0.03 = 0.013. C'est aussi la valeur d'une liste de positions (quantités scalaire prix) et la brique d'une régression. En Python : sum(x * y for x, y in zip(a, b)), après avoir vérifié que len(a) == len(b), car zip s'arrête silencieusement à la liste la plus courte.
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 lengthLongueur, direction et similarité
Un vecteur multiplié scalairement par lui-même donne sa longueur au carré, donc la norme (longueur) vaut math.sqrt(dot(a, a)) : pour [3, 4] c'est 5.0. Diviser un vecteur par sa norme donne un vecteur unitaire de longueur 1 qui ne garde que la direction (mais un vecteur nul n'a pas de direction, refusez-le avec ValueError). La similarité cosinus dot(a, b) / (norm(a) * norm(b)) mesure l'alignement de deux vecteurs, de -1 (opposés) à 0 (sans lien, à angle droit) jusqu'à 1 (même direction, quelle que soit l'échelle). Appliquée à des séries de rendements centrées, c'est la corrélation, une grandeur centrale du risque de portefeuille.
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, sinon vous perdrez des données en silence. Et ne testez jamais des résultats flottants avec == : le cosinus de deux directions identiques peut donner 0.9999999999999999. Comparez avec math.isclose(...), comme le font les tests du lab. En pratique, vous utiliserez bientôt NumPy dont np.dot et np.linalg.norm font tout cela rapidement ; savoir ce qu'ils calculent permet de les vérifier.- Produit scalaire : multiplier position par position et additionner ; vérifier d'abord les longueurs.
- Norme
sqrt(dot(a, a)); vecteur unitairea / norm(a)(refuser le vecteur nul). - Similarité cosinus
dot(a, b) / (norm(a) * norm(b))de -1 à 1 ; comparez les flottants avecisclose.
À suivre : matrices et systèmes linéaires, des tableaux de nombres qui agissent sur des vecteurs et résolvent plusieurs équations à la fois.
Lab : ce qui est noté
- Combiner poids et rendements avec
dot25 pts - Mesurer la longueur d'un vecteur avec
norm25 pts - Comparer des directions avec
cosine_similarity25 pts - Ramener un vecteur à la longueur 1 avec
normalize25 pts