Simple Moving Average - SMA (Rolling Mean)

Simple Moving Average (Rolling Mean)

The Problem First

Imagine you're tracking your daily steps for a week:

Mon: 3,000 | Tue: 12,000 | Wed: 2,500 | Thu: 11,000 | Fri: 4,000 | Sat: 13,000 | Sun: 3,500

The numbers jump up and down wildly. It's hard to answer: "Am I generally becoming more active or not?"

This is the core problem — raw data is noisy. Moving Average solves this.


What is Moving Average?

Moving Average = Average of the last N values, calculated at every step

Instead of looking at one day's value, you look at the average of the last few days. Then you "move" forward one step and calculate again.


Simple Example — Window Size = 3

Your daily steps:

Day

Steps

3-Day Moving Avg

Mon

3,000

Tue

12,000

Wed

2,500

(3000+12000+2500)/3 = 5,833

Thu

11,000

(12000+2500+11000)/3 = 8,500

Fri

4,000

(2500+11000+4000)/3 = 5,833

Sat

13,000

(11000+4000+13000)/3 = 9,333

Sun

3,500

(4000+13000+3500)/3 = 6,833

 See what happened? The moving average values — 5833 → 8500 → 5833 → 9333 → 6833 — are much smoother than the original jumpy numbers.


Why Do We Use It?

1. To remove noise Raw data has random spikes that don't mean anything. Moving average filters them out so you see the real trend.

2. To see the big picture Instead of asking "did I walk a lot today?", you ask "have I been walking more this week overall?" — much more meaningful.

3. Used everywhere in real life

  • 📈 Stock market — 50-day and 200-day moving averages tell traders the trend direction
  • 🌡️ Weather — "average temperature this month" smooths daily fluctuations
  • 🏪 Sales forecasting — businesses predict next month's sales using past months' averages
  • 🤖 ML / Time Series — it's a classic feature used in models to capture trends

The "Window" Concept

The window size (N) controls how smooth vs. sensitive the average is:

Window Size

Effect

Small (N=2 or 3)

Reacts quickly to changes, still a bit noisy

Large (N=7 or 30)

Very smooth, but slow to react to new changes

Think of it like sunglasses — darker glasses block more light (more smoothing), but you also miss some details.

Where Moving Average is Actually Used (ML/Data Science Context)

1. Time Series Forecasting

When you have data over time — stock prices, sales, temperature, website traffic — raw data is too noisy to feed directly into a model. Moving average smooths it first, making patterns clearer for the model to learn.

2. Feature Engineering

This is the biggest use case for you as an ML engineer.

Before training a model, you create new columns like:

  • price_7day_avg — average price of last 7 days
  • sales_30day_avg — average sales of last 30 days

These features help the model understand "what has been happening recently" — which a single day's value can't tell.

3. Anomaly Detection

If today's value is very far from the moving average, it's probably an anomaly — fraud, system failure, sudden spike. Moving average becomes your baseline to compare against.

4. Signal Smoothing (before EDA or Visualization)

Before you even plot data, applying moving average removes visual noise so you can actually see the trend in your EDA (Exploratory Data Analysis).

5. Stock/Finance Models

Classic use — 50-day MA crossing 200-day MA is a buy/sell signal. If you ever build a finance-related ML model, this will be a standard feature.


Python Program


    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt

    # --- Sample Data: Daily Sales for 15 days ---
    data = {
        'day': list(range(1, 16)),
        'sales': [200, 450, 180, 500, 220, 480, 210, 460, 190, 510, 230, 490, 200, 470, 215]
    }

    df = pd.DataFrame(data)

    # --- Calculate Moving Averages ---
    df['SMA_3'] = df['sales'].rolling(window=3).mean()   # 3-day simple moving avg
    df['SMA_7'] = df['sales'].rolling(window=7).mean()   # 7-day simple moving avg
    df['EMA_3'] = df['sales'].ewm(span=3, adjust=False).mean()  # 3-day exponential moving avg

    print(df.to_string(index=False))

    # --- Plot ---
    plt.figure(figsize=(12, 5))
    plt.plot(df['day'], df['sales'],  label='Raw Sales',  marker='o', linewidth=1.5)
    plt.plot(df['day'], df['SMA_3'],  label='SMA (3-day)', linewidth=2)
    plt.plot(df['day'], df['SMA_7'],  label='SMA (7-day)', linewidth=2)
    plt.plot(df['day'], df['EMA_3'],  label='EMA (3-day)', linewidth=2, linestyle='--')

    plt.title('Moving Average on Sales Data')
    plt.xlabel('Day')
    plt.ylabel('Sales')
    plt.legend()
    plt.grid(True)
    plt.tight_layout()
    plt.savefig('moving_average.png')
    plt.show()
    print("Plot saved!")


Output:

day sales SMA_3 SMA_7 EMA_3 1 200 NaN NaN 200.000000 2 450 NaN NaN 325.000000 3 180 276.666667 NaN 252.500000 4 500 376.666667 NaN 376.250000 5 220 300.000000 NaN 298.125000 6 480 400.000000 NaN 389.062500 7 210 303.333333 320.000000 299.531250 8 460 383.333333 357.142857 379.765625 9 190 286.666667 320.000000 284.882812 10 510 386.666667 367.142857 397.441406 11 230 310.000000 328.571429 313.720703 12 490 410.000000 367.142857 401.860352 13 200 306.666667 327.142857 300.930176 14 470 386.666667 364.285714 385.465088 15 215 295.000000 329.285714 300.232544 Plot saved!



What Each Line Does

Code

What it does

rolling(window=3).mean()

SMA — simple average of last 3 values

rolling(window=7).mean()

SMA — wider window, smoother line

ewm(span=3).mean()

EMA — gives more weight to recent values


Output You'll See

  • First 2 rows of SMA_3 will be NaN — that's normal, because you need at least 3 values to start calculating
  • First 6 rows of SMA_7 will be NaN — same reason
  • EMA has no NaN — it starts calculating from day 1

Real ML Usage (Feature Engineering snippet)


    # In a real ML project, you'd add these as features before training
    df['sales_lag1']  = df['sales'].shift(1)         # yesterday's sales
    df['sales_sma3']  = df['sales'].rolling(3).mean() # 3-day avg (trend feature)
    df['sales_sma7']  = df['sales'].rolling(7).mean() # 7-day avg (long trend)
    df['sales_ema3']  = df['sales'].ewm(span=3, adjust=False).mean()

    # Then drop NaN rows before training
    df.dropna(inplace=True)

    # Now df is ready to be fed into your ML model
    X = df[['sales_lag1', 'sales_sma3', 'sales_sma7', 'sales_ema3']]
    y = df['sales']

This is exactly how time series feature engineering is done in real projects — you create these rolling features and feed them to models like XGBoost, LSTM, or Linear Regression.


One Line Summary

Moving Average takes the average of the last N data points and slides that window forward — turning noisy, jumpy data into a smooth trend line.

That's it! Once you get this idea, SMA and EMA (which you've seen before) are just variations on top of this same concept.

No comments:

Post a Comment

Phase 5 - Caching | Post 9 | Caching — Making Your Services Fast With Zero Extra Effort

Post 9 of 15 | Phase 5: Caching Caching — Making Your Services Fast With Zero Extra Effort In the previous post you learned how to keep your...