OilPriceAPI guides

Gas storage vs TTF prices: what to compare and what not to conclude

By OilPriceAPI · Published November 7, 2026

European storage levels describe the market's physical position. TTF prices reflect expectations about storage plus weather, LNG, pipeline flows, demand, and delivery timing. Putting both series on a chart is useful. It does not prove storage caused a price move.

Ask a narrower question: does unusually low storage for this time of year coincide with a higher price for a specified TTF contract, and was that storage information available when the price was observed? This guide structures the comparison. It presents no measured historical relationship or trading signal; the example below is synthetic.

Choose the physical series and price instrument

Identify storage geography and aggregation. An EU aggregate, one country and one facility are different series. Preserve the gas day, reporting flags, coverage and units. Select a price instrument deliberately. The futures reference and TTF market page are starting points; verify the exact contract and price field. A reference quote is not automatically an official settlement.

Price seriesQuestionMain caveat
Day-ahead hub priceNear-term physical gasDifferent from a monthly future
Fixed delivery-month futureExpectations for one delivery periodTime to delivery shrinks
Front-month futures seriesNearest selected contractInstrument changes at a roll
Winter stripUpcoming winter pricingDefine months, weights and quote basis

Measure storage in more than one way

Stored energy in TWh and filling percentage answer different questions; percentages can move with reported working capacity. Record energy, capacity, filling percentage, seven-day change, seasonal deviation, coverage, and revisions where available.

Define a baseline before inspecting the result. One option is the median of the same calendar-day window in five prior years. For a historical simulation, do not calculate it using future years. Document leap-day treatment and changing country coverage. A high correlation between two seasonal level series may contain little incremental information.

Join on availability, not the date printed on a row

Store the gas day, source publication timestamp, retrieval timestamp and, for revisions, when that version first became available. A Monday storage observation published Tuesday evening cannot inform a Tuesday-morning report. For each price observation, select the latest storage publication available at or before its timestamp.

If your export lacks publication history, label the analysis retrospective. A gas-day field alone cannot reconstruct what an analyst knew at the time.

A runnable Python example

This is a synthetic normalized schema, not an OilPriceAPI response or empirical study. All prices refer to one fictional delivery month. Install pandas in your own environment. The first price joins to the previous evening's publication, never the following evening's.

import pandas as pd

# Synthetic, normalized example. This is not an OilPriceAPI response.
storage = pd.DataFrame({
    "published_at": pd.to_datetime([
        "2026-01-05T18:00:00Z", "2026-01-06T18:00:00Z",
        "2026-01-07T18:00:00Z"], utc=True),
    "inventory_twh": [700.0, 692.0, 685.0],
    "baseline_twh": [730.0, 725.0, 720.0],
})
prices = pd.DataFrame({
    "price_at": pd.to_datetime([
        "2026-01-06T09:00:00Z", "2026-01-07T09:00:00Z",
        "2026-01-08T09:00:00Z"], utc=True),
    "contract_month": ["2026-03"] * 3,
    "price_eur_mwh": [31.0, 31.5, 31.2],
})
joined = pd.merge_asof(
    prices.sort_values("price_at"),
    storage.sort_values("published_at"),
    left_on="price_at", right_on="published_at",
    direction="backward", tolerance=pd.Timedelta("2 days"),
)
joined["storage_gap_twh"] = (
    joined["inventory_twh"] - joined["baseline_twh"]
)
joined["price_change_eur_mwh"] = joined.groupby(
    "contract_month"
)["price_eur_mwh"].diff()
joined["storage_age_hours"] = (
    joined["price_at"] - joined["published_at"]
).dt.total_seconds() / 3600
print(joined.to_string(index=False))

The two-day tolerance is an example analysis choice, not a promised source cadence. Set it from the release calendar; leave unmatched observations missing.

Test a hypothesis without overselling it

Chart storage deviation beside the specified price series, then examine price changes rather than levels alone. Compare seasons and periods; report sample size and missing rows. For prediction, choose lags using a chronological training period, test once on a later holdout, and compare with a simple no-change baseline.

Publication timing is necessary but insufficient. Weather can affect both withdrawals and prices; the forward curve may react to supply news before storage changes. Market participants may already expect the reported movement. A correlation is not a buy or sell recommendation.

Turn it into a repeatable report

Name geography, storage measure, TTF instrument and sample period in the chart title. Show source times, revisions and coverage. The daily energy report guide and template places prices and fundamentals side by side with their distinct meanings. For contract history, see the historical futures guide.

Check available datasets and plan access, then verify a small permitted sample for your geography, contract and reporting deadline. Request coverage for undocumented series before designing around them.