Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Apply ARIMA, VAR, cointegration, and time series econometric methods
.claude/skills/brycewang-stanford-time-series-guide/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 26% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 51% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 24% | 0% |
| case-22 | ✗→✓ | ▲ Improved | 42% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 68% | 0% |
A skill for applying time series econometric methods including ARIMA modeling, VAR systems, cointegration analysis, and unit root tests. Covers stationarity concepts, model selection, forecasting, and diagnostic checking for economic and financial data.
A time series is stationary when its statistical properties (mean, variance, autocorrelation) do not change over time. Most econometric methods require stationarity. Non-stationary series can produce spurious regressions.
pythonfrom statsmodels.tsa.stattools import adfuller, kpss import pandas as pd def test_stationarity(series: pd.Series, name: str = "Series") -> dict: """ Test for stationarity using ADF and KPSS tests. Args: series: Time series data name: Label for the series """ # Augmented Dickey-Fuller test # H0: Unit root exists (non-stationary) adf_result = adfuller(series.dropna(), autolag="AIC") # KPSS test # H0: Series is stationary kpss_result = kpss(series.dropna(), regression="c", nlags="auto") return { "series": name, "adf": { "statistic": adf_result[0], "p_value": adf_result[1], "lags_used": adf_result[2], "conclusion": ( "Stationary (reject unit root)" if adf_result[1] < 0.05 else "Non-stationary (fail to reject unit root)" ) }, "kpss": { "statistic": kpss_result[0], "p_value": kpss_result[1], "conclusion": ( "Non-stationary (reject stationarity)" if kpss_result[1] < 0.05 else "Stationary (fail to reject stationarity)" ) } }
Method 1: Differencing
y_diff = y_t - y_{t-1} (first difference)
y_diff2 = delta(y_diff) (second difference, rarely needed)
Method 2: Log transformation + differencing
y_log = log(y_t) (stabilizes variance)
y_return = log(y_t) - log(y_{t-1}) (log returns)
Method 3: Detrending
Subtract a fitted trend (linear, polynomial, or HP filter)ARIMA(p, d, q):
p = order of autoregressive (AR) component
d = degree of differencing
q = order of moving average (MA) component
SARIMA(p, d, q)(P, D, Q, s):
Seasonal extension with period s
P, D, Q = seasonal AR, differencing, MA orderspythonfrom statsmodels.tsa.arima.model import ARIMA import numpy as np def fit_arima(series: pd.Series, order: tuple = None) -> dict: """ Fit an ARIMA model, optionally using auto-selection. Args: series: Time series data order: (p, d, q) tuple; if None, uses AIC-based selection """ if order is None: # Grid search over common orders best_aic = np.inf best_order = (0, 0, 0) for p in range(4): for d in range(3): for q in range(4): try: model = ARIMA(series, order=(p, d, q)) result = model.fit() if result.aic < best_aic: best_aic = result.aic best_order = (p, d, q) except Exception: continue order = best_order model = ARIMA(series, order=order) result = model.fit() return { "order": order, "aic": result.aic, "bic": result.bic, "coefficients": dict(zip(result.param_names, result.params)), "residual_diagnostics": { "ljung_box_p": float( result.test_serial_correlation("ljungbox", lags=[10])[0]["lb_pvalue"].iloc[0] ) } }
pythonfrom statsmodels.tsa.api import VAR def fit_var_model(data: pd.DataFrame, maxlags: int = 12) -> dict: """ Fit a VAR model to multivariate time series data. Args: data: DataFrame with multiple time series columns maxlags: Maximum lag order to consider """ model = VAR(data) # Select lag order by information criteria lag_selection = model.select_order(maxlags=maxlags) optimal_lag = lag_selection.aic result = model.fit(optimal_lag) return { "lag_order": optimal_lag, "aic": result.aic, "variables": list(data.columns), "granger_causality": "Use result.test_causality() for pairwise tests", "irf": "Use result.irf(periods=20) for impulse response functions" }
Granger causality tests whether past values of variable X improve forecasts of variable Y beyond what past values of Y alone provide. It is a test of predictive precedence, not true causation.
pythonfrom statsmodels.tsa.stattools import coint from statsmodels.tsa.vector_ar.vecm import coint_johansen def test_cointegration(y1: pd.Series, y2: pd.Series) -> dict: """ Test for cointegration between two series. Args: y1: First time series y2: Second time series """ # Engle-Granger two-step test eg_stat, eg_pvalue, eg_crit = coint(y1, y2) return { "engle_granger": { "statistic": eg_stat, "p_value": eg_pvalue, "conclusion": ( "Cointegrated" if eg_pvalue < 0.05 else "Not cointegrated" ) }, "interpretation": ( "If cointegrated, these series share a long-run equilibrium " "relationship. Use a Vector Error Correction Model (VECM) " "rather than a VAR in differences." ) }
1. Residual autocorrelation: Ljung-Box test (should be non-significant)
2. Residual normality: Jarque-Bera test or Q-Q plot
3. Heteroskedasticity: ARCH-LM test for conditional heteroskedasticity
4. Stability: Check that AR roots lie inside the unit circle
5. Forecast accuracy: Out-of-sample RMSE, MAE, MAPE
6. Information criteria: Compare AIC/BIC across candidate modelsReport all diagnostic results in your paper. Reviewers expect evidence that residuals are well-behaved and that the chosen model specification is justified by information criteria and domain knowledge.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-02 | fail→pass | 20,273 | 16,797 | -17% | 1 | 1 | 0% | 4,441 | 5,616 | +26% | 0 | 0 | — |
case-03 | fail→pass | 11,446 | 9,501 | -17% | 1 | 1 | 0% | 2,490 | 3,748 | +51% | 0 | 0 | — |
case-01 | fail→pass | 14,491 | 31,704 | +119% | 1 | 1 | 0% | 3,337 | 4,139 | +24% | 0 | 0 | — |
case-04 | pass→pass | 15,541 | 16,299 | +5% | 1 | 1 | 0% | 2,685 | 4,516 | +68% | 0 | 0 | — |
case-05 | pass→pass | 14,315 | 13,315 | -7% | 1 | 1 | 0% | 2,393 | 3,964 | +66% | 0 | 0 | — |
case-06 | pass→pass | 13,039 | 12,350 | -5% | 1 | 1 | 0% | 2,103 | 3,682 | +75% | 0 | 0 | — |
case-07 | pass→pass | 12,081 | 10,892 | -10% | 1 | 1 | 0% | 2,092 | 3,648 | +74% | 0 | 0 | — |
case-08 | fail→fail | 18,669 | 14,929 | -20% | 1 | 1 | 0% | 3,168 | 4,428 | +40% | 0 | 0 | — |
case-09 | pass→pass | 9,521 | 6,038 | -37% | 1 | 1 | 0% | 1,742 | 2,885 | +66% | 0 | 0 | — |
case-10 | fail→fail | 13,682 | 11,519 | -16% | 1 | 1 | 0% | 2,352 | 3,772 | +60% | 0 | 0 | — |
case-11 | pass→pass | 7,138 | 4,317 | -40% | 1 | 1 | 0% | 1,321 | 2,617 | +98% | 0 | 0 | — |
case-12 | pass→pass | 6,834 | 4,459 | -35% | 1 | 1 | 0% | 1,214 | 2,558 | +111% | 0 | 0 | — |
case-13 | pass→pass | 4,881 | 3,027 | -38% | 1 | 1 | 0% | 815 | 2,281 | +180% | 0 | 0 | — |
case-14 | pass→pass | 11,123 | 12,616 | +13% | 1 | 1 | 0% | 1,686 | 3,817 | +126% | 0 | 0 | — |
case-15 | pass→pass | 3,746 | 2,707 | -28% | 1 | 1 | 0% | 593 | 2,253 | +280% | 0 | 0 | — |
case-16 | pass→pass | 8,182 | 5,849 | -29% | 1 | 1 | 0% | 1,436 | 2,836 | +97% | 0 | 0 | — |
case-17 | pass→pass | 7,944 | 8,184 | +3% | 1 | 1 | 0% | 1,422 | 3,200 | +125% | 0 | 0 | — |
case-18 | pass→pass | 6,849 | 5,535 | -19% | 1 | 1 | 0% | 1,183 | 2,792 | +136% | 0 | 0 | — |
case-19 | pass→pass | 10,530 | 9,422 | -11% | 1 | 1 | 0% | 1,734 | 3,455 | +99% | 0 | 0 | — |
case-20 | pass→pass | 17,436 | 21,281 | +22% | 1 | 1 | 0% | 2,989 | 5,913 | +98% | 0 | 0 | — |
case-21 | pass→pass | 14,420 | 15,117 | +5% | 1 | 1 | 0% | 2,672 | 4,482 | +68% | 0 | 0 | — |
case-22 | fail→pass | 23,213 | 22,003 | -5% | 1 | 1 | 0% | 4,127 | 5,859 | +42% | 0 | 0 | — |
case-23 | fail→fail | 22,117 | 22,797 | +3% | 1 | 1 | 0% | 3,821 | 5,838 | +53% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +17 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.