Overview of Quantitative Trading Strategies › Common Pitfalls in Strategy Development
Quantitative FinanceAll chapters Overview of Quantitative Trading Strategies › Common Pitfalls in Strategy DevelopmentOne section · Sections in this chapter6 / 9 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
The gap between backtested and live trading performance is one of the most frustrating aspects of quantitative finance. Strategies that look phenomenal in historical testing often fail in production. Understanding the common pitfalls helps avoid them.
Look-Ahead Bias
Look-ahead bias occurs when the backtest uses information that wasn't available at the time. Examples include:
- Using end-of-day prices for decisions made during trading hours
- Using revised financial data instead of originally reported values
- Assuming instant knowledge of index reconstitutions or corporate actions
This bias is insidious because it's often unintentional. Data vendors typically provide "as-is" data reflecting current knowledge, not point-in-time data showing what was known historically.
Survivorship Bias
Survivorship bias results from testing only on securities that survived to the present, ignoring those that delisted, went bankrupt, or were acquired. This systematically overestimates returns because the worst performers are excluded.
Consider a value strategy that buys cheap stocks. Many cheap stocks are cheap because they're headed toward bankruptcy. A survivorship-biased backtest never sees these losses because those companies aren't in the database.
Overfitting and Data Snooping
Overfitting occurs when a model captures noise in the training data rather than predictive signal. The model performs well historically but fails on new data.
Signs of overfitting include:
- Strategy requires many parameters or complex rules
- Performance is sensitive to small parameter changes
- Out-of-sample performance degrades significantly
- Strategy works only on specific subperiods
The antidote is simplicity, economic rationale, and rigorous out-of-sample testing. As a rule of thumb, simpler strategies with clear economic logic are more likely to survive in live trading.
Transaction Cost Underestimation
Backtests often assume unrealistically low transaction costs. Real-world trading involves:
- Bid-ask spreads: The immediate cost of crossing the spread
- Market impact: Moving prices against you when trading large positions
- Slippage: Execution prices worse than expected due to latency
- Borrowing costs: Fees for shorting stocks, which can be substantial for hard-to-borrow names
def analyze_transaction_cost_sensitivity(returns, turnover, cost_levels):
"""
Analyze how performance degrades with different transaction cost assumptions.
"""
results = []
for cost in cost_levels:
adjusted_returns = returns.copy()
# Subtract transaction costs (turnover * cost per period)
adjusted_returns = adjusted_returns - turnover.mean() * cost
annual_return = adjusted_returns.mean() * 12
annual_vol = adjusted_returns.std() * np.sqrt(12)
sharpe = annual_return / annual_vol if annual_vol > 0 else 0
results.append(
{
"Cost (bps)": cost * 10000,
"Annual Return": annual_return,
"Sharpe Ratio": sharpe,
}
)
return pd.DataFrame(results)cost_levels = [0, 0.001, 0.002, 0.005, 0.01, 0.02]
sensitivity = analyze_transaction_cost_sensitivity(
strategy_returns, strategy_turnover, cost_levels
)Transaction Cost Sensitivity Analysis
==================================================
Cost (bps) Annual Return Sharpe Ratio
0 62.44% 13.46
10 62.11% 13.39
20 61.79% 13.32
50 60.80% 13.11
100 59.16% 12.75
200 55.87% 12.04
The table reveals how sensitive the strategy is to transaction cost assumptions. A strategy that looks profitable at 10 basis points per trade might be worthless at 50 basis points. High-turnover strategies are particularly vulnerable.
Key Parameters
The key parameters for sensitivity analysis are:
- cost_levels: Range of transaction cost assumptions (0 to 200 bps). Tests how execution friction changes strategy results.
- turnover: The portfolio turnover rate. Determines how heavily transaction costs impact net returns.