σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft AcademyParcours
Ctrl K
AO
+1,2 k apprenants
ConnexionRejoindre ↗
Parcours
AO
+1,2 k apprenants
Connexion
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Parcours Python›Module 11 · Systèmes de production et modèles de pointe›Sujet 11.12·~2 hExpert

Apprentissage par renforcement pour le trading

Position dans le parcoursModule 11 sur 11 · Sujet 12 sur 13
11.12 Apprentissage par renforcement pour le trading
—Score du lab— / 100XP total—Série—

Apprendre en essayant

En apprentissage supervisé, chaque exemple vient avec la bonne réponse. Le trading n'est pas ainsi : personne ne vous donne la meilleure position, vous agissez et le marché répond par un gain ou une perte. L'apprentissage par renforcement modélise cela comme un agent qui observe un état, prend une action, reçoit une récompense et passe à un nouvel état, avec pour but de maximiser la récompense totale dans le temps. Pour le trading, l'état peut être les rendements récents ou la position actuelle, les actions acheter, garder ou vendre, et la récompense le gain du pas moins les coûts. La difficulté est que les actions ont des conséquences plus tard et que l'agent doit découvrir ce qui paie en essayant.

# Reward of one step: profit from the position held, minus the cost of changing position
def step_reward(position, price_change, previous_position, cost):
    return position * price_change - cost * abs(position - previous_position)

print(round(step_reward(1, 0.5, 0, 0.1), 4))         # 0.4    went long, the price rose 0.5, paid 0.1 to trade
print(round(step_reward(-1, 0.5, 1, 0.1), 4))        # -0.7   flipped from long to short just before a rise: lost 0.5 and paid 0.2
print(step_reward(1, 0.5, 1, 0.1))                   # 0.5    holding the same position costs nothing

Q-learning : la valeur d'une action dans un état

Le Q-learning garde une table Q[état, action] : la récompense totale attendue si l'on prend action dans état puis qu'on agit bien. Après chaque pas, il pousse l'entrée vers une meilleure estimation, la cible : la récompense qu'on vient de recevoir plus la valeur actualisée de la meilleure action dans l'état suivant, reward + gamma * max(Q[état suivant]). La mise à jour est Q[s, a] += alpha * (cible - Q[s, a]), avec un taux d'apprentissage alpha. Le facteur d'actualisation gamma (0 à 1) dit combien les récompenses futures comptent : gamma = 0 est un agent à courte vue, proche de 1 un agent patient, et le retour d'une séquence est r0 + gamma r1 + gamma^2 r2 + .... À un pas terminal, il n'y a pas d'état suivant et la cible est simplement la récompense.

# One Q-learning update on a table of 2 states x 3 actions (short, flat, long)
import numpy as np

def q_update(q, state, action, reward, next_state, alpha, gamma):
    updated = q.copy()
    target = reward if next_state is None else reward + gamma * updated[next_state].max()
    updated[state, action] += alpha * (target - updated[state, action])
    return updated

q = np.zeros((2, 3))
q = q_update(q, 0, 2, 1.0, 1, 0.5, 0.9)               # in state 0 we went long and earned 1.0
print(q[0])                                           # [0.  0.  0.5]   moved halfway (alpha 0.5) toward the target of 1.0
q = q_update(q, 0, 2, 1.0, 1, 0.5, 0.9)
print(q[0])                                           # [0.   0.   0.75]   a second visit moves it further

Explorer, et une boucle d'entraînement complète

Un agent qui prend toujours la meilleure action qu'il connaît ne découvre jamais si une autre est meilleure. L'epsilon-greedy y remédie : avec une probabilité epsilon il explore une action aléatoire, sinon il exploite l'action de plus grand Q, les égalités allant à la première. Epsilon commence en général haut puis décroît. La boucle est alors : observer l'état, choisir une action, recevoir la récompense et l'état suivant, mettre à jour Q, recommencer. Dans un marché jouet où un jour de hausse est souvent suivi d'un autre, l'agent qui voit « hier était en hausse » apprend que rester long rapporte, et une table de deux états et trois actions suffit à le montrer.

