Skip to content
ML Academy

Week 5 · Sunday — consolidate and defend

Forecasting studio 5: repair an invalid backtest and explain horizon and segment errors

Project thread forecasting · linked lessons day 21, day 22, day 23, day 24, day 25

Milestone W5-b: a repaired backtest with every flaw documented, an evidence-based explanation of horizon and segment error differences, and pre-registered Week 6 freeze criteria. Together with Saturday, this is the Week 5 main evidence in Appendix C: backtest configuration and results, and demonstrated cutoff correctness.

  • 90 minsession length
  • 4timed blocks
  • 5tasks
  • —status

Session plan90 min

  1. 20′Spaced recall
  2. 40′Improve - inspect and repair an invalid backtest
  3. 20′Teach-back - why the repaired numbers differ
  4. 10′Weekly review and planning

Before you start

Prepare before the session (2 minutes). Save the following as forecasting-project/review/flawed_w05.py. It is scaffolding with deliberate flaws, so do not reuse it.

# flawed_w05.py - a rolling-origin backtest for the D-14 forecast (contains deliberate flaws; do not reuse)
import sqlite3
import pandas as pd
from sklearn.ensemble import HistGradientBoostingRegressor
from sklearn.metrics import mean_absolute_error

con = sqlite3.connect("python/artifacts/airline_sample.sqlite")
df = pd.read_sql("""
    SELECT f.date, f.flight_no, f.route, f.weekday, f.holiday, f.capacity, f.competitor_price,
           f.bookings_final, b.cumulative_bookings AS bk_d14
    FROM flight_day f
    JOIN booking_curve b ON b.date = f.date AND b.flight_no = f.flight_no AND b.days_to_departure = 14
""", con, parse_dates=["date"]).sort_values(["flight_no", "date"])

g = df.groupby("flight_no")["bookings_final"]
df["lag_7"] = g.shift(7)
df["roll_28"] = g.transform(lambda s: s.rolling(28, min_periods=7).mean())
df["snaive_364"] = g.shift(364)
feats = ["weekday", "holiday", "capacity", "competitor_price", "bk_d14", "lag_7", "roll_28"]

rows = []
for origin in pd.date_range("2023-07-01", "2024-06-01", freq="MS"):
    train = df[df["date"] < origin]
    test = df[(df["date"] >= origin) & (df["date"] < origin + pd.DateOffset(months=1))]
    m = HistGradientBoostingRegressor(random_state=0).fit(train[feats], train["bookings_final"])
    rows.append({"origin": origin.date(),
                 "mae_model": mean_absolute_error(test["bookings_final"], m.predict(test[feats])),
                 "mae_snaive": mean_absolute_error(test["bookings_final"], test["snaive_364"])})

res = pd.DataFrame(rows)
print(res.round(1).to_string(index=False))
print("mean MAE model", round(res["mae_model"].mean(), 1), "| seasonal naive", round(res["mae_snaive"].mean(), 1))

Run it from the repository root with uv run --project python python forecasting-project/review/flawed_w05.py. It takes well under a minute on a laptop. You also need your Saturday files: configs/backtest_w05.yaml, outputs/backtest_w05.csv, the availability-check code and the contract. The colleague and the RM lead are simulated.

Blocks4

  1. Block 1: Spaced recall

    20 min

    Answer the prompts in task recall-week5 closed-book (12 minutes). Then check them against lessons 21-25 and your recall log (8 minutes), and log misses with corrections. Include at least one item that you missed in Weeks 2-4.

  2. Block 2: Improve - inspect and repair an invalid backtest

    40 min

    A simulated colleague's backtest, review/flawed_w05.py (see setup), reports excellent skill against seasonal naive.

    1. Minutes 0-5 - commit. Run it, note the printout, and write one sentence on whether you trust it, before you read the code closely.
    2. Minutes 5-20 - find the flaws (task review-backtest).
    3. Minutes 20-32 - repair (task repair-backtest). Repair using your Saturday cutoff checks, then re-run.
    4. Minutes 32-40 - explain (task explain-errors). Explain the horizon and segment differences in your own backtest.

    If Saturday's candidate was carried forward, run it in the first 15 minutes and repair only the two most severe flaws.

  3. Block 3: Teach-back - why the repaired numbers differ

    20 min

    Explain to a simulated RM lead, in at most 200 words written or 3 minutes spoken (task teach-back):

    • why the colleague's backtest looked better;
    • what the repaired and your own backtests show by horizon and market;
    • which forecast you would trust for which segment.

    Then answer the lead's simulated follow-up question.

  4. Block 4: Weekly review and planning

    10 min

    Week 5 review in decision-log.md:

    • lessons 21-25 status;
    • studio status;
    • recall misses.

    Write the Week 6 freeze criteria now, before any test data is seen. These are the rules that will pick the final design from backtest evidence, for example "the lowest mean decision cost across origins, with skill below 1 on at least 9 of 12 origins; otherwise the pickup baseline".

