User Journey: Calibrate or refresh a surface
Table of Contents
This page documents a user journey: A trader builds or refreshes a candidate volatility surface from the day's market, reads its calibration error and its slices, and leaves it unpublished.
A user journey describes what one person is trying to do, before anything is built. It is a design document that outlives any sprint, so it names the screens, the entity fields each screen shows, and the operations and messages each step needs.
1. Goal
"I want today's quotes turned into a candidate surface I can price from, and I want to see how well that surface fits before anyone signs it off." The journey is done when a candidate surface exists for the chosen as-of, the person has read its calibration error and its slices, and the surface is still a candidate: nothing has been published, so pricing still reads the surface it read before.
2. Actor and trigger
The actor is the trader, acting as maker: the person who holds the market-data management role for this party. The trader owns the surface and is the only person who builds or refreshes it; an approver owns the decision to publish, in a different journey. The trigger is the start of a trading day, a market move, a fresh quote set, or a request from pricing. The journey starts at the list of curves and surfaces and ends when the trader leaves the surface unpublished.
A surface is a derived object. It is a candidate until it is approved and published, and only the published object is visible to pricing and reporting; see What is missing for the model and the engine that do not exist yet.
3. Steps
- Find the surface. The person opens Curves and surfaces and filters to
surfaces. The system lists the market series whose
series_subclassis volatility, one row peroresmd_uri, with its asset class and itsderivation_kind. There is no surface table to list, so the catalogue row is the only row the screen can show. - Choose the surface and an as-of. The person selects a series and an as-of
timestamp. The system reads the
market_seriesrow and the observations at or before that instant. The chosen as-of is the snapshot the calibration would read; the point-in-time read is a repository method (read_as_of), not an operation on the wire. - Read the market it is built from. The system lists the quotes the surface
is built from, one row per
oresmd_uri: the value, thesourcetag that published it, and itsobservation_datetime. An observation is evidence the market sent; nobody signs it off. - Confirm the parameterisation. The person checks the surface's axes, its
strike or moneyness convention, and the model the fit would use. The system
carries none of these: it shows the series'
derivation_kindand itsderivation_config_id=/=derivation_config_version, and it marks the fields the model does not hold as absent rather than showing them empty. See What is missing. - Fit the quotes to the parameterisation. The person chooses Calibrate candidate. The system has no calibration engine and no operation to call, so the step names the subject it needs and changes nothing. See What is missing.
- Read the calibration error. The person reads the fit error for the candidate, by slice and overall. Nothing serves it: the only curve compute the server offers returns bootstrapped discount points, not a surface fit error.
- Read the slices. The person inspects the smiles across tenors and the
surface mesh. The snapshot read is keyed by an
oresmd_uriand reconstructs curve or grid points; it has no surface or slice shape, so the screen shows the quotes alone. - Refresh or leave. The person either excludes a quote, changes the as-of and refits, or accepts the candidate. Refitting repeats step 5.
- Leave unpublished. The person chooses Leave unpublished and returns to the list. The system records no publication: the surface stays a candidate, and the published object pricing reads is unchanged.
Calibration, if it existed, would be a server-side computation that writes a derived series, so the journey would not carry state between steps: the reply would carry the candidate. Nothing in this journey publishes.
4. Screens and wireframes
One screen. The surface row and its as-of sit at the top, the quotes and the parameterisation sit in the middle, and the calibration error and the slices they produce sit at the bottom, so the person reads cause above effect. The state line at the foot says the surface is a candidate only.
Figure 1: Surface calibration: the surface and as-of, the quotes it reads, the parameterisation, and the calibration error and slices.
5. Prototype
A static page at doc/prototypes/market_data/calibrate-or-refresh-a-surface/index.html: mock data only, no backend,
no build step and no session. It argues that a surface fit is a calibration error before it is a picture: the error, the slices and the mesh answer different questions.
- Variants
- a the slice table, b the 2-D smile, c the fit-error summary
- States
- converged, failed (no convergence, the last iterate shown as such)
- Source
doc/prototypes/market_data/calibrate-or-refresh-a-surface/index.html- Open
/OreStudio/doc/prototypes/market_data/calibrate-or-refresh-a-surface/once the site is built, or the file directly
6. Entities composed
| Entity | What it contributes | Model |
|---|---|---|
market_series |
The surface identity: the oresmd_uri, its asset class, and its =derivation_kind=/config/version marking it derived |
ores.marketdata.market_series |
market_observation |
The market quotes the surface is calibrated from, one point per oresmd_uri and observation_datetime |
ores.marketdata.market_observation |
observation_lineage |
The provenance of each derived surface point: which config/version and which source series it read | ores.marketdata.observation_lineage |
market_series_asset_class |
The asset class the surface list filters on | ores.marketdata.market_series_asset_class |
tenor |
The tenor axis labels the quotes and smiles are named by | ores.refdata.tenor |
ir_curve_bootstrap_config |
The nearest existing derivation recipe: the config whose id/version the series carries | ores.refdata.ir_curve_bootstrap_config |
currency |
The currency the surface is quoted in | ores.refdata.currency |
The models above are what the screen can read today. There is no surface model, so the parameterisation, the strike labels and the calibration-error rows have no entity to compose; see What is missing.
7. Operations and messages
| Step | Operation | Subject | Status |
|---|---|---|---|
| Find the surface | List the series that may be a surface | marketdata.v1.market_series.list |
exists |
| Choose the surface | Read one series | marketdata.v1.market_series.get |
exists |
| Read the market | List the observations of one series | marketdata.v1.market_observations.list_by_series_id |
exists |
| Read the slices | Read the curve/grid snapshot for an oresmd_uri |
marketdata.v1.curve_snapshot.get |
partial |
| Confirm the parameterisation | Read the derivation config | refdata.v1.ir_curve_bootstrap_configs.get |
partial |
| Fit the quotes | Calibrate the surface | marketdata.v1.surface.calibrate |
missing |
| Read the calibration error | Read the fit error | marketdata.v1.surface.calibration.get |
missing |
| Read the slices | Read one smile | marketdata.v1.surface-slice.get |
missing |
| Refresh the surface | Re-read the observations over a range | marketdata.v1.ops.get_series_evolution |
exists |
| Leave unpublished | Arrange the approval later | inbox.v1.ops.raise_approval |
exists |
| Check the change trail | Read the series' history | marketdata.v1.history.get |
exists |
The generic history read is the one with entity_type
ores.marketdata.market_series; market_series registers a history provider.
The snapshot and buckets reads are keyed by the oresmd_uri, not by a typed
surface identity, and both read now: .get has no as-of parameter and
.buckets serves five half-hour buckets ending now. The approval subject is
the generic one; the approval kind that would carry how many approvals a
surface publish needs and which group decides it does not exist yet.
8. What is missing
- There is no surface model. No table carries a surface's axes, its
quoting convention or its parameterisation, so the screen cannot show what
the surface is. The candidate is a surface entity, and its axe and
parameter entities, in
ores.marketdataorores.refdata. Until then the screen listsmarket_seriesrows whoseseries_subclassis volatility and marks the missing fields as absent. - There is no calibration engine and no operation to call it. The subject
marketdata.v1.surface.calibratewould have to be added, with a request that names the surface and the as-of and a response that carries the fitted points and the fit error. Until then the Calibrate candidate button names the step and stays inert. - There is no quoting convention and no strike-label vocabulary. Nothing
says whether a strike is an absolute level, a delta, or a moneyness, so a
strike axis cannot be labelled and the quotes cannot be mapped to the
surface's parameterisation. The candidate is a vol quoting convention in
ores.refdata. Until then the screen shows the raworesmd_uricoordinates and no axis labels. - There is no calibration-error read. The subject
marketdata.v1.surface.calibration.getwould have to be added to return the residual per quote and the error per slice. Until then the calibration error panel is empty and labelled. - There is no surface or slice read.
marketdata.v1.curve_snapshot.getreconstructs curve or grid points at one instant and has no surface shape, and there is no slice subject. The candidate is a surface read, with a slice subject such asmarketdata.v1.surface-slice.get, on top of the modelled surface. Until then the screen shows the quotes alone; the concurrent slices journey Inspect a surface's slices records the same gap from the reading side. - A read cannot be taken as of a time in the past. Both snapshot reads
always read now, so the as-of the person chooses cannot be served over the
wire; the point-in-time read exists only as the repository method
read_as_of. The candidate is anas_ofparameter on the snapshot request. Until then the screen offers the current snapshot and cannot reproduce yesterday's calibration. - The surface has no typed identity at the wire. Every read is keyed by
the
oresmd_uristring, so a caller cannot ask for "the USD swaption surface" without knowing the URI spelling. The candidate is a typed surface read,marketdata.v1.surfaces.*. Until then the screen shows the URI as the identity.
9. Related journeys
- Author a surface's framework — set the axes, the quoting convention and the model this calibration reads.
- Adjust a curve or surface by hand — correct a candidate where the market is thin or wrong.
- Inspect a surface's slices — read the smiles and the mesh the calibration produced.
- Ask for a publish to be approved — put the candidate surface to a second pair of eyes.
- Watch a curve or surface evolve — see how the published surface moved over the day.
10. Related knowledge
11. See also
- Market data journeys
- Bootstrap or refresh a curve — the curve-shaped sibling this journey mirrors.
- Inspect a surface's slices
- User Journeys