Una técnica común para optimizar los parámetros de una estrategia de trading es utilizar una búsqueda por fuerza bruta. Esto implica probar una variedad de valores para los parámetros y seleccionar aquellos que produzcan los mejores resultados. A continuación te presento un ejemplo de cómo hacer una optimización de los parámetros de una estrategia de trading en Python:
Supongamos que tienes una estrategia que utiliza dos indicadores, la media móvil (MA) de 50 días y la media móvil exponencial (EMA) de 200 días. Estás buscando los valores óptimos para los siguientes parámetros:
- El umbral de la MA: el porcentaje superior o inferior en el que la MA indicará una señal de compra o venta (por ejemplo, si la MA sube un 2% por encima del precio actual, significaría una señal de compra).
- El umbral de la EMA: lo mismo que el umbral de la MA, pero para la EMA.
- El período de espera: el número de días que esperarías para abrir una posición después de recibir una señal de compra o venta.
Para optimizar estos parámetros, podríamos seguir los siguientes pasos:
- Cargar los datos históricos de precios para la acción que quieres operar. En este ejemplo, podemos usar la biblioteca yfinance para cargar los precios de las acciones de Apple desde 2010 hasta la fecha actual:
import yfinance as yf
ticker = "AAPL"
start_date = "2010-01-01"
end_date = "2021-01-01"
prices = yf.download(ticker, start=start_date, end=end_date)
- Definir una función para ejecutar la estrategia de trading con los parámetros dados y devolver el rendimiento acumulado. En este ejemplo, suponemos que el rendimiento se mide simplemente como la diferencia entre el precio de venta y el precio de compra de todas las operaciones abiertas durante el período de prueba:
def run_strategy(prices, ma_threshold, ema_threshold, wait_period):
ma = prices["Adj Close"].rolling(window=50).mean()
ema = prices["Adj Close"].ewm(span=200).mean()
buy_price, sell_price, is_holding = None, None, False
pnl = 0
for i in range(len(prices)):
if not is_holding and ma[i] * (1 + ma_threshold) < prices["Adj Close"][i]:
buy_price = prices["Adj Close"][i]
is_holding = True
elif is_holding and ma[i] * (1 - ma_threshold) > prices["Adj Close"][i]:
sell_price = prices["Adj Close"][i]
pnl += sell_price - buy_price
is_holding = False
if not is_holding and ema[i] * (1 + ema_threshold) < prices["Adj Close"][i]:
buy_price = prices["Adj Close"][i]
is_holding = True
elif is_holding and ema[i] * (1 - ema_threshold) > prices["Adj Close"][i]:
sell_price = prices["Adj Close"][i]
pnl += sell_price - buy_price
is_holding = False
if is_holding and i == len(prices) - 1:
sell_price = prices["Adj Close"][i]
pnl += sell_price - buy_price
if is_holding and i - wait_period >= 0:
sell_price = prices["Adj Close"][i]
pnl += sell_price - buy_price
is_holding = False
return pnl
- Definir una función para ejecutar la búsqueda por fuerza bruta. En este ejemplo, probamos 5 valores diferentes para cada parámetro, lo que nos da un total de 125 combinaciones diferentes que se probarán:
import itertools
def optimize_strategy(prices):
ma_thresholds = [-0.02, -0.01, 0, 0.01, 0.02]
ema_thresholds = [-0.02, -0.01, 0, 0.01, 0.02]
wait_periods = [0, 1, 2, 3, 4]
best_params = None
best_pnl = float("-inf")
for params in itertools.product(ma_thresholds, ema_thresholds, wait_periods):
pnl = run_strategy(prices, *params)
if pnl > best_pnl:
best_params = params
best_pnl = pnl
return best_params, best_pnl
- Ejecutar la optimización e imprimir los resultados:
best_params, best_pnl = optimize_strategy(prices)
print("Best parameters:", best_params)
print("Best PNL:", best_pnl)