An end-to-end portfolio system that turns deliberately imperfect synthetic aviation data into leakage-safe next-day hourly demand forecasts, calibrated uncertainty, staffing recommendations, fuel plans, and a Streamlit decision report.
Synthetic aviation portfolio project — not company operational data. Airport codes are geographic archetypes. Every operational value, threshold, price, planning rule, and result is invented for demonstration and is not Signature Aviation data.
At 18:00 local time, estimate arrivals for every hour of the next local calendar day at six FBO archetypes. Operations can use the P80 forecast to consider labor coverage and fuel buffers while managers can see uncertainty, capacity risks, and model reliability.
flowchart TD
A[Raw synthetic source systems] --> B[Bronze normalization]
B --> C[Validation + quarantine]
C --> D[Silver clean data]
D --> E[Forecast-origin gold features]
E --> F[Chronological split]
F --> G1[Seasonal naive]
F --> G2[Linear regression]
F --> G3[Per-FBO SARIMAX]
F --> G4[Global XGBoost]
G1 --> H[Comparison + champion]
G2 --> H
G3 --> H
G4 --> H
H --> I[80/95% calibrated intervals]
I --> J1[Staffing plan]
I --> J2[Fuel plan]
J1 --> K[Streamlit report]
J2 --> K
- Seven distinct source tables covering two full years and six FBO profiles.
- Negative-binomial-like over-dispersed counts with different intraday, weekly, seasonal, event, reservation, and weather behavior by FBO.
- Injected duplicates/revisions, malformed keys, negative impossibilities, missing forecasts, late ingestion, DST transitions, and legitimate event outliers. Counts are recorded in a manifest.
- A Python/Pandas data pipeline with explicit bronze, silver, quarantine, and gold layers.
- Pandera schema checks, natural-key/range/referential checks, saved failures, and quarantine instead of silent repair.
- A forecast-origin model table. Weather forecasts must be issued by the origin; reservations must already exist and future cancellation/no-show outcomes are excluded.
- Chronological train/validation/test partitions, seasonal-naive and linear baselines, global Poisson XGBoost, plus a callable per-FBO SARIMAX implementation. The default omits expensive SARIMAX backtesting; enable/run it explicitly on suitable compute.
- MAE, RMSE, WAPE, bias, peak/event errors, segment error analysis, and empirical FBO-level 80/95% intervals with global fallback.
- Synthetic staffing/fuel policy translation, integer shift optimizer, asymmetric policy cost, monitoring, stable Power BI exports, Docker, CI, linting, and tests.
| Bad | Implemented alternative |
|---|---|
| Tomorrow's actual weather | Latest forecast issued at or before forecast origin |
| Target-hour service/fuel/revenue/staffing | Reservations known before origin and historical demand only |
| Rolling window containing the target | Windows shifted to end before the earliest target horizon |
| Random row split | Calendar-based chronological split |
| Future cancellation/no-show outcome | Cancellation only if already known; no-show excluded |
UTC is the canonical key. Local timezone-aware timestamps exist only for operational interpretation, including repeated DST hours.
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python -m aviation_forecast.cli run-all
streamlit run report/app.pyIndividual stages are available through generate-data, build-data, validate, eda, train, forecast --origin ..., plan, and monitor. make test and make lint verify the code. Docker examples:
docker build -t synthetic-fbo .
docker run --rm -v "$PWD/data:/app/data" -v "$PWD/artifacts:/app/artifacts" synthetic-fbo run-all
docker run --rm -p 8501:8501 --entrypoint streamlit synthetic-fbo run report/app.py --server.address=0.0.0.0data/gold/forecast_training_examples.parquet: forecast-origin model examples.artifacts/metrics/model_comparison.csv: metrics created from actual execution; no scores are prewritten here.data/predictions/day_ahead_forecast.*: next-day P50/P80/P95 outputs.artifacts/planning/: staffing, fuel, and simulated impact tables.reports/: data-quality, EDA, model-error, and monitoring outputs.report/: five-page, artifact-only Streamlit report.
The final chronological test run produced the following network results:
| Model | MAE | RMSE | WAPE | Bias |
|---|---|---|---|---|
| Poisson HistGradientBoosting degraded mode | 0.316 | 0.626 | 11.89% | -0.020 |
| Linear Regression | 0.326 | 0.637 | 12.26% | -0.003 |
| Seasonal naive (lag 168) | 2.168 | 3.146 | 81.47% | -0.042 |
| Per-FBO SARIMAX | 2.175 | 3.196 | 81.72% | -2.027 |
Native XGBoost is installed but cannot load on this macOS host because libomp.dylib is absent.
The pipeline records this condition and uses sklearn's Poisson histogram gradient boosting as an
explicit degraded mode. On a host with OpenMP, the same training path instantiates XGBRegressor.
The SARIMAX convergence behavior and strong underforecast bias indicate that its compact
specification is not competitive here; this result is reported rather than manipulated.
This is synthetic and cannot estimate real commercial value. Event generation and staffing/fuel rules are simplified. The compact default prioritizes laptop reproducibility; full SARIMAX rolling fits and broader time-aware hyperparameter/ablation grids belong on scheduled compute. A production version would add source-owned contracts, orchestration, a registry, alert routing, forecast SLA/freshness checks, retraining approval, and rollback to a reduced-feature or seasonal-naive model when feeds fail. Drift signals produce OK, WATCH, or INVESTIGATE; they never trigger automatic retraining alone.