σμ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 AcademyRutas
Ctrl K
AO
+1,2 k estudiantes
Iniciar sesiónUnirse ↗
Rutas
AO
+1,2 k estudiantes
Iniciar sesión
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Ruta de Python›Módulo 11 · Sistemas de producción y modelos de vanguardia›Tema 11.12·~2 hExperto

Aprendizaje por refuerzo para trading

Posición en la rutaMódulo 11 de 11 · Tema 12 de 13
11.12 Aprendizaje por refuerzo para trading
—Puntuación del lab— / 100XP total—Racha—

Aprender probando

En el aprendizaje supervisado cada ejemplo trae la respuesta correcta. El trading no es así: nadie te dice la mejor posición, actúas y el mercado responde con una ganancia o una pérdida. El aprendizaje por refuerzo lo modela como un agente que observa un estado, toma una acción, recibe una recompensa y pasa a un nuevo estado, con el objetivo de maximizar la recompensa total en el tiempo. En trading el estado puede ser los rendimientos recientes o la posición actual, las acciones comprar, mantener o vender, y la recompensa la ganancia del paso menos los costes. La dificultad es que las acciones tienen consecuencias más tarde y el agente debe descubrir qué paga probando.

# 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: el valor de una acción en un estado

Q-learning mantiene una tabla Q[estado, acción]: la recompensa total esperada si tomas acción en estado y luego actúas bien. Tras cada paso empuja la entrada hacia una mejor estimación, el objetivo: la recompensa recién recibida más el valor descontado de la mejor acción en el estado siguiente, reward + gamma * max(Q[estado siguiente]). La actualización es Q[s, a] += alpha * (objetivo - Q[s, a]), con una tasa de aprendizaje alpha. El factor de descuento gamma (0 a 1) dice cuánto importan las recompensas futuras: gamma = 0 es un agente miope, cerca de 1 uno paciente, y el retorno de una secuencia es r0 + gamma r1 + gamma^2 r2 + .... En un paso terminal no hay estado siguiente y el objetivo es solo la recompensa.

# 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

Explorar y un bucle de entrenamiento completo

Un agente que siempre toma la mejor acción que conoce nunca descubre si otra es mejor. Epsilon-greedy lo arregla: con probabilidad epsilon explora una acción aleatoria, si no explota la acción de mayor Q, y los empates van a la primera. Epsilon suele empezar alto y decaer. El bucle es entonces: observar el estado, elegir una acción, recibir la recompensa y el estado siguiente, actualizar Q, repetir. En un mercado de juguete donde un día al alza suele ir seguido de otro, el agente que ve «ayer fue al alza» aprende que mantenerse largo paga, y una tabla de dos estados y tres acciones basta para mostrarlo.

# 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
El backtest de una política aprendida es fácil de engañarUn agente entrenado en un tramo de historia encontrará cualquier patrón que pagó allí, real o accidental, y los datos de mercado son escasos y no estacionarios: la lección de un año puede no valer el siguiente. Entrena y prueba en periodos separados (walk-forward), cobra costes y deslizamiento realistas dentro de la recompensa, penaliza el riesgo y las posiciones grandes, compara con una regla trivial como comprar y mantener y desconfía de cualquier resultado demasiado bueno. El aprendizaje por refuerzo es aquí más una herramienta de investigación que una estrategia de producción.
  • Un agente observa un estado, actúa, recibe una recompensa (ganancia menos costes) y aprende qué acciones pagan; el retorno es la suma descontada r0 + gamma r1 + gamma^2 r2 + ....
  • Q-learning actualiza Q[s, a] += alpha * (reward + gamma * max Q[s'] - Q[s, a]) (solo reward en un paso terminal) y aquí no edita la tabla antigua en el sitio.
  • Epsilon-greedy explora con probabilidad epsilon y si no explota el mayor Q; entrena y prueba en periodos separados, cobra costes realistas y compara con referencias simples.

A continuación: el proyecto final, una biblioteca completa de valoración o de estrategia que reúne todo.

Lab: qué se califica

  • Explorar o explotar con choose_action25 pts
  • Aprender de un paso con q_update25 pts
  • Cobrar por operar en step_reward25 pts
  • Sumar el futuro con discounted_return25 pts
Explorador · lab-141-1
▾ lab-141-1
…
bash · en el navegador
learner@quantcraft:~/lab-141-1$
Python aún no cargadoPythonLn 1, Col 1Spaces: 4UTF-8

¿Restablecer este tema?

Todo lo que hay en lab-141-1 vuelve a los archivos iniciales y se limpia el terminal. Tu solución actual se perderá: no se puede deshacer.

Se restablecerá
  • main.py → código inicial
  • Historial del terminal y salida de pruebas
  • Cambios sin enviar
Se conservará
  • Mejor puntuación del lab
  • Tu XP y tu racha
  • Progreso de la lección y notas

Inicia sesión para ejecutar tu código.

Todas las clases se pueden leer gratis. Crea una cuenta o inicia sesión para ejecutar código, lanzar las pruebas y enviar este lab.

  • IDE en el navegador con terminal bash — sin instalar nada
  • Corrección instantánea, XP y tu lugar en la ruta
Crear una cuentaIniciar sesión
O
Continuar con GitHub