Skip to content

Buy and Hold Strategy

The simplest investment strategy - buy a stock and hold it for the entire period.

Strategy Overview

Concept: Buy once at the beginning and hold until the end
Complexity: Beginner
Time Frame: Long-term (months to years)
Best For: Learning backtesting basics, benchmark comparison

Code Example

python
def on_strategy_start(portfolio, state):
    """Initialize - called once at backtest start"""
    print("=== Buy and Hold Strategy Started ===")
    print(f"Initial Capital: ${portfolio.initial_capital:,.2f}")
    
    # Track if we've made our initial purchase
    state['purchased'] = False

def on_bar_close(data_contexts, portfolio, state):
    """Buy once at the very beginning and hold"""
    
    # Only buy once at the start
    if not state['purchased'] and portfolio.position('AAPL') == 0:
        
        # Calculate how many shares we can buy with all our cash
        current_price = data_contexts['AAPL'].close
        max_shares = int(portfolio.cash / current_price)
        
        print(f"Making initial purchase: {max_shares} shares at ${current_price:.2f}")
        state['purchased'] = True
        
        return {
            'symbol': 'AAPL',
            'action': 'buy', 
            'quantity': max_shares
        }
    
    # After initial purchase, just hold (do nothing)
    return None

Expected Results

Typical Performance (varies by time period):

  • Total Return: Matches market performance
  • Sharpe Ratio: 0.8 - 1.2 (depends on period)
  • Max Drawdown: Follows market drawdowns
  • Win Rate: N/A (single trade)

Key Learnings

1. Benchmark Performance

Buy-and-hold provides a baseline to compare other strategies against.

2. Market Risk

Your performance directly tracks the underlying stock's movement.

3. Simplicity Works

Sometimes the simplest strategies are hard to beat.

Variations

Multi-Asset Buy and Hold

python
SYMBOLS = ['AAPL', 'GOOGL', 'MSFT']

def on_bar_close(data_contexts, portfolio, state):
    if not state.get('purchased', False):
        orders = []
        cash_per_stock = portfolio.cash / len(SYMBOLS)
        
        for symbol in SYMBOLS:
            price = data_contexts[symbol].close
            shares = int(cash_per_stock / price)
            
            orders.append({
                'symbol': symbol,
                'action': 'buy',
                'quantity': shares
            })
        
        state['purchased'] = True
        return orders
    
    return None

Dollar-Cost Averaging

python
def on_bar_close(data_contexts, portfolio, state):
    """Buy fixed dollar amount every month"""
    
    # Initialize purchase tracking
    if 'last_purchase_day' not in state:
        state['last_purchase_day'] = 0
        state['monthly_investment'] = 1000  # $1000 per month
    
    # Get current day (assuming daily data)
    current_day = state.get('current_day', 0)
    state['current_day'] = current_day + 1
    
    # Buy every 30 days (monthly)
    if current_day - state['last_purchase_day'] >= 30:
        price = data_contexts['AAPL'].close
        shares = int(state['monthly_investment'] / price)
        
        if portfolio.cash >= (shares * price):
            state['last_purchase_day'] = current_day
            
            return {
                'symbol': 'AAPL',
                'action': 'buy',
                'quantity': shares
            }
    
    return None

When to Use

Good For:

  • Learning backtesting basics
  • Long-term investing simulation
  • Benchmark comparison
  • Testing market timing strategies

Not Good For:

  • Active trading strategies
  • Short-term performance
  • Risk management learning

Next Steps


This strategy teaches the fundamentals of backtesting without complex logic.

Test your trading strategies risk-free with professional backtesting.