| """ |
| src/features/price_pressure.py |
| ================================ |
| Computes the Fuel Price Pressure Indicator — a 0–100 score that |
| captures the lagged and rolling impact of oil prices on aviation costs. |
| |
| Also computes rolling oil price features used as regression inputs. |
| """ |
|
|
| import pandas as pd |
| import numpy as np |
| from src.utils.logger import get_logger |
| from config.settings import PROCESSED_DIR, OIL_ROLLING_DAYS |
|
|
| logger = get_logger(__name__) |
|
|
|
|
| def compute_fuel_pressure(df: pd.DataFrame) -> pd.DataFrame: |
| """ |
| Compute fuel_pressure_indicator for a DataFrame that contains oil_price |
| and oil_price_change_pct columns. |
| |
| Formula: |
| FPI = clip( |
| (pct_change_norm * 60) + (disruption_impact * 20) + (rolling_trend * 20), |
| 0, 100 |
| ) |
| """ |
| df = df.copy() |
|
|
| pct_chg = pd.to_numeric(df.get("oil_price_change_pct", 0), errors="coerce").fillna(0) |
| disruption = pd.to_numeric(df.get("disruption_index", 0), errors="coerce").fillna(0) |
|
|
| |
| pct_norm = (pct_chg / 10).clip(-1, 3) * 60 |
|
|
| |
| disruption_contrib = (disruption / 100) * 20 |
|
|
| df["fuel_pressure_indicator"] = (pct_norm + disruption_contrib).clip(0, 100).round(2) |
|
|
| return df |
|
|
|
|
| def enrich_oil_features(oil_df: pd.DataFrame) -> pd.DataFrame: |
| """ |
| Add rolling average columns to an oil price DataFrame. |
| Expects 'brent_usd' and 'date' columns. |
| """ |
| df = oil_df.copy().sort_values("date") |
|
|
| for w in OIL_ROLLING_DAYS: |
| df[f"brent_rolling_{w}d"] = ( |
| df["brent_usd"].rolling(w, min_periods=1).mean().round(2) |
| ) |
|
|
| df["oil_volatility_14d"] = ( |
| df["brent_usd"].rolling(14, min_periods=2).std().round(2) |
| ) |
|
|
| df["brent_above_90"] = (df["brent_usd"] > 90).astype(int) |
| df["brent_above_100"] = (df["brent_usd"] > 100).astype(int) |
|
|
| return df |
|
|
|
|
| def run(df: pd.DataFrame = None) -> pd.DataFrame: |
| if df is None: |
| df = pd.read_csv(PROCESSED_DIR / "flight_disruptions.csv", low_memory=False) |
| return compute_fuel_pressure(df) |
|
|
|
|
| if __name__ == "__main__": |
| oil_df = pd.read_csv(PROCESSED_DIR / "oil_prices.csv") |
| print(enrich_oil_features(oil_df).tail(10).to_string(index=False)) |
|
|