Build a TTF/Brent Energy Ratio Tracker in 5 Minutes
Track the most important metric in global energy markets with 20 lines of code. The TTF/Brent ratio—European natural gas versus crude oil on an energy-equivalent basis—has become the single most important indicator for understanding global energy market structure.
At 0.87 (January 2026), the TTF/Brent ratio signals a fundamental shift from the pre-2021 average of 0.40. This tutorial shows you how to build a real-time ratio tracker using OilPriceAPI.
Deep Dive: Investment Analysis
For the full investment analysis explaining what this ratio means for global energy markets, LNG exporters, and European industrials, see our comprehensive analysis: The Ratio That Reveals Everything: How One Number Explains the Largest Energy Restructuring in 50 Years.
What You'll Build
A ratio tracker that:
- Fetches live prices — Brent crude and Dutch TTF natural gas
- Calculates the energy-equivalent ratio — Converting to common units (USD/MWh)
- Compares to historical averages — Contextualize current levels
- Alerts on key thresholds — Get notified when the ratio crosses critical levels
Prerequisites
- OilPriceAPI key (get one free)
- Python 3.8+ or Node.js 18+
The Math Behind the Ratio
Before we code, understand the calculation:
TTF/Brent Ratio = (TTF_EUR × EUR_USD) / (Brent_USD / 1.7)
Where:
- TTF is priced in EUR/MWh
- Brent is priced in USD/barrel
- 1.7 converts barrels to MWh (1 barrel ≈ 1.7 MWh thermal energy)
- EUR_USD exchange rate converts TTF to USD
Python Implementation
import requests
from datetime import datetime
API_KEY = "your_api_key_here"
BASE_URL = "https://api.oilpriceapi.com/v1"
HEADERS = {"Authorization": f"Token \{API_KEY\}"}
def get_latest_price(code: str) -> float:
"""Fetch latest price for a commodity code."""
response = requests.get(
f"\{BASE_URL\}/prices/latest",
headers=HEADERS,
params={"by_code": code}
)
response.raise_for_status()
data = response.json()
return data["data"]["price"]
def calculate_ttf_brent_ratio() -> dict:
"""Calculate the TTF/Brent energy-equivalent ratio."""
# Fetch current prices
ttf_eur = get_latest_price("DUTCH_TTF_EUR") # EUR/MWh
brent_usd = get_latest_price("BRENT_CRUDE_USD") # USD/barrel
eur_usd = get_latest_price("EUR_USD") # USD per EUR
# Convert TTF to USD/MWh
ttf_usd = ttf_eur * eur_usd
# Convert Brent to USD/MWh (1 barrel = 1.7 MWh)
brent_usd_mwh = brent_usd / 1.7
# Calculate ratio
ratio = ttf_usd / brent_usd_mwh
return {
"ratio": round(ratio, 3),
"ttf_eur_mwh": ttf_eur,
"ttf_usd_mwh": round(ttf_usd, 2),
"brent_usd_bbl": brent_usd,
"brent_usd_mwh": round(brent_usd_mwh, 2),
"eur_usd": eur_usd,
"timestamp": datetime.utcnow().isoformat()
}
def analyze_ratio(ratio: float) -> str:
"""Interpret the ratio relative to historical context."""
if ratio < 0.50:
return "CRISIS LOW: Below pre-2021 average. Check for data anomaly."
elif ratio < 0.65:
return "OVERSUPPLY: Gas discounted to oil. Bullish for industrials."
elif ratio <= 0.90:
return "NEW NORMAL: LNG-dominated market. Structural premium."
elif ratio <= 1.20:
return "STRESS: Gas at/above oil parity. Demand destruction likely."
else:
return "CRISIS: Extreme gas premium. Check for supply disruption."
# Run the tracker
if __name__ == "__main__":
result = calculate_ttf_brent_ratio()
analysis = analyze_ratio(result["ratio"])
print(f"""
TTF/Brent Energy Ratio Tracker
==============================
Ratio: \{result['ratio']\} (Historical avg: 0.40)
Prices:
TTF: EUR \{result['ttf_eur_mwh']\}/MWh (USD \{result['ttf_usd_mwh']\}/MWh)
Brent: USD \{result['brent_usd_bbl']\}/bbl (USD \{result['brent_usd_mwh']\}/MWh)
EUR/USD: \{result['eur_usd']\}
Analysis: \{analysis\}
Updated: \{result['timestamp']\}
""")Node.js/TypeScript Implementation
const API_KEY = "your_api_key_here";
const BASE_URL = "https://api.oilpriceapi.com/v1";
interface PriceResponse {
data: {
price: number;
code: string;
updated_at: string;
};
}
interface RatioResult {
ratio: number;
ttfEurMwh: number;
ttfUsdMwh: number;
brentUsdBbl: number;
brentUsdMwh: number;
eurUsd: number;
timestamp: string;
}
async function getLatestPrice(code: string): Promise<number> {
const response = await fetch(
`${BASE_URL}/prices/latest?by_code=${code}`,
{
headers: { Authorization: `Token ${API_KEY}` },
}
);
if (!response.ok) {
throw new Error(`Failed to fetch ${code}: ${response.statusText}`);
}
const data: PriceResponse = await response.json();
return data.data.price;
}
async function calculateTtfBrentRatio(): Promise<RatioResult> {
// Fetch all prices in parallel
const [ttfEur, brentUsd, eurUsd] = await Promise.all([
getLatestPrice("DUTCH_TTF_EUR"),
getLatestPrice("BRENT_CRUDE_USD"),
getLatestPrice("EUR_USD"),
]);
// Convert TTF to USD/MWh
const ttfUsd = ttfEur * eurUsd;
// Convert Brent to USD/MWh (1 barrel = 1.7 MWh)
const brentUsdMwh = brentUsd / 1.7;
// Calculate ratio
const ratio = ttfUsd / brentUsdMwh;
return {
ratio: Math.round(ratio * 1000) / 1000,
ttfEurMwh: ttfEur,
ttfUsdMwh: Math.round(ttfUsd * 100) / 100,
brentUsdBbl: brentUsd,
brentUsdMwh: Math.round(brentUsdMwh * 100) / 100,
eurUsd: eurUsd,
timestamp: new Date().toISOString(),
};
}
// Ratio interpretation bands
function analyzeRatio(ratio: number): string {
if (ratio < 0.50) return "CRISIS LOW";
if (ratio < 0.65) return "OVERSUPPLY";
if (ratio <= 0.90) return "NEW NORMAL";
if (ratio <= 1.20) return "STRESS";
return "CRISIS";
}
// Run
calculateTtfBrentRatio().then((result) => {
console.log(`TTF/Brent Ratio: ${result.ratio}`);
console.log(`Status: ${analyzeRatio(result.ratio)}`);
console.log(`Historical avg: 0.40 | Current: ${result.ratio}`);
});Historical Ratio Analysis
Track how the ratio has evolved over time:
def get_historical_ratio(days: int = 30) -> list:
"""Fetch historical prices and calculate ratio over time."""
# Get historical data for each commodity
ttf_history = requests.get(
f"{BASE_URL}/prices/historical",
headers=HEADERS,
params={"code": "DUTCH_TTF_EUR", "days": days}
).json()["data"]
brent_history = requests.get(
f"{BASE_URL}/prices/historical",
headers=HEADERS,
params={"code": "BRENT_CRUDE_USD", "days": days}
).json()["data"]
# For simplicity, use a fixed EUR/USD rate
# (For production, fetch historical EUR/USD as well)
eur_usd = 1.168
ratios = []
for ttf, brent in zip(ttf_history, brent_history):
ttf_usd = ttf["price"] * eur_usd
brent_mwh = brent["price"] / 1.7
ratio = ttf_usd / brent_mwh
ratios.append({
"date": ttf["created_at"][:10],
"ratio": round(ratio, 3),
"ttf": ttf["price"],
"brent": brent["price"]
})
return ratiosSet Up Threshold Alerts
Get notified when the ratio moves into different regimes:
def check_ratio_alerts(ratio: float, previous_ratio: float = None) -> list:
"""Check if ratio has crossed key thresholds."""
alerts = []
thresholds = [
(0.65, "OVERSUPPLY", "below"),
(0.90, "NEW_NORMAL_TOP", "above"),
(1.00, "OIL_PARITY", "above"),
(1.20, "CRISIS", "above"),
]
for threshold, name, direction in thresholds:
if direction == "above" and ratio > threshold:
if previous_ratio and previous_ratio <= threshold:
alerts.append(f"ALERT: Ratio crossed ABOVE {threshold} ({name})")
elif direction == "below" and ratio < threshold:
if previous_ratio and previous_ratio >= threshold:
alerts.append(f"ALERT: Ratio crossed BELOW {threshold} ({name})")
return alertsAvailable API Endpoints
OilPriceAPI provides all the data you need for energy market analysis:
| Endpoint | Code | Unit | Description |
|---|---|---|---|
| /v1/prices/latest?by_code=DUTCH_TTF_EUR | DUTCH_TTF_EUR | EUR/MWh | Dutch TTF Natural Gas |
| /v1/prices/latest?by_code=BRENT_CRUDE_USD | BRENT_CRUDE_USD | USD/bbl | Brent Crude Oil |
| /v1/prices/latest?by_code=EUR_USD | EUR_USD | rate | Euro/USD Exchange |
| /v1/prices/latest?by_code=NATURAL_GAS_USD | NATURAL_GAS_USD | USD/MMBtu | Henry Hub Natural Gas |
| /v1/prices/latest?by_code=WTI_USD | WTI_USD | USD/bbl | WTI Crude Oil |
| /v1/prices/historical | various | - | Historical price data |
Use Cases
Energy Trading Desks
Monitor ratio for relative value opportunities between gas and oil markets.
Industrial Risk Management
Track the ratio to hedge energy input costs for manufacturing.
LNG Exporters
The ratio directly impacts LNG netback economics and contract negotiations.
Macro Funds
Use as leading indicator for European industrial competitiveness and EUR/USD direction.
Production Considerations
- Caching: TTF and Brent update frequently during trading hours. Cache for 1-5 minutes depending on your latency requirements.
- Timezone awareness: European gas markets close at different times than oil. Weekend data reflects Friday closes.
- Error handling: Always handle API failures gracefully—markets close and data can be delayed.
Get Started
Ready to Build Your Ratio Tracker?
Get your free API key. 10,000 requests included in the 7-day trial, no credit card required.
broad commodity coverage • Real-time prices • Historical data • Python & Node.js SDKs