Academy/Strategy Code Breakdown/Golden Cross — Code Walkthrough
Strategy Code BreakdownLesson 3

Golden Cross — Code Walkthrough

Understand the SMA calculation, why 50/200 periods are used, and how the Golden Cross and Death Cross crossover signals are detected.

9 minute read
4 key takeaways

Golden Cross — Code Walkthrough

The Golden Cross is one of the most well-known technical signals in finance. When the 50-day SMA crosses above the 200-day SMA, it signals a long-term bullish trend shift. Let's walk through every line of golden-cross-strategy.ts.

Step 1 — Configuration

typescript
export interface GoldenCrossConfig {
  fastPeriod: number;      // short-term SMA (default 50)
  slowPeriod: number;      // long-term SMA (default 200)
  stopLossPct: number;     // 0.10 = exit if price falls 10% from entry
  positionSizePct: number; // 0.20 = allocate 20% of portfolio per trade
}

export const defaultConfig: GoldenCrossConfig = {
  fastPeriod: 50,
  slowPeriod: 200,
  stopLossPct: 0.10,
  positionSizePct: 0.20,
};

50 and 200 are the canonical periods because they approximate 10-week and 40-week (roughly one trading year) timeframes. They're used by institutional investors as filters — many funds won't buy a stock trading below its 200-day SMA.

Step 2 — calculateSMA: Simple Moving Average

typescript
export function calculateSMA(closes: number[], period: number): number[] {
  return closes.map((_, i) => {
    if (i < period - 1) return NaN; // not enough history yet

    // slice the window, sum it, divide by period
    return closes.slice(i - period + 1, i + 1)
                 .reduce((a, b) => a + b, 0) / period;
  });
}

Performance Note

This SMA implementation is O(n × period) because it re-slices on every bar. For 200-period SMA over 5000 bars, that's 1,000,000 additions. A production system would use a running sum: add today's close, subtract the close that fell out of the window — O(n) total.

For a teaching tool and lab-scale backtests (< 10,000 bars), this is perfectly fine. The simplicity makes the logic transparent: you can read "slice from i-period+1 to i" and immediately understand the window.

Step 3 — generateSignals: Golden and Death Cross Detection

typescript
export function generateSignals(closes, config) {
  const fast = calculateSMA(closes, config.fastPeriod);   // 50-day SMA
  const slow = calculateSMA(closes, config.slowPeriod);   // 200-day SMA

  return closes.map((_, i) => {
    const smaFast = fast[i];
    const smaSlow = slow[i];

    // Skip until both SMAs have enough data (first 200 bars)
    if (isNaN(smaFast) || isNaN(smaSlow) || i === 0) {
      return { index: i, signal: 0, smaFast, smaSlow };
    }

    // Golden Cross: 50-day crossed ABOVE 200-day (yesterday it was below)
    const goldenCross = fast[i - 1] < slow[i - 1] && smaFast > smaSlow;

    // Death Cross: 50-day crossed BELOW 200-day (yesterday it was above)
    const deathCross = fast[i - 1] > slow[i - 1] && smaFast < smaSlow;

    const signal = goldenCross ? 1 : deathCross ? -1 : 0;
    return { index: i, signal, smaFast, smaSlow };
  });
}
ConditionSignalInterpretation
50 SMA crosses above 200 SMA+1 (BUY)Golden Cross — long-term bullish shift
50 SMA crosses below 200 SMA-1 (SELL)Death Cross — long-term bearish shift
No crossover this bar0 (HOLD)Trend continues, no action needed
Either SMA is NaN0 (HOLD)Insufficient history, skip bar

Signal Frequency

Golden/Death Crosses are rare — on daily SPY data you might see only 3–6 per year. This is a long-term trend strategy. Expect low trade frequency, but when it fires, the position is held for months.

Key Takeaways
  • SMA is the simplest average: sum of last N closes divided by N
  • Golden Cross (50 SMA crosses above 200 SMA) is a widely-followed bullish signal
  • Death Cross (50 SMA crosses below 200 SMA) is the bearish counterpart
  • The strategy needs 200 bars of data before it can generate any signal

Open Golden Cross Strategy in Lab

Clone the Golden Cross strategy and run a live backtest