Nuestro sistema de comercio automatizado tenía un valor esperado positivo: las matemáticas se comprobaron, las pruebas de retroceso parecían grandes, y inicialmente, ganó dinero. pero con el tiempo, estaba sangrando. Este no fue un error en el código, fue un malentendido fundamental de lo que importa en la producción. La trampa del valor esperado La mayoría de los tutoriales de comercio, artículos académicos y cursos en línea te enseñan a maximizar el valor esperado. E[profit] = Σ(probability_i × outcome_i) Si este número es positivo, debes tomar el comercio. Si puedes hacer que este número sea más grande, debes optimizarlo. Excepto en la producción, esta estrategia de optimización tiene un defecto fatal: . it doesn't account for the path you take to reach that expected value Déjame mostrarle lo que quiero decir con un escenario real de nuestro sistema. El sistema de sangrado Nuestra estrategia fue diseñada para capturar los picos de precios en los mercados volátiles. Analizar posibles direcciones de precios para cada ventana de negociación Optimizar el tamaño de posición utilizando la programación cuadrática Ejecutar comercios para capturar oportunidades de spread En papel, el valor esperado fue sólidamente positivo. en la práctica: Día 1-3: Atrapado un gran pico, hizo $ 15,000 Día 4-12: Pequeñas pérdidas todos los días, total -$8,000 Día 13-14: Otro pico, hecho $ 12,000 Día 15-28: sangrado gradual, total -$11,000 El problema? Nuestro optimizador había desarrollado un vicio estructural. Estaba sistemáticamente tomando posiciones que ganaron grandes ocasionalmente pero perdieron pequeñas cantidades con frecuencia. El cálculo del valor esperado dijo que esto estaba bien: las grandes ganancias finalmente compensarían. pero "en definitiva" requiere capital infinito y horizonte de tiempo infinito. Nosotros no teníamos ninguno. Ver la diferencia: una simulación Para ilustrar por qué estos controles de riesgos son importantes, comparemos dos estrategias para negociar el mismo mercado durante un año: Dimensionamiento agresivo de la posición basado exclusivamente en el valor esperado, utilizando un apalancamiento del 150% cuando las oportunidades parecen buenas. Strategy A (EV Maximization) Las mismas señales de mercado, pero con tamaño fraccional de Kelly (40% de agresivo) y reducción de posición basada en CVaR durante períodos de alto riesgo de cola. Strategy B (Risk-Controlled) Los resultados dicen una historia crucial. Mire el gráfico izquierdo de cerca - la mayoría de los caminos de maximización de EV no fallan catastróficamente. Ellos son simplemente... no compounding. Puedes ver el patrón del sapo: ocasionales picos, seguido de erosión lenta. Este es el sangrado insidioso que el valor esperado positivo se pierde. ¿Nota cómo unos pocos caminos alcanzaron los 500.000 dólares?Ellos sacan la media hasta los 146.000 dólares. es sólo $ 136k, y 29 de los 100 caminos terminan por debajo del capital inicial. Mediana In a backtest, you might have gotten lucky and seen one of those winner paths. In production, you get one random draw. El gráfico correcto es "aburrido", y ese es exactamente el punto. No hay fotos de la luna hasta $ 500k, pero también no hay retrasos catastróficos. La estrategia controlada por riesgos se aglomera estrechamente alrededor de un crecimiento modesto. Esta es la realidad de la producción: la estrategia que sobrevive se compone.La estrategia que sangra no hace nada, independientemente de lo que prometió el cálculo del valor esperado. Lo que el valor esperado no captura Riesgo de ruina Este es el problema del jugador clásico, formalizado por el Criterio de Kelly. Incluso con un valor esperado positivo, si su tamaño de posición es incorrecto, usted Vaya a romper. Will Considera: Tienes $100,000 de capital y un comercio con una probabilidad de ganar del 60% que duplica tu apuesta o la pierde.El valor esperado es positivo (+20%).Pero si apuestas todo, tienes una probabilidad de perder todo en el primer comercio. Kelly dice que el tamaño óptimo de la apuesta es: kelly_fraction = (p * b - q) / b # where p = win probability, q = loss probability, b = odds Pero aquí está lo que aprendimos en la producción: . even Kelly is too aggressive ¿Por qué? porque: Sus estimaciones de probabilidad están equivocadas (siempre) Los mercados cambian (su 60% de ventaja se convierte en 52%) Las correlaciones se rompen durante el estrés (cuando lo necesitas más) No se puede reequilibrar de inmediato (deslizamiento, latencia, impacto en el mercado) Terminamos usando Kelly fraccional (25-50% de la apuesta teórica de Kelly) porque los costos del mundo real de sobreestimar su margen son catastróficos. Inestabilidad numérica en eventos extremos Una mañana, nuestro sistema se estrelló durante un evento meteorológico extremo.No un accidente de software, sino un accidente matemático. Nuestra matriz de covarianza se convirtió en singular.El optimizador no pudo encontrar una solución.Estábamos congelados, incapaces de negociar, durante las condiciones exactas en las que nuestra estrategia debería haber hecho más dinero. El problema: habíamos optimizado para los escenarios esperados.Pero los eventos extremos tienen diferentes estructuras de correlación.Los activos que normalmente se mueven de forma independiente de repente se correlacionan perfectamente.Su matriz de covarianza cuidadosamente estimada, construida a partir de miles de días normales, se vuelve inútil. La corrección no era mejor que los cálculos de valor esperados. : regularization from sklearn.covariance import LedoitWolf # Instead of sample covariance cov_matrix = np.cov(returns.T) # Use shrinkage towards structured estimator lw = LedoitWolf() cov_matrix_robust = lw.fit(returns).covariance_ Esto dispara cierta precisión en tiempos normales para la estabilidad en extremos. Sus cálculos de valor esperado serán ligeramente peores. Desacuerdo de Horizon Aquí hay un problema que no aparece en las pruebas de retroceso: su cálculo del valor esperado asume que puede esperar lo suficiente para que la ley de los números grandes funcione. En la producción no se puede. Lo descubrimos cuando nuestro sistema mostró un valor esperado positivo fuerte sobre las ventanas de 90 días pero perdió constantemente dinero sobre las ventanas de 30 días. Nuestros proveedores de capital revisaron el rendimiento mensualmente.Nuestros límites de riesgo se ajustaron trimestralmente en función de los resultados recientes.Si tuvimos tres meses malos, nuestros límites de posición se cortaron, independientemente de lo que dijera el valor esperado a largo plazo. La estrategia teórica tomó 6-12 meses para mostrar de forma fiable el beneficio.La realidad operativa nos dio 3 meses antes de que las consecuencias comenzaran. Hemos tenido que agregar restricciones explícitas de horizonte temporal a nuestra optimización: def optimize_with_horizon_constraint(scenarios, max_horizon_days=30): """ Optimize not just for long-term EV, but for probability of positive returns within operational time horizon """ # Standard expected value ev = np.mean(scenarios) # But also: what'sthe probability we're profitable # within our actual time horizon? rolling_returns = pd.Series(scenarios).rolling(max_horizon_days).sum() prob_profitable_in_horizon = (rolling_returns > 0).mean() # Penalize strategies with low short-term win probability # even if long-term EV is great if prob_profitable_in_horizon < 0.6: return ev * 0.5 # Heavily discount return ev Esto significaba aceptar estrategias con un valor esperado teórico ligeramente menor, pero con una mayor probabilidad de mostrar ganancias dentro de nuestras limitaciones operativas. Qué optimizar en lugar de Después de las dolorosas lecciones, aquí está lo que aprendimos a optimizar para: Retorno ajustado al riesgo con CVaR En lugar de maximizar E[beneficio], minimizamos CVaR (Valor Condicional en Riesgo): la pérdida esperada en el peor 5% de los escenarios import cvxpy as cp # Decision variable: position sizes positions = cp.Variable(n_assets) # Scenarios returns scenario_returns = get_price_scenarios() # shape: (n_scenarios, n_assets) portfolio_returns = scenario_returns @ positions # CVaR constraints alpha = 0.05 # 5% tail var = cp.Variable() u = cp.Variable(n_scenarios) constraints = [ u >= 0, u >= -(portfolio_returns - var), ] cvar = var + cp.sum(u) / (n_scenarios * alpha) # Optimize for return while constraining tail risk objective = cp.Maximize(cp.sum(portfolio_returns) / n_scenarios - lambda_risk * cvar) Esto penaliza explícitamente las estrategias que tienen buenos retornos medios pero un riesgo de cola catastrófico. Robustez a error de modelo Suponemos que nuestro modelo está equivocado y optimizamos para el dentro de un límite de incertidumbre razonable: El peor caso # Instead of single expected return estimate mu_estimated = historical_returns.mean() # Assume uncertainty mu_lower_bound = mu_estimated - 2 * historical_returns.std() / np.sqrt(len(historical_returns)) # Optimize for worst-case in uncertainty range # (Robust optimization / minmax approach) Esto protege contra las estimaciones de parámetros demasiado confiables. Tamaño de posición Kelly-Constrainted Limitamos explícitamente los tamaños de posición basados en el criterio de Kelly, incluso cuando el optimizador quiere más: def kelly_position_limit(edge, volatility, capital, max_kelly_fraction=0.25): """ edge: expected return per unit risk volatility: standard deviation of returns max_kelly_fraction: fraction of theoretical Kelly to actually use """ kelly_full = edge / (volatility ** 2) kelly_fraction = capital * kelly_full * max_kelly_fraction return kelly_position Usamos el 25% Kelly como una restricción dura. Sí, esto reduce el valor esperado. También garantiza que todavía estaremos negociando el próximo mes. El pensamiento de producción El cambio del pensamiento del valor esperado al pensamiento de la producción es filosófico: “¿Qué estrategia tiene el mayor retorno esperado?” Research mindset "¿Qué estrategia sobrevivirá si estoy equivocado en mis suposiciones?" Production mindset Aquí están los cambios prácticos que hicimos: Backtests: análisis de peores meses agregados, no solo retornos medios Tamaño de posición: Conservador por defecto, con kill-switches para anomalías Metría de riesgo: rastrear CVaR diariamente, no solo P&L Validación del modelo: Asume un 30% de incertidumbre de parámetros en todas las estimaciones Planificación de desastres: rutas de código explícitas para los escenarios de "modelo está completamente equivocado" La lección El valor esperado es un concepto matemático hermoso, limpio, intuitivo y teóricamente óptimo. Tampoco es suficiente. En la producción, no está negociando contra una distribución de probabilidad. Los propios modelos de riesgo imperfectos Los mercados que cambian Restricciones operativas que no están en tu backtest La realidad psicológica de ver su capital disminuir día tras día a pesar de que el "valor esperado es positivo" Los sistemas que sobreviven no son los que tienen el valor esperado más alto; son los que permanecen robustos cuando el modelo está equivocado, los mercados se desplazan y aparecen cisnes negros. Optimizar para la supervivencia primero. rentabilidad segundo. valor esperado es un componente de ese cálculo, pero no es la función objetiva.