Skip to main content

Strategy Basics

Every quantitative strategy follows a lifecycle. Understanding this lifecycle is the foundation of successful strategy development.

The Strategy Lifecycle​

Research → Develop → Backtest → Optimize → Deploy → Monitor
↑ │
└──────────────────── Iterate ←─────────────────────────┘

1. Research​

Before writing any code, answer:

  • What market inefficiency am I trying to exploit?
  • Why does it exist? (behavioral bias, structural friction, information asymmetry)
  • Will it persist? (or will it be arbitraged away?)
tip

The best strategies are built on understanding why something works, not just finding patterns in data.

2. Develop​

Convert your hypothesis into code:

from vecalpha import Strategy

class MomentumStrategy(Strategy):
"""Buy when price breaks above 20-day high."""

def on_bar(self, bar):
if self.position == 0:
if bar.close > self.high(20):
self.buy(size=self.calculate_position_size())
else:
if bar.close < self.low(10):
self.sell(size=self.position)

3. Backtest​

Test on historical data. Key questions:

  • Would this have made money?
  • What were the worst losses?
  • How does it perform in different market conditions?

4. Optimize​

Fine-tune parameters carefully:

  • Avoid overfitting
  • Use out-of-sample testing
  • Focus on robustness, not peak performance

5. Deploy​

Move to live trading:

  • Start with paper trading
  • Scale up gradually
  • Set risk limits

6. Monitor​

Track performance and iterate:

  • Compare live vs. backtest
  • Identify degradation early
  • Adapt to changing markets

Strategy Types​

Trend Following​

Capture sustained price movements.

Logic: Prices that have been rising tend to continue rising.

Indicators: Moving averages, breakout systems, ADX

Works best: Strong trending markets

Struggles: Sideways, choppy markets

Mean Reversion​

Profit from prices returning to average.

Logic: Extreme moves tend to reverse.

Indicators: Bollinger Bands, RSI, z-scores

Works best: Range-bound, choppy markets

Struggles: Strong trends

Statistical Arbitrage​

Exploit statistical relationships.

Logic: Related securities move together; divergences revert.

Indicators: Cointegration, correlation, pairs

Works best: Markets with related instruments

Struggles: Structural breaks, regime changes

Market Making​

Provide liquidity for spread capture.

Logic: Buy at bid, sell at ask, capture spread.

Indicators: Order book analysis, volatility

Works best: High-volume, liquid markets

Struggles: Fast markets, adverse selection


Strategy Components​

Every strategy needs these core components:

1. Data Input​

What data does your strategy consume?

# Example data requirements
data_config = {
'symbols': ['AAPL', 'MSFT'],
'timeframe': '1h',
'fields': ['open', 'high', 'low', 'close', 'volume'],
'start_date': '2020-01-01',
}

2. Signal Generation​

The logic that produces buy/sell signals.

def generate_signal(self, data):
"""Return: 1 (buy), -1 (sell), 0 (hold)"""
if condition_buy:
return 1
elif condition_sell:
return -1
return 0

3. Position Sizing​

How much to trade.

def calculate_position_size(self):
"""Risk-based position sizing."""
risk_per_trade = 0.02 # 2% of portfolio
stop_loss_distance = self.entry_price * 0.05 # 5% stop
position_size = (self.portfolio_value * risk_per_trade) / stop_loss_distance
return position_size

4. Risk Management​

Protect against losses.

risk_config = {
'max_position_size': 0.10, # Max 10% in one position
'max_drawdown': 0.15, # Stop if drawdown exceeds 15%
'max_correlation': 0.70, # Limit correlated positions
}

5. Execution​

How orders are placed.

execution_config = {
'order_type': 'limit', # or 'market'
'time_in_force': 'GTC', # Good Till Cancel
'slippage_tolerance': 0.001, # Max slippage
}

Common Pitfalls​

1. Overfitting​

Problem: Strategy works perfectly on historical data but fails in live trading.

Solution:

  • Use out-of-sample testing
  • Limit parameters
  • Focus on economic rationale, not just data mining

2. Look-Ahead Bias​

Problem: Using future information in signals.

Solution:

  • Always shift data properly
  • Test: "Could I have known this at trade time?"

3. Survivorship Bias​

Problem: Testing only on currently traded securities.

Solution:

  • Use survivorship-free data
  • Include delisted/bankrupt securities

4. Ignoring Costs​

Problem: Not accounting for commissions and slippage.

Solution:

  • Include realistic costs in backtests
  • Consider impact on high-frequency strategies

Your First Strategy​

Ready to build? Here's a template:

from vecalpha import Strategy, Backtest

class SimpleMovingAverageStrategy(Strategy):
"""Simple MA crossover strategy."""

def __init__(self):
self.short_window = 20
self.long_window = 50

def on_bar(self, bar):
# Calculate indicators
short_ma = self.sma(self.short_window)
long_ma = self.sma(self.long_window)

# Generate signals
if self.position == 0: # No position
if short_ma > long_ma:
self.buy(size=self.calculate_position_size())
else: # Have position
if short_ma < long_ma:
self.sell(size=self.position)

# Run backtest
results = Backtest(
SimpleMovingAverageStrategy,
symbol='AAPL',
start='2020-01-01',
end='2024-01-01',
initial_capital=100000
).run()

print(results.summary())

Next Steps​