Evolutionary search as an alpha hypothesis generator. Fitness design, selection pressure, and rigorous out-of-sample validation for trading strategies.
Most alpha research pipelines still rely on human-guided search. This paper explores genetic algorithms as an alternative for automated strategy discovery, where candidate trading rules evolve through selection, crossover, and mutation. We formalize fitness function design with penalized objectives and demonstrate a minimal GA implementation, while emphasizing that robust validation -- not raw optimization power -- determines whether discovered strategies survive out-of-sample.
Most alpha research pipelines still rely on human-guided search. Genetic algorithms offer an alternative — instead of hand-designing every parameter combination, we let a population of candidate strategies evolve through selection, crossover, and mutation. Trading rules often define non-convex search spaces where gradient methods do not fit naturally and brute force quickly becomes expensive.
A strategy chromosome might encode: feature choices, lookback windows, threshold values, position sizing rules, stop-loss or take-profit logic, and rebalance frequency. The fitness function should not reward raw return alone:
This matters because the optimizer will exploit whatever you reward. If you maximize in-sample Sharpe without penalties, the algorithm may discover hyperactive, brittle, or capacity-blind rules.
import random import numpy as np def strategy_fitness(params, prices): short_win, long_win, threshold = params if short_win >= long_win: return -1e6 short_ma = prices.rolling(short_win).mean() long_ma = prices.rolling(long_win).mean() signal = (short_ma / long_ma - 1 > threshold).astype(int) - \ (short_ma / long_ma - 1 < -threshold).astype(int) ret = signal.shift(1) * prices.pct_change() sharpe = np.sqrt(252) * ret.mean() / ret.std() if ret.std() > 0 else -999 turnover = signal.diff().abs().mean() return sharpe - 0.5 * turnover def mutate(params): p = params.copy() idx = random.randint(0, 2) if idx == 0: p[0] = max(2, p[0] + random.randint(-3, 3)) elif idx == 1: p[1] = max(5, p[1] + random.randint(-5, 5)) else: p[2] = max(0.0, p[2] + random.uniform(-0.01, 0.01)) return p
Evolutionary search is powerful precisely because it can overfit aggressively. A robust workflow uses nested validation, purged cross-validation, parameter stability checks, transaction-cost modeling, and inferential metrics such as PSR or deflated Sharpe. The best way to think about GA in quant finance is not "automatic profit machine," but automated hypothesis generator.