Generated 2026-08-11 04:05 UTC from the live server. Regenerate with flight/ops/gen_signal_catalog.py after any catalog change; --check fails if this file and the engine disagree.
53 signals · 16 contradictions · 35 producers · 57 aliases
Read the description, not the name. A name is shorthand; the description is what the predicate actually tests — including what it does NOT test.
A contradiction fires when every required signal fires and no excluded one does. Its name is printed verbatim as the report headline, so the name is published prose, not an internal label.
arb_shut_but_eu_drawingspread_wide, freight_extreme, eu_oil_stocks_tightcrude_build_products_at_lowscrude_building, gasoline_undersupplied, distillate_undersupplieddiesel_clean_longdiesel_crack_extremedistillate_oversuppliedeu_comfortable_us_tightcrude_undersupplied, eu_oil_stocks_comfortableflow_freight_divergenceeu_oil_imports_decliningfreight_collapsedforced_storage_buildpunishing_carry, cushing_building_fastfreight_locked_arbspread_wide, freight_extremefundamental_rallyspread_wide, wti_positioning_mediangasoline_overhanggasoline_oversupplied, gasoline_crack_extremeglobal_stocks_tightcrude_undersupplied, eu_oil_stocks_tightopec_revision_vs_priceopec_demand_downgraded, crude_price_extremerefiner_margin_trapcrack_extreme, gasoline_oversuppliedregime_curve_destructionsteep_backwardation, punishing_carryrotterdam_squeezenl_stocks_tight, spread_wide, freight_extremesupply_shock_signaturevix_oil_supply_shock, freight_extremeus_comfortable_eu_tighteu_oil_stocks_tight, crude_oversupplied| signal | fires when | metric | what it tests |
|---|---|---|---|
crude_building | > 1.0 | crude_stock_wow | Crude stocks (excl. SPR) built more than 1.0 million barrels week-on-week |
crude_oversupplied | > 80 | crude_seasonal_pctl | Crude stocks > 80th seasonal percentile |
crude_undersupplied | < 20 | crude_seasonal_pctl | Crude stocks < 20th seasonal percentile |
cushing_building_fast | > 5.0 | cushing_7d_pct | Cushing built >5% in 7 days |
cushing_full | > 2.0 | cushing_z | Cushing inventory z-score above 2 (a statistical high vs its own history — NOT a claim about tank capacity; the name is shorthand) |
cushing_tight | < -2.0 | cushing_z | Cushing inventory z-score below -2 |
production_at_seasonal_high | >= 99 | production_seasonal_pctl | Production at or above the 99th percentile of the same-week distribution (a seasonal high, NOT an all-time record) |
| signal | fires when | metric | what it tests |
|---|---|---|---|
eu_electricity_price_extreme | > 2.0 | de_electricity_price_z | German electricity price z-score above 2 (demand destruction / energy crisis signal) |
eu_gas_stocks_comfortable | > 80 | eu_gas_seasonal_pctl | EU27 gas stocks above 80th seasonal percentile |
eu_gas_stocks_tight | < 20 | eu_gas_seasonal_pctl | EU27 gas stocks below 20th seasonal percentile |
eu_oil_exports_rising | > 10 | eu_oil_exports_3m_pct | EU27 oil exports up >10% over 3 months (refinery product re-export) |
eu_oil_imports_declining | < -10 | eu_oil_imports_3m_pct | EU27 oil imports dropped >10% over 3 months |
eu_oil_imports_surging | > 10 | eu_oil_imports_3m_pct | EU27 oil imports surged >10% over 3 months |
eu_oil_stocks_comfortable | > 80 | eu_oil_seasonal_pctl | EU27 oil stocks above 80th seasonal percentile |
eu_oil_stocks_tight | < 20 | eu_oil_seasonal_pctl | EU27 oil stocks below 20th seasonal percentile |
eu_renewables_accelerating | > 2.0 | eu_renewables_yoy_change | EU27 renewable share up >2pp year-on-year (long-term oil demand displacement) |
nl_stocks_tight | < 20 | nl_oil_seasonal_pctl | Netherlands (Rotterdam/ARA hub) oil stocks below 20th seasonal percentile |
| signal | fires when | metric | what it tests |
|---|---|---|---|
bubble_detected | > 0.0 | bubble_gsadf_excess | Peak BSADF of an ONGOING explosive episode (within 21 days) exceeds its 95% critical value, and the move is upward. The test detects explosive roots in either direction — downward episodes are excluded here because they are crashes, not bubbles. Absent when the last episode is stale, which is the usual state. Populate via bubble_test() |
crude_price_extreme | > 95 | wti_price_pctl | WTI price above 95th historical percentile (flat price extreme) |
freight_collapsed | < -2.0 | bwet_z | BWET freight z-score below -2 |
freight_extreme | > 3.0 | bwet_z | BWET freight z-score above 3 |
punishing_carry | < -15.0 | roll_yield_pct | 12-month roll yield (M12/M1 − 1, negative in backwardation) worse than -15% — the curve pays the market NOT to store |
spread_inverted | < 0 | brent_wti_spread | Brent below WTI |
spread_wide | > 2.0 | brent_wti_zscore | Brent-WTI spread z-score above 2 |
steep_backwardation | < -10.0 | m1_m12 | 12-month curve (M12−M1, negative = backwardation) below -$10: prompt $10+ over the 12-month — steep backwardation |
steep_contango | > 5.0 | m1_m12 | 12-month curve (M12−M1) above +$5: contango |
vix_oil_supply_shock | > 0.5 | vix_corr | VIX-WTI correlation above 0.5 — a correlation CONSISTENT WITH a supply shock, which does not by itself identify one (the name is shorthand) |
| signal | fires when | metric | what it tests |
|---|---|---|---|
opec_call_rising | > 0 | opec_call_qoq_change | Call on DoC crude rising quarter-over-quarter. NOTE: the call series extends past the last realized quarter, so this reads the shape of OPEC's own FORECAST, not an observed change — a legitimate thing to watch, but not a realized q/q move |
opec_compliance_gap_extreme | > 200 | opec_compliance_gap_max_kbd | Max /Table 5-8 direct - Table 5-7 secondary/ across OPEC members > 200 tb/d (compliance-gaming signal, Iraq typical offender) |
opec_demand_downgraded | < -0.1 | opec_world_demand_revision | OPEC MoM revision to world oil demand < -0.1 mb/d (more bearish than last month) |
opec_demand_upgraded | > 0.1 | opec_world_demand_revision | OPEC MoM revision to world oil demand > +0.1 mb/d (more bullish than last month) |
opec_iea_spread_inverted | < -0.5 | opec_iea_demand_spread_2026 | IEA 2026 world demand forecast exceeds OPEC by > 0.5 mb/d (unusual - IEA bullish, OPEC cautious) |
opec_iea_spread_widening | > 1.5 | opec_iea_demand_spread_2026 | OPEC 2026 world demand forecast exceeds IEA by > 1.5 mb/d (diverging outlooks, classic OPEC-bullish setup) |
opec_production_gap | > 2.0 | opec_call_production_gap | Call on DoC crude minus OPEC crude production > 2 mb/d, on the most recent quarter BOTH series cover (structural undersupply on OPEC own figures). Period-aligned since 2026-08-11: it previously differenced last-vs-last, which took a forecast quarter against a print six quarters earlier |
| signal | fires when | metric | what it tests |
|---|---|---|---|
brent_positioning_median | between 30 and 70 | brent_mm_pctl | Brent managed money between 30th and 70th percentile (no crowded trade) |
brent_specs_extended | > 90 | brent_mm_pctl | Brent managed money positioning > 90th percentile |
brent_specs_short | < 10 | brent_mm_pctl | Brent managed money positioning < 10th percentile |
wti_positioning_median | between 30 and 70 | wti_mm_pctl | WTI managed money between 30th and 70th percentile (no crowded trade) |
wti_specs_extended | > 90 | wti_mm_pctl | WTI managed money positioning > 90th percentile |
wti_specs_short | < 10 | wti_mm_pctl | WTI managed money positioning < 10th percentile |
| signal | fires when | metric | what it tests |
|---|---|---|---|
crack_extreme | > 3.0 | crack_321_z | 3-2-1 crack z-score above 3 |
diesel_crack_extreme | > 3.0 | crack_diesel_z | Diesel crack z-score above 3 |
distillate_oversupplied | > 90 | distillate_seasonal_pctl | Distillate stocks > 90th seasonal percentile |
distillate_undersupplied | < 20 | distillate_seasonal_pctl | Distillate stocks < 20th seasonal percentile |
gasoline_crack_extreme | > 3.0 | crack_gasoline_z | Gasoline crack z-score above 3 |
gasoline_oversupplied | > 90 | gasoline_seasonal_pctl | Gasoline stocks > 90th seasonal percentile |
gasoline_undersupplied | < 20 | gasoline_seasonal_pctl | Gasoline stocks < 20th seasonal percentile |
maintenance_detected | < -2.0 | maintenance_trough_z | Refinery runs z-score below -2 — a utilization trough. Turnarounds are the usual cause but an unplanned outage or weak demand looks identical here; the signal does not distinguish them (refining desk signal — populate via maintenance_signal()) |
refinery_strong | > 92 | refinery_util | Refinery utilization above 92% |
refinery_weak | < 85 | refinery_util | Refinery utilization below 85% |
| signal | fires when | metric | what it tests |
|---|---|---|---|
weather_cold_extreme | > 2.0 | hdd_anomaly_z | US heating degree days z-score above 2 vs 10-year average (cold snap, bullish heating oil/distillate demand) |
weather_hot_extreme | > 2.0 | cdd_anomaly_z | US cooling degree days z-score above 2 vs 10-year average (heat wave, bullish gasoline + AC power gen) |
weather_mild_winter | < -2.0 | hdd_anomaly_z | US heating degree days z-score below -2 (mild winter, bearish distillate/heating oil) |
Where a metric is computed by more than one surface, this is the definition all of them must use — published so a number can be reproduced from the published formula.
brent_wti_spread
brent_wti_zscore
crack_321_z
roll_yield_pct
wti_mm_pctl
Which series each metric comes from, and over what window.
| metric | series | window (days) | handler | status |
|---|---|---|---|---|
brent_mm_pctl | CFTC.BRENT.MM_Net | 1560 | percentile | ready |
brent_wti_spread | PET.RBRTE.D, PET.RWTC.D | - | spread | ready |
brent_wti_zscore | PET.RBRTE.D, PET.RWTC.D | 1300 | spread | ready |
bubble_gsadf_excess | PET.RWTC.D | 126 | bubble_test | ready |
bwet_z | SHIP.BWET.D | 1260 | stats | ready |
cdd_anomaly_z | - | - | none | no_data |
crack_321_z | PET.RWTC.D, PET.EER_EPMRU_PF4_Y35NY_DPG.D, PET.EER_EPD2DXL0_PF4_Y35NY_DPG.D | 1260 | crack_spread | ready |
crack_diesel_z | PET.RWTC.D, PET.EER_EPD2DXL0_PF4_Y35NY_DPG.D | 1260 | crack_spread | ready |
crack_gasoline_z | PET.RWTC.D, PET.EER_EPMRU_PF4_Y35NY_DPG.D | 1260 | crack_spread | ready |
crude_seasonal_pctl | PET.WCESTUS1.W | - | seasonal | ready |
cushing_7d_pct | PET.W_EPC0_SAX_YCUOK_MBBL.W | 7 | changes | ready |
cushing_z | PET.W_EPC0_SAX_YCUOK_MBBL.W | 260 | stats | ready |
de_electricity_price_z | EUROSTAT.nrg_pc_205.DE.EUR.S.MWH20-499.E7000.I_TAX.KWH | 3650 | stats | ready |
distillate_seasonal_pctl | PET.WDISTUS1.W | - | seasonal | ready |
eu_gas_seasonal_pctl | EUROSTAT.nrg_stk_gas.EU27_2020.A.G3000.STKCL_NAT.MIO_M3 | - | seasonal | ready |
eu_oil_exports_3m_pct | EUROSTAT.nrg_te_oil.EU27_2020.A.TOTAL.O4000.THS_T | 1825 | changes | ready |
eu_oil_imports_3m_pct | EUROSTAT.nrg_ti_oil.EU27_2020.A.TOTAL.O4000.THS_T | 1825 | changes | ready |
eu_oil_seasonal_pctl | EUROSTAT.nrg_stk_oil.EU27_2020.A.O4000.STKCL_NAT.THS_T | - | seasonal | ready |
eu_renewables_yoy_change | EUROSTAT.nrg_ind_ren.EU27_2020.A.REN.PC | 1825 | changes | ready |
gasoline_seasonal_pctl | PET.WGTSTUS1.W | - | seasonal | ready |
hdd_anomaly_z | - | - | none | no_data |
m1_m12 | ICE.BRENT.M12.D, ICE.BRENT.M1.D | - | spread | ready |
maintenance_trough_z | PET.WPULEUS3.W | 260 | maintenance_signal | ready |
nl_oil_seasonal_pctl | EUROSTAT.nrg_stk_oil.NL.A.O4000.STKCL_NAT.THS_T | - | seasonal | ready |
opec_call_production_gap | OPEC.MOMR11_1.MEMO.CALL_ON_DOC_CRUDE.Q, OPEC.MOMR11_1.NON_DOC.DOC_CRUDE_OIL_PRODUCTION.Q | - | custom_opec_gap | computed |
opec_call_qoq_change | OPEC.MOMR11_1.MEMO.CALL_ON_DOC_CRUDE.Q | - | custom_last_minus_prev | computed |
opec_compliance_gap_max_kbd | OPEC.MOMR5_7.*.M, OPEC.MOMR5_8.*.M | - | custom_compliance_gap | computed |
opec_iea_demand_spread_2026 | - | - | none | virtual |
opec_world_demand_revision | OPEC.MOMR11_1_REV.DEMAND.TOTAL_WORLD_DEMAND.A | - | latest | ready |
production_seasonal_pctl | PET.WCRFPUS2.W | - | seasonal | ready |
refinery_util | PET.WPULEUS3.W | - | latest | ready |
roll_yield_pct | ICE.BRENT.M1.D, ICE.BRENT.M12.D | - | custom_roll_yield | computed |
vix_corr | MACRO.VIX.D, PET.RWTC.D | 60 | rolling_correlation | ready |
wti_mm_pctl | CFTC.WTI.MM_Net | 1560 | percentile | ready |
wti_price_pctl | PET.RWTC.D | - | percentile | ready |
| key | label |
|---|---|
brent_mm_pctl | Brent managed money net positioning percentile |
brent_wti_spread | Brent-WTI spread ($/bbl) |
brent_wti_zscore | Brent-WTI spread z-score |
bubble_gsadf_excess | GSADF bubble-test excess above critical value |
bwet_z | BWET freight z-score |
cdd_anomaly_z | US cooling degree days anomaly z-score (vs 10-yr avg) |
crack_321_z | 3-2-1 crack z-score |
crack_diesel_z | diesel crack z-score |
crack_gasoline_z | gasoline crack z-score |
crude_seasonal_pctl | crude stocks seasonal percentile |
cushing_7d_pct | Cushing 7-day percent change |
cushing_z | Cushing inventory z-score |
de_electricity_price_z | German electricity price z-score |
distillate_seasonal_pctl | distillate stocks seasonal percentile |
eu_gas_seasonal_pctl | EU27 gas stocks seasonal percentile |
eu_oil_exports_3m_pct | EU27 oil exports 3-month percent change |
eu_oil_imports_3m_pct | EU27 oil imports 3-month percent change |
eu_oil_seasonal_pctl | EU27 oil stocks seasonal percentile |
eu_renewables_yoy_change | EU27 renewable share year-on-year change (pp) |
gasoline_seasonal_pctl | gasoline stocks seasonal percentile |
hdd_anomaly_z | US heating degree days anomaly z-score (vs 10-yr avg) |
m1_m12 | 12-month curve, M12−M1 ($/bbl; negative = backwardation — key name is legacy) |
maintenance_trough_z | refinery runs z-score (maintenance trough indicator) |
nl_oil_seasonal_pctl | Netherlands oil stocks seasonal percentile |
opec_call_production_gap | OPEC call-vs-production gap (mb/d) |
opec_call_qoq_change | OPEC call on DoC crude QoQ change (mb/d) |
opec_compliance_gap_max_kbd | max OPEC direct-vs-secondary production gap (tb/d) |
opec_iea_demand_spread_2025 | OPEC-IEA 2025 world demand spread (mb/d) |
opec_iea_demand_spread_2026 | OPEC-IEA 2026 world demand spread (mb/d) |
opec_world_demand_revision | OPEC world demand MoM revision (mb/d) |
production_seasonal_pctl | US crude production seasonal percentile |
refinery_util | US refinery utilization (%) |
roll_yield_pct | 12-month roll yield (%, M12 vs M1) |
vix_corr | VIX-WTI correlation |
wti_mm_pctl | WTI managed money net positioning percentile |
wti_price_pctl | WTI price historical percentile |
Method and provenance: signals-background.md (published at /methodology/background). Measured behaviour — fire rates, collinearity, base rates: signals-catalog-review-2-2026-08-10.md.