Tasks5

Sign in to save your work.
  1. Task 1

    recall

    Answer closed-book:

    1. Name three ways a structural break differs from seasonality in a plot.
    2. What does an ACF spike at lag 7 in daily departures suggest? What does it not prove?
    3. Why can over-differencing hurt?
    4. Why is AIC not out-of-sample accuracy?
    5. What is the minimum safe lag of bookings_final for a D-14 forecast, and why?
    6. Expanding vs sliding window: when does each help?
    7. Why report error per horizon instead of pooled?
    8. Give one item missed in Weeks 2-4.

    The expected evidence for this task is shown after you save your own output.

  2. Task 2

    review

    List every flaw in flawed_w05.py with its line, the mechanism, and whether it inflates the model's score, the baseline's score, or only the reporting. Rank them by severity.

    The expected evidence for this task is shown after you save your own output.

  3. Task 3

    code

    Write review/repaired_w05.py: the smallest version that removes every flaw you listed in review-backtest. It must follow your Saturday conventions (contract, horizon-specific gaps, baselines) and report per origin and per market next to the baselines of your own backtest.

    Run your Saturday availability check against its features. Compare its results with the flawed printout and with your own backtest_w05.csv.

    The expected evidence for this task is shown after you save your own output.

  4. Task 4

    analysis

    Using backtest_w05.csv, explain:

    • (a) the D-30 against D-14 difference for the pickup baseline;
    • (b) why the seasonal naive's error does or does not depend on horizon, given what it uses;
    • (c) the market differences;
    • (d) whether the three 2024-03-01 break routes behave differently in origins after March 2024.

    Cite numbers for each.

    The expected evidence for this task is shown after you save your own output.

  5. Task 5

    defense

    Write or record the explanation for the simulated RM lead (at most 200 words). Then answer the follow-up question, "So should we stop using the seasonal naive?", in at most 60 words.

    The expected evidence for this task is shown after you save your own output.

Rubric4 criteria

CriterionMeetsExceeds
Backtest flaw detectionAt least four of the six flaws are identified, including the ones that directly break the D-14 cutoff.All six are identified and ranked, with an ablation showing which flaw causes most of the inflation.
Repair and verificationThe repaired backtest runs, passes the availability check, and is compared with the learner's own backtest.The repair reuses the project's backtest function and configuration rather than duplicating logic. Remaining differences are fully reconciled.
Horizon and segment explanationHorizon and market differences are explained with numbers and plausible mechanisms.Separates evidence from hypothesis, notes how few post-break origins exist, and says what further evidence would settle the question.
Pre-registrationWeek 6 freeze criteria are written before any test data are seen.The criteria include a fallback rule and a decision-cost criterion, not only MAE.

Required output

Saved in forecasting-project/:

  • review/backtest-review-w05.md, with the committed sentence, the ranked flaws and the comparison table;
  • review/repaired_w05.py, runnable, with its availability-check output;
  • the four error explanations and the teach-back text;
  • the pre-registered Week 6 freeze criteria in decision-log.md;
  • updated notes/recall-log.md.

This completes the Week 5 main evidence: backtest configuration and results, and demonstrated cutoff correctness.

Studios are tracked separately from the 60 core lessons; completing one never completes a lesson.