Why interpolation matters
The market quotes a handful of points; a usable curve needs hundreds. Gas for next month, next winter, and next year all trade, but April and May in between may not, and every position that settles in an unquoted period still needs a price. Interpolation fills the gaps between known points, and it is deceptively easy to do badly.
The skill is not drawing lines between dots. It is filling the silence between quotes without inventing information the market never gave, which requires understanding what makes a curve economically sensible, not just visually smooth.
Linear interpolation: the safe default
Between two known points, assume a straight line. To find the value at a point that is a fraction t of the way from the left point (value a) to the right point (value b):
At t = 0 you get a; at t = 1 you get b; at t = 0.5 the midpoint. A straight line between two positive prices can never go negative or overshoot, the interpolated value always sits between its two neighbours. It is boring, but it is bullet-proof, which is why desks lean on it.
A worked example. March = 64, June = 76 (three months apart). May is two months after March, so two-thirds of the way to June: t = 2/3 ≈ 0.667, giving May = 64 + 0.667 × (76 - 64) = 72. No overshoot, no nonsense, that is linear interpolation doing its safe job.
Linear interpolation holds the curve flat before the first quote and after the last (flat extrapolation), a deliberate, safe choice: every interpolated value sits inside the quoted range, so no overshoot is possible.
When linear is not enough: splines and overshoot
Linear is safe but can be too crude when the underlying curve genuinely bends. Suppose quoted points are Jan 60, Apr 48, Jul 40, a curve falling toward summer but flattening as it goes. Linear interpolation for mid-February draws a straight line from 60 to 48, giving roughly 56, but if the real seasonal curve is convex, the true value might be nearer 57-58. A straight line under-reads a convex curve between its knots.
This is why richer methods exist. Splines fit a smooth curve through the points that respects curvature and can better capture gentle seasonal bends. The trade-off is that smoother methods can overshoot, wiggling above or below all the data, sometimes producing negative prices, manufacturing the very arbitrage linear interpolation avoids.
The practical rule: start linear (safe, predictable), reach for shape-preserving splines only when the data genuinely curves, and always check the result introduces no spurious wiggles. Smoothness is a means, not the goal; economic sensibility is the goal.
Interpolation in code
Filling a monthly curve from a few quotes is a few lines. The safety check, that every interpolated price lies within the known range, is the line that catches overshoot instantly:
pythonimport numpy as np # Known quote points: month index (0 = Jan) -> price. known_months = np.array([2, 5, 8]) # Mar, Jun, Sep known_prices = np.array([64.0, 76.0, 70.0]) # currency / MWh # Interpolate every month Jan..Sep all_months = np.arange(0, 9) interp = np.interp(all_months, known_months, known_prices) # Safety check: every interpolated price must lie within the known range. lo, hi = known_prices.min(), known_prices.max() safe = np.all((interp >= lo) & (interp <= hi)) print("all prices within range:", "PASS" if safe else "FAIL (overshoot!)")
Linear interpolation holds the ends flat (Jan and Feb equal March), and every value sits inside the quoted band, so the safety check passes. On a shape-preserving spline the same check is what proves the smoother fit did not overshoot into an impossible price.
The curve is a product, not a calculation
Fitting the curve is a page of maths. Everything around that fit, the ninety percent of production curve work that is not the maths, is what lets real money trade against the number. The desk question is not "how do I build a curve?" but "how does a trading desk build, validate, deploy, monitor, and trust a curve?"
Two facts drive everything below. First, most failures enter upstream of the fit, in the market-data layer: a crossed broker quote, a settlement that did not refresh, a duplicate that quietly makes the constraint matrix rank-deficient. By the time these reach the solver, the damage is done, and the solver may even "succeed" while producing a poisoned curve. Second, most failures are only caught downstream, by diagnostics, a spline that dips negative, a stale strip distorting a storage valuation, none visible in the fitted number itself, only if you test for them and publish the uncertainty.
The organising idea is a pipeline with a gate at each end: Market Data → Validation → Cleaning → Curve Builder → Diagnostics → Publication → Valuation → Risk. Every stage has a single responsibility and a typed interface, so a change in interpolation policy cannot reach into market-data handling, and a new feed cannot silently alter the fit.
Market data: the failures that happen before interpolation
Ask an experienced curve engineer where curve bugs come from and they will not say "the interpolation method." They will say "the data." The market-data layer is where a production curve is won or lost, and it is almost entirely absent from textbook treatments. It draws on the same governed trade capture and reference data that feed the rest of the platform.
A single delivery product, say the Q1 gas quarter, may be quoted in the same minute by several sources that disagree: an exchange settlement (authoritative, but only struck once, at close), an exchange last-trade (live, but possibly hours old for an illiquid product), one or more broker bid/ask pairs (indicative, sometimes crossed or wide), and a trader mark (a manual override, lowest authority). You cannot feed all of them to the solver; you must resolve them to one clean number per product, and record why.
That resolution is a sequence of decisions, each a place production curves break:
- Bid/ask to mid. The usable price is the mid, but only if the market is not crossed (bid > ask, a feed error) and not pathologically wide (a huge spread means no real liquidity). Both are rejected, not averaged.
- Source hierarchy. For a liquid front product the last trade is freshest; for an illiquid back product the settlement is the daily reference. The engine prefers settlement, then trade, then broker, then manual mark.
- Stale-quote thresholds. Every quote carries a timestamp; anything older than a freshness threshold is excluded rather than trusted. A stale mark that survives into the board is the classic silent poison.
- Missing quotes. A product with no usable quote is simply absent, and its tenor becomes one of the inferred months the constrained fit must pin from the prior. Missingness is normal, not an error.
- Duplicates. The same product from two sources must be deduplicated, because a duplicated constraint is not harmless: two identical rows make the system singular and the solve rank-deficient.
- Time synchronisation. Gas and power, and different exchanges, close at different times and on different calendars. A curve struck "as of 17:00" must assemble quotes all valid as of that instant, applying each market’s close convention, not mixing a post-close settlement from one venue with a pre-close broker quote from another.
pythonfrom market_data import MarketDataEngine, RawQuote, QuoteSource raws = [ RawQuote("Q1", bid=87.8, ask=88.2, source=QuoteSource.BROKER, ts=now-5m), RawQuote("Q1", settlement=88.0, source=QuoteSource.SETTLEMENT, ts=now-2m), # duplicate, higher authority RawQuote("Q2", bid=62.0, ask=70.0, source=QuoteSource.BROKER, ts=now-1m), # spread too wide -> reject RawQuote("Q3", bid=56.0, ask=54.0, source=QuoteSource.BROKER, ts=now), # crossed (bid>ask) -> reject RawQuote("Q4", last_trade=78.0, source=QuoteSource.TRADE, ts=now-3h), # stale -> reject RawQuote("Jan", settlement=95.0, source=QuoteSource.SETTLEMENT, ts=now), ] clean, report = MarketDataEngine().clean(raws, now) # clean board: {'Q1': 88.0, 'Jan': 95.0} # Q1 source used: exchange_settlement # rejected -> stale: ['Q4'] | wide: ['Q2'] | crossed: ['Q3'] | deduped: ['Q1']
The two Q1 quotes were deduplicated with the settlement winning over the broker; Q2 dropped for a wide spread, Q3 for being crossed, Q4 for being stale. Crucially, the engine tells you why the others did not survive, the difference between a black box and an auditable pipeline. The lesson experienced engineers repeat: a great fit on a bad board is a bad curve.
The arbitrage validation suite
Arbitrage-freeness is a property to prove, not assume. Production turns it into an explicit validation suite that runs after construction and gates publication: a curve that fails any hard check never reaches the books; a curve that passes carries the report as its audit trail.
- Negative forwards. No delivery price may be negative (barring genuinely negative-price power regimes, handled explicitly). A single negative is almost always an interpolation overshoot and can hand a downstream storage or swing model "free" energy. Hard fail.
- Calendar-spread violations. Every quoted block must reprice from the fitted monthly curve. If the day-weighted average of a quarter’s months does not equal the quarter’s quote, the curve contains a calendar-spread arbitrage. Hard fail above tolerance.
- Butterfly / convexity. Large sign flips in the second difference across three consecutive deliveries flag implausible local concavity, usually a bad interpolation or a mis-keyed mark. A soft diagnostic, because genuine seasonality is convex in places.
- Peak/off-peak consistency. For power, the hour-weighted blend of the peak and off-peak curves must equal the baseload, or the three products form an arbitrage. Hard check.
- Block repricing error. The direct constraint check across all quoted products; for an interpolant it must be at solver precision. A nonzero value means the solve did not honour the quotes.
- Monthly to quarterly aggregation. Aggregating fitted months to quarters and quarters to the cal-year must be self-consistent, catching day-weighting bugs.
A validation suite is only convincing if you see it fail on a broken curve. Fed a curve with an overshoot-induced negative in July, a calendar-spread arbitrage, and a peak/off-peak split that does not reblend, each check fires exactly on its failure and localises it, naming the month, the mispriced quarter, and the baseload miss. In production these are the gates between a corrupted curve and the books, and because each returns where it failed, the on-call engineer gets a pointer, not just a red light.
Publishing uncertainty and auditability
A production curve builder does not publish only prices. It publishes how much to trust each price, because a curve where February is a hard outright and one where February is inferred from a quarter and a seasonal prior are very different objects, even if both print the same number. Five artefacts, all cheap by-products of the fit, make the difference visible:
- Confidence score. A per-month value in [0, 1]: how strongly a real quote pins that month versus how much it leans on the prior. Months with their own outright score near 1; months known only through a broad block and the prior score lower.
- Number of inferred months. How many months have no outright quote and exist only because the fit inferred them, a fact a risk manager should see stamped on the curve.
- Per-quote sensitivity. For every published point, how much it moves if each input quote moves by one unit, telling a trader instantly which mark their exposure really depends on.
- Residual contribution. When the board is inconsistent and reconciled by weighted least squares, each quote’s residual says how much it was bent to reach agreement; the largest residual localises a stale mark.
- Shape-prior influence. The complement of the confidence score, what fraction of each month’s value comes from the seasonal prior rather than the market. A curve whose summer months are 90% prior-driven is a curve whose summer view is your model’s, not the market’s.
On a worked board where only two months trade outright plus the four quarters, ten of the twelve months are inferred, months anchored by a nearby outright or a tight block score high (0.90-1.00), while months known only through a broad quarter score around 0.45. Publishing these vectors alongside the price is what makes the curve auditable: a trader can see, per month, how much of the number is market and how much is model.
When the board is inconsistent, the reconciliation spreads the disagreement across the quotes, and the residual vector, visualised as a heatmap, localises the culprit at a glance. A stale calendar strip shows a residual that dwarfs every other, immediately fingering it as the stale mark, turning "the curve looks off" into "the cal strip is stale, refresh it."
Curve sensitivities: how the curve moves when a quote moves
The constrained fit gives something a bumping approach would only approximate: the exact derivative of every curve point with respect to every quote, in closed form. This is the curve’s Jacobian, the natural bridge from construction to risk.
With prior b and constraints Af = q, the fitted curve is an affine function of the quote vector, so the sensitivity of the whole curve to the quotes is the constant matrix:
Column j is the influence of quote j: how the entire curve shifts if product j’s quote rises by one unit. Because f is affine in q, this derivative is exact and global, no finite-difference bump, no step-size choice, valid for any move size, and it matches a finite-difference check to machine precision.
The individual numbers are readable desk facts. On a board where January trades outright inside Q1, marking Q1 up by one unit moves February and March up (dFeb/dQ1 ≈ 1.44, dMar/dQ1 ≈ 1.60) but not January (dJan/dQ1 = 0), because January has its own outright quote that pins it, so the whole quarter adjustment is absorbed by the two inferred months. The Feb and Mar sensitivities exceed 1 precisely because they alone must carry the quarter’s move.
This is the curve’s delta ladder: it tells the risk engine, for any book valued off the curve, how the book’s value flows back to the underlying market quotes. A row of the Jacobian is directly a hedging recipe, to hedge one unit of February (an illiquid month with no outright), buy 1.44 of the Q1 quarter and sell 0.50 of the January outright, isolating February by taking the quarter and backing out the January component. An inferred curve point becomes a hedgeable risk, straight out of the fit, no extra modelling.
Choosing a solver
The constrained fit can be solved several ways, and the "right" one depends on conditioning, size, sparsity, and whether you need to survive rank-deficiency. Six approaches, benchmarked on the identical problem, all agree to machine precision but differ where it counts:
- KKT direct, factor the full symmetric indefinite system. The default: clear, robust, handles indefiniteness.
- Normal equations, fastest when well-conditioned and quotes are few, but forming the system squares the condition number.
- QR, factors the constraint matrix directly, avoiding the squaring; better stability cheaply.
- SVD, most stable, reveals rank, the choice for rank-deficient or collinear boards, at a larger constant cost.
- Interior-point / CG, matrix-vector only, the viable path once the system is large and sparse (an hourly curve) and will not fit densely.
- Active-set, earns its keep only when inequality constraints (hard positivity, monotonicity) are added; with equalities alone it collapses to the KKT solve.
Two structural facts drive the choice. Forming the normal equations squares the condition number, so on a near-collinear board QR or SVD on the constraint matrix directly are safer. And the equality-only problem has a fixed active set, so a full active-set solver collapses to KKT here, active-set only pays off once you add inequality constraints such as hard positivity or monotonicity bounds.
The engineering rule: default to KKT for clarity, drop to Normal equations when you have proven the board is well-conditioned and need speed, and reach for QR/SVD the moment conditioning is marginal or rank-deficiency is possible. The engine encodes this as a policy, try the fast path, catch the failure, fall back to the stable solver, rather than paying for the safest solver on every curve.
Curve-fitting models: a quant reference
The constrained-least-squares fit is the production workhorse, but a curve engineer draws on a wider toolkit depending on the market, the liquidity, and whether the goal is a smooth term structure, a seasonal shape, or a dynamic model that evolves over time. The families below span parametric term structures, spline methods, seasonal and statistical decompositions, and stochastic models.
Parametric term-structure models
When to use: a smooth, low-parameter fit to a sparsely quoted term structure where you want interpretable factors (Nelson-Siegel-Svensson adds a second curvature term for more flexibility). Less suited to seasonal power/gas curves, where the shape is not monotone-decaying.
When to use: when you must hit every liquid quote exactly and extrapolate smoothly to a mandated long-term anchor beyond the last liquid tenor, common for long-dated discounting where a convergence level is prescribed.
Spline methods
| Method | Formula / idea | Continuity | Overshoot risk | When to use |
|---|---|---|---|---|
| Cubic spline | piecewise cubics, C2 continuous | C2 (smooth curvature) | Yes, can dip below data | Smooth curves where the data is genuinely convex and quotes are clean |
| Monotonic spline | Hyman / Fritsch-Carlson slope limiting on a cubic | C1 | No (monotone preserved) | Discount factors or any curve that must not reverse direction |
| Shape-preserving (PCHIP) | piecewise cubic Hermite, slope-limited | C1 | No | The safe default for commodity forwards: captures curvature, never invents peaks or negatives |
| Tension / smoothing spline | penalise curvature with a tension parameter | C2 | Tunable | Trading smoothness against fit when quotes are noisy |
Seasonal and statistical decomposition
When to use: building the seasonal prior that pins the illiquid months of a gas or power curve; the fitted seasonal factors become the shape the constrained fit leans on where no quote exists.
When to use: compressing curve risk for VaR and scenario generation, and for building low-dimensional shocks that keep the curve realistic. The first three principal components usually capture 95%+ of daily curve variance.
Stochastic and dynamic models
When to use: modelling spot and prompt dynamics for storage/swing valuation and for simulating forward-curve evolution. Calibration recovers the mean-reversion speed kappa, the (seasonal) level theta(t), and volatility sigma, typically by regressing the daily change on the level (an AR(1) fit) or by maximum likelihood.
pythonimport numpy as np # OU calibration by AR(1) regression: X_{t+1} = a + b X_t + e x = np.asarray(prices) b, a = np.polyfit(x[:-1], x[1:], 1) # slope b, intercept a dt = 1/252 kappa = -np.log(b)/dt # mean-reversion speed theta = a/(1-b) # long-run level resid = x[1:] - (a + b*x[:-1]) sigma = np.std(resid)*np.sqrt(2*kappa/(1-b**2)) print(f"kappa={kappa:.2f} theta={theta:.2f} sigma={sigma:.2f}")
When to use: a time-dynamic version of the prior-plus-quotes idea, ideal when marks arrive asynchronously and you want a curve that carries information forward rather than refitting from scratch each snapshot.
When to use: power and gas markets with distinct calm and spike regimes, where a single volatility badly misprices the tails; the regime probabilities also feed scenario and stress design.
These models are not alternatives to the production pipeline but tools inside it: seasonal decomposition and PCA build the prior and the risk factors, splines and parametric forms do the fitting, and the stochastic models (OU, Kalman, regime-switching) drive the simulation and dynamics that storage, swing, and VaR depend on.
A worked example: from three quotes to P&L
To make the workflow concrete, take a minimal gas board, three monthly quotes, and thread it all the way through to a valuation and P&L impact.
| Contract | Market price (currency/MWh) |
|---|---|
| Jan | 58 |
| Feb | 60 |
| Mar | 63 |
Step 1, interpolation
Suppose a position delivers in mid-February, at the point halfway between the Feb and Mar marks. Linear interpolation gives value = 60 + 0.5 × (63 - 60) = 61.5. A shape-preserving spline would return a similar value here because the three points are already monotone and gently convex, no overshoot to correct.
Step 2, shaping to a finer grain
February’s 60 is a monthly average. To value a daily or hourly position you shape it: distribute the monthly average across finer buckets with a profile that preserves the average. If a weekday day-shape puts peak days at 1.08 and weekend days at 0.85 of the month, a peak delivery day values at 60 × 1.08 = 64.8, while the whole month still averages back to 60.
Step 3, hourly curve
For power the same logic goes to 24 hourly buckets per day, with a peak/off-peak (or full hour-of-day) profile. February’s 60 becomes 672 hourly prices (28 days × 24) that still average to 60, but now an hour-8 peak load values against its own price, not a smeared monthly average, which is exactly what makes an hourly position value correctly.
Step 4, valuation impact
Consider a 10 MW baseload position across February (28 days × 24 h = 672 hours, so 6,720 MWh). Valued at the monthly average of 60, its mark is 6,720 × 60 = 403,200. The shaping does not change a flat baseload’s total (the profile averages to 1), but it changes the value of any non-flat position, a peak-only contract over the same month values at 60 × 1.08 × its peak MWh, materially above the naive monthly number.
Step 5, P&L impact
Now the Feb mark moves from 60 to 62 on the next day’s board. The baseload position’s mark-to-market becomes 6,720 × 62 = 416,640, a P&L of +13,440 from the two-unit curve move. The curve Jacobian makes this explicit: because the position is pure February, its entire P&L flows from the February mark, and if February were inferred from Q1 rather than quoted outright, the same P&L would instead be attributed across the Q1 quarter and the January outright via the sensitivities, exactly the hedging decomposition described earlier.
The chain, interpolate to price the gap, shape to the delivery granularity, value the position, and attribute the P&L back to the marks that moved, is the whole reason curve quality is money: every step inherits the curve’s shape, and an error in the illiquid, inferred region propagates straight into the valuation and the P&L.
Complexity and scaling: 12 months to 8,760 hours
A monthly curve is 12 points; a daily curve is 365; an hourly power curve is 8,760. The maths is identical, but the engineering is not, and a method that is instant on 12 points can be unusable on 8,760 if you ignore structure.
The expensive dimension of the constrained fit is the number of quotes (small, ~5-20), not the number of curve points. A reduction turns the full (n+m)×(n+m) KKT system into a tiny m×m system in the multipliers, on a 365-day curve that is a 116× speed-up, with the two agreeing to machine precision. Because the expensive dimension is always the small quote count, a daily or even hourly fit stays cheap as long as you exploit the reduction rather than factoring the giant block directly.
The smoothness solve is the other half. The interpolation and smoothness systems are tridiagonal or near-banded, so storing and solving them sparse is O(n) in time and memory:
text# Smoothness solve, dense vs sparse, three curve sizes # n= 12 (months): dense 0.037 ms | sparse 0.063 ms | speedup 1x # n= 365 (days) : dense 2.094 ms | sparse 0.123 ms | speedup 17x # n= 8760 (hours) : dense 8821.4 ms | sparse 3.554 ms | speedup 2482x
At 12 months, dense is actually faster, the sparse machinery has overhead not worth paying, so a monthly curve should use a dense solve. At 8,760 hours, dense takes 8.8 seconds and sparse takes 3.6 milliseconds, a 2,482× speed-up, and the memory gap is decisive: the dense 8760×8760 matrix is 0.61 GB of float64, while the sparse tridiagonal is 0.21 MB. An hourly power curve simply cannot be built densely at scale; sparsity is not an optimisation, it is a prerequisite. The crossover rule: dense below a few hundred points, sparse above, and always sparse for anything hourly.
Production architecture: where the curve engine lives
The engine is one stage in a larger pricing-and-risk platform. The whole lifecycle on one line: market data → validation → cleaning → curve builder → arbitrage validation → diagnostics & confidence → versioning & approval → publication → valuation engine → risk engine, with a monitoring feedback loop watching every stage and triggering the next rebuild.
Two architectural principles matter most. Each stage has a single responsibility and a typed interface, so a change in interpolation policy cannot reach into market-data handling, and a new feed cannot silently alter the fit. And publication is a gate, not a step: a curve becomes visible to valuation only after diagnostics pass, and it is published immutable and versioned, so every downstream number can be traced to the exact curve, quotes, and config that produced it.
That traceability is the backbone of model governance: when risk asks "why did this book’s value move," the answer is a diff of two versioned curves and their quote boards. Putting the whole pipeline together, raw multi-source ticks in, a validated published curve out, is the difference between a script that builds a curve once and a service a trading floor depends on for years.
End to end on one realistic board: a duplicate broker quote is deduplicated in favour of the settlement, the constrained fit reprices every survivor exactly and infers the ten unquoted months, the arbitrage suite passes, and February publishes at a price no source quoted, produced by the whole pipeline and validated end to end. This is a curve engine as a system, not a fit.
Industrial testing
A production curve engine is tested far beyond "run it on an example and eyeball the output." Six kinds of test, each catching a different class of bug:
- Unit tests pin specific numbers: interpolation matches the reference to machine precision; the fit reprices exactly; a known inferred month recovers to its expected value.
- Property-based tests assert invariants across many random inputs, the most valuable kind for a numerical library. For interpolation the invariant is no overshoot: for any random monotone node set, a shape-preserving interpolant stays within the node range. Two thousand random monotone curves, zero overshoot violations, far stronger evidence than any single example.
- Stress tests push extremes: a wildly ill-scaled board, a nearly rank-deficient board, a curve with a genuine price spike. The engine must handle them or fail loudly with a diagnostic, never silently produce a poisoned curve.
- Monte-Carlo quote perturbation probes stability: perturb every quote by a small random amount many times and confirm the curve responds smoothly and never violates a hard check.
- Benchmark tests track performance, so a refactor that quietly makes the solve 10× slower is caught.
- Regression tests freeze a known-good curve for a fixed board and assert the engine still reproduces it bit-for-bit after any change, the safety net that lets you refactor the internals with confidence.
Together these turn "it worked when I tried it" into "it provably still works", the standard a front-office library is held to.
Monitoring: catching a curve that drifts in production
Testing proves the engine is correct before deployment; monitoring catches problems after, when live data does something the tests never imagined. The key production monitor is explained vs unexplained move: day over day, the curve should move only where quotes moved. A curve point that shifts with no corresponding quote change is a red flag, a config change, a data-feed glitch, or a bug, and should alert.
If Q1 quotes move and Jan/Feb/Mar move with them, that is fully explained, no alert. If no quote changed but June jumped, the monitor points straight at that month. In production this catches the overnight surprises: a prior quietly re-parameterised, a stale mark that dropped out, an interpolation-policy config that changed, before a trader discovers them by mispricing a book.
Other standard monitors: day-over-day curve distance (a large move triggers review), diagnostic drift (rising condition number or residual RMS over days signals a degrading feed), and confidence erosion (more months slipping into the inferred/low-confidence bucket as liquidity thins). Monitoring is trust made operational: a curve you do not watch is a curve you cannot trust.
Curve governance: publish versions, never overwrite
A published curve is a controlled artefact, not a mutable variable. The governing principle is simple and strict: a desk never overwrites a published curve; it publishes a new version. Yesterday’s curve, and this morning’s version, must remain exactly as they were, forever, because books were valued and risk was run against them and those numbers have to be reproducible at audit.
- Version numbers. Every rebuild produces a new, monotonically increasing version. A downstream valuation references a specific version, so any P&L or risk number ties to the exact curve behind it.
- Approval workflow. Publication is gated on sign-off. Within tolerance (all diagnostics green, move within thresholds) approval can be automated; an exception, a large unexplained move, a failed check, a low-confidence board, routes to a human curve owner.
- Rollback. If a bad curve slips through, the desk rolls forward to the previous good version rather than editing the bad one in place, the bad version stays in the record, flagged, for the post-mortem.
- Digital signatures. Each published version is signed (a hash of curve + board + config) so downstream consumers can verify they are using an authentic, untampered curve.
- Audit trail. Every action, build, approve, publish, roll back, is logged with who/what/when, forming the immutable history a regulator or model-validation team will ask for.
Governance is not bureaucracy; it is what makes every downstream number defensible months later. When risk asks "why did this book move overnight," the answer is a diff of two versions, their quote boards, their configs, their curves, not an archaeology dig.
Determinism and reproducibility
Quantitative production systems live or die on determinism: the same inputs must always produce the same curve, bit for bit, or reproducibility and audit collapse. Given identical quotes, config, and code, the engine must return an identical curve every time, no dependence on hash-ordering, thread-scheduling, or uninitialised memory. Two builds of the same board being byte-for-byte identical is what lets the version hash be a meaningful signature and lets a regression test assert an exact match.
The precision disciplines that make this hold:
- Floating-point tolerance, never equality. Every reprice and arbitrage check uses an absolute tolerance; recall that 0.1 + 0.2 does not equal 0.3 in floating point. "Reprices exactly" means "to ~1e-13," and the tolerance is a declared constant, not a magic number sprinkled through the code.
- Conditioning thresholds. The engine has an explicit condition-number threshold above which it refuses the fast path and switches to SVD (or rejects the board and alerts). The threshold is a declared policy, so "how ill-conditioned is too ill-conditioned" is an auditable decision, not an accident of which solver was called.
- Reproducibility across environments. Pinning library versions matters: different linear-algebra backends can reorder floating-point operations and change the last bits. A deterministic build pins its numerical stack and records the versions in the curve’s provenance, so a curve rebuilt months later on a different machine is still bit-comparable.
Determinism is not pedantry: it is the difference between "the curve was 86.76 because here is the exact board, config, and code that produced it" and "the curve was about 86.8, roughly, we think." Only the former survives an audit.
Real market products: conventions, not numbers
Credibility on a desk comes from handling the actual products, with their real units, calendars, and shaping. Two convention families must be handled before any maths touches the numbers.
Units, normalise to one internal unit on ingest. Gas alone spans p/therm (NBP), €/MWh (TTF), and \$/MMBtu (Henry Hub); power adds \$/MWh. Getting a unit wrong is not a rounding error, it is the ill-scaling that pushes the condition number from single digits to enormous and corrupts the whole solve. Normalise explicitly on ingest; never let a unit sneak into the constraint matrix.
Delivery granularity and shaping. Months nest into quarters, quarters into seasons (gas Summer = Apr-Sep, Winter = Oct-Mar) and cal-years; power adds peak/off-peak and, at the finest grain, weekend, gas-day, and power-hour products. Each is a day- or hour-weighted average constraint on the finer curve. The peak/off-peak split is a calendar computation, not a fixed fraction: under the common Mon-Fri 08-20 definition, January 2026 has 264 peak hours and 480 off-peak hours (weekends are entirely off-peak), so using a nominal fraction instead of the true hour count is a subtle, recurring mispricing.
US nodal power adds a whole dimension. European power quotes a single zonal price; US ISOs quote Locational Marginal Prices at thousands of nodes, and an LMP decomposes into three components:
A liquid hub trades outright; an individual node trades as hub + basis. The engine builds a liquid hub curve with the full machinery, then adds a (usually sparser) basis curve per node, the same constrained-fit-with-a-prior problem one level down.
Benchmark markets and hubs
The conventions above are not abstract, they are the real benchmark hubs a commodity desk builds curves for. Each has its own units, calendar, shaping, and liquidity profile, and the engine carries the convention per market.
| Hub / market | Commodity | Region | Unit | Notes |
|---|---|---|---|---|
| Henry Hub | Natural gas | US | \$/MMBtu | The US gas benchmark; calendar-month delivery, deep liquidity |
| TTF | Natural gas | Europe (NL) | €/MWh | The European gas benchmark; gas-day 06:00-06:00 CET |
| NBP | Natural gas | UK | p/therm | UK gas hub; gas-day 05:00-05:00 UK, therm units |
| JKM | LNG | Asia | \$/MMBtu | The Asian LNG marker; links gas across basins via shipping |
| ERCOT | Power | US (Texas) | \$/MWh | Nodal (LMP) market; energy + congestion + losses, 5x16 on-peak |
| PJM | Power | US (East) | \$/MWh | Largest US ISO; nodal LMPs, hub + basis, NERC-holiday off-peak |
| EPEX | Power | Europe (Central) | €/MWh | Zonal day-ahead/intraday; hourly and quarter-hourly products |
| Nord Pool | Power | Nordics | €/MWh | Hydro-dominated zonal market; strong weather/inflow dependence |
| WTI | Crude oil | US | \$/bbl | US crude benchmark; monthly futures, physical delivery at Cushing |
| Brent | Crude oil | Global | \$/bbl | The global crude benchmark; waterborne, cash-settled forward |
Power markets split further into nodal (ERCOT, PJM, where thousands of nodes each price as hub + basis) and zonal (EPEX, Nord Pool, a single price per bidding zone). Gas markets connect across basins through LNG: a JKM-TTF spread is a shipping-and-arbitrage relationship, and a desk trading it needs both curves built to the same as-of instant on compatible conventions, or the spread inherits a phantom basis.
Curve quality metrics
In production a curve is not just built, it is scored. A dashboard of quality metrics tells the desk, at a glance, whether today’s curve is trustworthy or degrading, and which curves need a human before they publish.
| Metric | What it measures | Why it matters |
|---|---|---|
| RMSE | root-mean-square repricing error across quoted products | Overall fit quality; a rising baseline signals stale marks or a bad board |
| MAE | mean absolute repricing error | Robust companion to RMSE, less dominated by a single large miss |
| Bid/ask deviation | distance of the fitted mark from the quoted mid, in spreads | A fit outside the bid/ask is economically implausible; flags a mis-fit or bad quote |
| Calibration error | max |Af - q| across quoted blocks | The direct constraint check; for an interpolant it must be at solver precision |
| Shape consistency | butterfly / second-difference sign flips | Detects implausible local concavity, usually a bad interpolation or mis-keyed mark |
| Liquidity score | depth and freshness of the quotes underpinning each tenor | How much real market backs each point, versus prior and inference |
| Confidence score | per-month [0,1] anchoredness to a real quote | How much of each point is market versus model, published alongside the price |
| Curve freshness | age of the newest and oldest quote on the board | A stale board silently poisons the curve; freshness is the first thing to check |
| Missing-quote % | fraction of tenors with no outright quote (inferred) | How much of the curve is prior-driven; rising as liquidity thins |
These metrics are the operational face of the uncertainty artefacts: RMSE and calibration error quantify the fit, confidence and liquidity scores quantify the trust, and freshness and missing-quote percentage quantify the board. Together they turn "is this curve good?" from a judgement call into a monitored, thresholded decision.
Multi-curve frameworks
A real desk does not manage one curve. A single valuation can touch a settlement curve, a pricing curve, a discount curve, an FX curve, a volatility surface, and one or more basis, transportation, and storage curves, each built with the same machinery but serving a different role, and they must be mutually consistent.
| Curve | Role | Interaction |
|---|---|---|
| Settlement curve | the authoritative daily marks used for official P&L | The reference other curves are reconciled against |
| Pricing curve | the live intraday curve positions are valued on | Must reconcile to settlement at close; drives real-time MtM |
| Discount curve | present-values future cashflows | Applied to every forward cashflow; often a rates/OIS curve |
| FX curve | forward exchange rates for cross-currency products | A gas curve in USD risk-managed in EUR inherits the EUR/USD forward |
| Volatility surface | implied vols across strike and maturity | Prices options and the optionality in swing and storage |
| Basis curve | the spread of a location/node to a liquid hub | Built on top of the hub curve; node = hub + basis |
| Transportation curve | the value of moving a commodity between locations | A locational spread; links two delivery-point curves |
| Storage curve | the value of moving a commodity across time | A calendar spread; its intrinsic value is a function of curve shape |
The key discipline is cross-curve consistency. A spark spread depends on the gas and power curves; a transported position depends on two locational curves; a cross-currency deal depends on the commodity and FX curves. If any pair is built at different as-of instants or on incompatible calendars, the spread inherits a phantom basis that shows up as fake P&L. The single-curve arbitrage suite therefore grows a cross-curve layer that checks the implied spreads against the quoted spreads.
AI applications in curve construction
Machine learning does not replace the constrained fit, which must still hit today’s quotes exactly and admit no arbitrage, but it augments the parts of the pipeline that are statistical rather than deterministic: cleaning the board, filling the illiquid region, and predicting shape from fundamentals.
- Anomaly detection in quotes. A model trained on historical quote behaviour flags a mark that is out of line with its neighbours, its own history, or correlated products, catching fat-finger errors and stale feeds before they reach the solver, a learned complement to the rule-based crossed/wide/stale checks.
- Missing-quote prediction. When a tenor has no quote, a model conditioned on the quoted points, the seasonal shape, and correlated markets predicts a value with an uncertainty, a richer prior than a fixed seasonal shape for the constrained fit to lean on.
- Curve completion for illiquid tenors. Gaussian-process and similar probabilistic models fill the illiquid region with a posterior mean and variance, exactly the per-point confidence band the workhorse engine approximates heuristically.
- Adaptive interpolation. Rather than a fixed method, a model can choose the interpolation and shaping per curve region based on liquidity and historical behaviour, tightening where quotes are dense and deferring to the prior where they are sparse.
- Weather-driven shape prediction. For gas and power, temperature and its forecast drive demand and therefore the seasonal and prompt shape; a weather-conditioned model predicts the shape the curve should take, improving the prior in the illiquid months.
- Renewable generation and load forecasting. Wind and solar output and system load shape the hourly power curve directly; forecasts of both feed the hourly shape engine, especially in renewable-heavy zonal markets like Nord Pool and EPEX.
- Probabilistic curve generation. Generative models produce coherent curve scenarios for VaR and stress testing that respect seasonality and cross-tenor correlation, a data-driven complement to PCA-based scenario generation.
The governing rule is that AI improves the statistical stages, cleaning, prior, shape, scenarios, but the deterministic guarantees, exact repricing of quotes and arbitrage-freeness, remain the job of the constrained fit and the validation suite. A neural curve that does not reprice the quotes or admits a spread arbitrage is not publishable, however good its shape; AI proposes, the constraints and diagnostics dispose.
Failure case studies: how real curves break
Every rule in a production engine exists because a curve once broke. Each case follows the same anatomy, symptom → root cause → detection → fix → prevention, because that discipline is itself the lesson.
- Cubic spline created negative gas prices. A downstream storage model booked "free" summer injection. Root cause: a natural cubic spline on a steep shoulder-month curve overshot below zero between quotes. Detection: the negative-forward check flagged a sub-zero month. Fix: switch to a shape-preserving interpolant, whose no-overshoot is a theorem. Prevention: make it the default and gate publication on the negative check.
- Duplicate exchange quote caused rank deficiency. The solve returned a garbage curve intermittently. Root cause: the same product arrived from two feeds, adding an identical constraint row and making the system singular. Detection: the solver’s rank check triggered the SVD fallback and logged it. Fix: deduplicate in the market-data layer. Prevention: the dedup stage plus the solver’s rank guard, two independent defences.
- Stale calendar strip distorted a storage valuation. A storage desk’s intrinsic value drifted overnight with no market move. Root cause: a cal-year strip mark was not refreshed after the quarters moved, so the board was internally inconsistent and the reconciliation bent the whole curve. Detection: the residual analyzer ranked the cal strip as the top stale-mark suspect. Fix: refresh the cal and refit off the quarters. Prevention: a pre-fit consistency check on every board.
- Daylight-saving time broke hourly power aggregation. A power day’s baseload did not match the hourly build twice a year. Root cause: the day was assumed to be 24 hours; the spring-forward day has 23 and the autumn day 25. An £80 baseload on the 23-hour day misprices by about £3.48/MWh. Fix: compute hours from the actual DST-aware calendar. Prevention: a regression test on the two DST days every year.
The pattern across all of them is the thesis in miniature: the failure was a data, convention, or numerical issue, never the interpolation maths, and each was caught (or should have been) by a cheap diagnostic gate, not by staring at the fitted number.
Business impact: why curve quality is money
Interpolation choices feel academic until you trace them into valuation. The curve is the input to every commodity structure, and its shape, not just its level, drives value.
- Storage intrinsic value. Storage earns the summer-winter spread; its intrinsic value is a function of the shape of the curve across the year. A cubic spline’s overshoot pushing the summer trough down can inflate the winter-summer spread by several percent, a spurious, material valuation manufactured purely by the interpolation artefact.
- Swing option valuation. A swing contract’s extrinsic value comes from optionality around the curve; a curve with spurious kinks creates phantom take-more/take-less signals a naive valuation monetises as fake extrinsic value. A clean, kink-free curve is a prerequisite for a defensible swing price.
- Spark-spread valuation. The spark spread is power minus a heat-rate multiple of gas; it depends on two curves and their alignment. If the gas and power curves are built with inconsistent conventions (one on a gas-day calendar, one on a power-hour calendar, mis-synchronised), the spread inherits a spurious basis that shows up as phantom P&L.
The through-line: every downstream valuation inherits the curve’s errors, and the errors that matter most are in the shape of the illiquid, inferred region, exactly the region this machinery, shape-preserving interpolation, prior-pinned inference, published confidence, is built to get right and to flag when it cannot. This is the direct link between curve construction and real-time valuation, Value at Risk, and the valuation and risk engines that consume the curve.
A multi-commodity book is a graph of curves, and the spreads are only arbitrage-free if the curves are built consistently, same as-of instant, compatible conventions, shared calendars. The single-curve arbitrage suite grows a cross-curve layer: does the spark spread implied by the gas and power curves match the quoted spark? A phantom basis between two internally-perfect curves is still phantom P&L.
Publishing uncertainty: the research frontier
The constrained-least-squares-with-a-prior engine is the industry workhorse, but it is not the last word. A front-office quant is expected to know where the field is going.
- Gaussian-process curve construction. Model the curve as a draw from a Gaussian process with a seasonal-plus-smooth kernel; condition on the quotes to get a posterior mean and variance. The variance is the prize: a principled, per-point uncertainty band that is small at quoted tenors and large in the illiquid gaps, the confidence score of the workhorse engine, but derived rather than heuristic.
- Neural curve fitting. A network can learn a flexible curve family from history, capturing nonlinear seasonal and cross-commodity structure a fixed kernel misses, at the cost of interpretability and arbitrage control. Promising for shape priors, risky as the final fitter.
- Dynamic factor models. Represent a whole panel of curves by a few latent factors evolving over time, excellent for co-movement and scenario generation; the daily fit still needs the constrained solve to hit today’s quotes exactly.
- Kalman filtering. Treat the curve’s latent state as evolving and update it as new quotes arrive, blending yesterday’s curve against today’s marks, a time-dynamic version of the prior-plus-quotes idea.
A worked Gaussian-process fit conditions a periodic-times-smooth kernel on a few quoted outrights and predicts every month with a band. At the quoted months the uncertainty collapses to the mark-noise floor; in the gaps it widens; and beyond the last quote it fans out furthest, the model correctly becoming least certain where it is extrapolating past all data. That published band is the honest artefact the workhorse engine approximates with its confidence score: a curve that tells you, per point, how much to trust it.
Frequently asked questions
Why must the gaps between quoted points be filled at all?
Because a usable curve needs a price for every delivery date, often 365 or more, while the market only quotes a handful of points. Any position settling in an unquoted period still needs a price, so the gaps must be filled to value arbitrary dates.
Why is linear interpolation considered safe?
A linearly interpolated value always lies between its two neighbours, so if both neighbours are positive the value cannot be negative or exceed them. No overshoot is possible, which makes it bullet-proof against impossible prices, though it can under-read a genuinely convex curve.
What danger do smooth spline interpolations introduce?
Overshoot: a spline can curve below the lowest quote or above the highest between points, sometimes producing negative prices. This manufactures arbitrage the data never implied, which is why shape-preserving methods and a range-check are used.
Where do most production curve failures actually come from?
The market-data layer, before the fit: crossed or wide broker quotes, stale settlements, duplicates that make the constraint matrix rank-deficient, and time-synchronisation errors. A great fit on a bad board is still a bad curve.
What is the curve Jacobian used for?
It is the exact, closed-form sensitivity of every curve point to every quote, J = A^T (A A^T)^-1. It serves as the curve’s delta ladder for risk and directly gives hedging recipes that map an illiquid inferred month onto tradeable quoted products.
Why does an hourly curve require sparse linear algebra?
An 8,760-point dense matrix is about 0.61 GB and takes seconds to solve, while the sparse tridiagonal equivalent is 0.21 MB and solves in milliseconds, a 2,482x speed-up. On a desk rebuilding many hourly curves, the dense version neither fits in memory nor in time, so sparsity is a prerequisite, not an optimisation.
What is the difference between Nelson-Siegel and Smith-Wilson?
Nelson-Siegel is a parsimonious three-factor parametric form (level, slope, curvature) that fits a smooth term structure but does not reprice every quote exactly. Smith-Wilson interpolates the observed points exactly and extrapolates toward a mandated long-term level, which is why it is used for regulated discount curves.
When should I use a shape-preserving spline instead of a cubic spline?
Use a shape-preserving (PCHIP-style) spline whenever an overshoot would be harmful, which is almost always for traded commodity forwards, because a natural cubic spline can dip below the data and produce negative prices. A cubic spline is only appropriate when the data is clean and genuinely convex and C2 smoothness is required.
How is a mean-reverting (Ornstein-Uhlenbeck) model calibrated?
Typically by fitting an AR(1) regression of the price change on the level: the slope gives the mean-reversion speed, the intercept gives the long-run level, and the residual standard deviation gives the volatility. Maximum-likelihood and seasonal-level variants refine this for storage and swing valuation.
What curve quality metrics matter most in production?
Calibration error and negative-price checks are hard-fail gates; RMSE and MAE measure fit quality; confidence and liquidity scores measure trust; and curve freshness and missing-quote percentage measure the board. Together they turn "is this curve good?" into a monitored, thresholded decision.
Why do commodity desks manage multiple curves?
A single valuation can touch a settlement curve, a pricing curve, a discount curve, an FX curve, a volatility surface, and basis, transport, and storage curves. Each plays a distinct role, and the spreads between them are only arbitrage-free if the curves are built to the same as-of instant on compatible conventions.
How is AI used in curve construction?
AI augments the statistical stages, anomaly detection in quotes, missing-quote prediction, curve completion for illiquid tenors, weather-driven shape and load forecasting, and probabilistic scenario generation, while the deterministic guarantees of exact repricing and arbitrage-freeness remain the job of the constrained fit and the validation suite.
Keep exploring
See it on your own trades
The fastest way to understand this in practice is a working walkthrough mapped to your desk.
Request a demo Platform overview