# A toy market where an up day tends to be followed by another up day; the agent learns to follow the trend
import random
import numpy as np

rng = random.Random(1)
positions = [-1, 0, 1]                                # action 0 = short, 1 = flat, 2 = long
q = np.zeros((2, 3))                                  # state 0 = yesterday down, state 1 = yesterday up
alpha, gamma, cost = 0.1, 0.9, 0.0005
state, previous = 1, 0
for step in range(20000):
    epsilon = max(0.05, 1 - step / 10000)
    u, explore = rng.random(), rng.randrange(3)
    action = explore if u < epsilon else int(np.argmax(q[state]))
    up = rng.random() < (0.65 if state == 1 else 0.35)           # the trend continues 65% of the time
    change = 0.01 if up else -0.01
    reward = positions[action] * change - cost * abs(positions[action] - previous)
    next_state = 1 if up else 0
    target = reward + gamma * q[next_state].max()
    q[state, action] += alpha * (target - q[state, action])
    state, previous = next_state, positions[action]

print(int(np.argmax(q[0])), int(np.argmax(q[1])))     # 0 2   after a down day go short, after an up day go long
# The discounted return: with gamma below 1 a reward now is worth more than the same reward later
def discounted_return(rewards, gamma):
    total = 0.0
    for reward in reversed(rewards):
        total = reward + gamma * total
    return total

rewards = [1.0, 1.0, 1.0]
print(discounted_return(rewards, 0.5))               # 1.75   1 + 0.5 + 0.25
print(discounted_return(rewards, 1.0))               # 3.0    a patient agent: a plain sum
print(discounted_return(rewards, 0.0))               # 1.0    a short-sighted agent: only the first reward counts
Le backtest d'une politique apprise est facile à tromperUn agent entraîné sur une portion d'historique trouvera tout motif qui a payé là, réel ou accidentel, et les données de marché sont rares et non stationnaires : la leçon d'une année peut ne pas tenir la suivante. Entraînez et testez sur des périodes séparées (walk-forward), facturez des coûts et un glissement réalistes dans la récompense, pénalisez le risque et les grosses positions, comparez à une règle triviale comme acheter-et-garder, et méfiez-vous de tout résultat trop beau. L'apprentissage par renforcement est ici davantage un outil de recherche qu'une stratégie de production.
  • Un agent observe un état, agit, reçoit une récompense (gain moins coûts) et apprend quelles actions paient ; le retour est la somme actualisée r0 + gamma r1 + gamma^2 r2 + ....
  • Le Q-learning met à jour Q[s, a] += alpha * (reward + gamma * max Q[s'] - Q[s, a]) (juste reward à un pas terminal) et ne modifie pas l'ancienne table sur place ici.
  • L'epsilon-greedy explore avec la probabilité epsilon et exploite sinon le plus grand Q ; entraînez et testez sur des périodes séparées, facturez des coûts réalistes et comparez à des références simples.

À suivre : le projet de synthèse, une bibliothèque complète de valorisation ou de stratégie qui réunit tout.

Lab : ce qui est noté

  • Explorer ou exploiter avec choose_action25 pts
  • Apprendre d'un pas avec q_update25 pts
  • Faire payer le trading dans step_reward25 pts
  • Additionner l'avenir avec discounted_return25 pts
Explorateur · lab-141-1
▾ lab-141-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-141-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

Tout le contenu de lab-141-1 revient aux fichiers de départ et le terminal est vidé. Votre solution actuelle sera perdue : cette action est irréversible.

Sera réinitialisé
  • main.py → code de départ
  • Historique du terminal et sortie des tests
  • Modifications non soumises
Sera conservé
  • Meilleur score du lab
  • Votre XP et votre série
  • Progression du cours et notes

Connectez-vous pour exécuter votre code.

Tous les cours sont gratuits à lire. Créez un compte ou connectez-vous pour exécuter du code, lancer les tests et soumettre ce lab.

  • IDE dans le navigateur avec terminal bash — rien à installer
  • Correction instantanée, XP et votre place dans le parcours
Créer un compteSe connecter
OU
Continuer avec GitHub