The market's volatility channel

Table of Contents

1. Summary

The market-wide factor moves the tick clock today and leaves the price law alone: a panic arrives as more observations of the same random walk. A market that is busy is also more volatile, and the same shared factor can carry that, because the arrival work already publishes it and every price process already holds the knobs a loading would scale. What is missing is three small seams — a setter on the price process, a loading on the link and the config row, and one line in each feed — plus the calibration that keeps a run's sigma what its configuration states. This note states those seams, the tail channel the mixture adds, and the bivariate Hawkes that would make activity and volatility excite each other; it also settles whether a rate change moves time at all.

2. Detail

2.1. What the factor is today

One state machine and one shared heat, read once per tick:

A(t) = S(t) + C(t) / R(t)

where S is the calm/active multiplier (calm derived so its long-run mean is one), C is the heat any event adds to and decay fades, and R is the summed mean rate of the series enrolled with the heat, so a series takes the share of C its own rate is of the total. The scheduler integrates A into the market's operational time, tau, and runs each feed's arrival law in sensitivity * tau. The rates move; the prices do not.

The heat's long-run mean is not zero — it settles at the event rate times jump/decay — so with the heat on, the average rate is above the configured one. That is a known property of the rate channel, and it is the first thing the volatility channel has to decide about rather than inherit.

2.2. Sampling against time

A diffusion's variance follows elapsed time, not the number of observations. Double the tick rate and a correctly written price law gives twice as many samples of the same path per second, not twice the variance.

The processes in ores.analytics.quant are of two kinds and they behave differently under a rate change:

  • A process with a time-scaled law takes next(elapsed_ticks), and the feed passes elapsed_seconds * ticks_per_second. A higher rate shortens each gap, so each step covers less time, and the variance per wall-clock second is unchanged. This is the correct behaviour, and it is what the arrival time-rescaling test asserts.
  • A process that answers supports_variable_step() = false= takes one nominal step per tick. When each step's variance is the same, the same nominal step now fits into a shorter gap, so variance per wall-clock second rises in proportion to the rate, and sigma with its square root.

2.3. Three quantities, and the choice between them

Every feed carries three numbers, tied together:

Symbol Meaning
r ticks per wall second: how often the feed publishes
Delta simulated time per tick: how far the law steps
v simulated seconds per unit of market time: how fast the simulated world runs

They satisfy v = r * Delta, so two of them are the design and the third follows. Which two are chosen is the whole question.

Measured before any code was written, the platform chooses them inconsistently:

  • A spot feed takes the gap, so Delta is the wall gap and v = 1: the simulated world runs at real speed.
  • A curve feed is built with Delta = one calendar day (the constant 1 / 365 year, ir_curve_feed_dt), so at one tick a minute v ≈ 1440: the simulated world runs fourteen hundred times faster than the spot feeds beside it.

So the market lives in two times at once, and nobody chose either. A rate change on a curve moves time; on a spot feed it does not. That is not a defect in either path but a missing decision.

The decision: v belongs to the market, one number for the run, and a feed's rate is pure sampling. Simulated time runs on the market's operational time, tau, which every feed already shares: the simulated world advances by v for each unit of tau. A tick therefore steps its price by the simulated time since the feed last ticked, v * (tau now - tau at the last tick), and a periodic feed at rate r steps by Delta = v / r.

  • One clock for every feed: spot and curve feeds live in one simulated world, because they share tau.
  • A rate change changes sampling only, and so does a feed's sensitivity: more ticks in a unit of tau, each covering less of it.
  • The default v keeps a curve at one tick a minute stepping a calendar day, as it always has. A spot feed deliberately speeds up to the run's v: at the default, a tick covers 1440 times the simulated time it did, so its moves per tick grow by about the square root of that, because that is the inconsistency being removed. A spot feed's parameters state its moves per nominal tick, and the Simple editor derives them from a move per hour, so a person sets them in simulated time.
  • A busy market runs tau, and so the simulated world, faster in wall time. Volatility per unit of market time stays fixed; volatility per wall second rises with the pace. A busy market is busier in time, not rougher per tick.
  • v is fixed for a run, set by the service's --market-speed, and logged at start. A curve's step is fixed when its feed is built. Setting v while a run goes on is left to the task that sets the market's chain and heat.
  • A higher rate therefore gives a smaller step, which is the safe direction for every numerical scheme.
  • The default v is chosen so a curve at one tick a minute keeps the numbers it produces today (v = 1440). Spot feeds deliberately speed up to the run's v, because that is the inconsistency being removed.
  • v is visible where a person watches the market, on the dashboard and the Market regime tab, because "how fast is this world running" is a question a demonstration asks and no screen answered.

2.4. A step is a discretisation, not the model

Nothing here changes a model's specification. dr = kappa(theta - r) dt + sigma dW says nothing about how often it is stepped. The processes that implement the exact transition of their law — the affine family, Vasicek, Hull–White, CIR, Ornstein–Uhlenbeck, and the Gaussian mixtures as exact normal increments — are the model for any Delta. The Euler and tree schemes (Black–Karasinski, Black–Derman–Toy, HJM, LMM) approximate it, and their error grows with the step.

Each such process therefore declares the largest step its scheme can take, and a feed refuses a rate so low that the step would exceed it, rather than silently producing a biased path. A step is also calendar time: real curves step on business days and skip weekends and holidays, which this design does not do. That is a limitation to state, not to build now.

The clean formulation is business time. Let

Theta(t) = integral of A(s) ds

be the integrated activity, and let the price process run on business time with a volatility per unit of it. Then "more activity" and "more variance per second" are two dials instead of one, and a series that is merely observed more often is visibly unchanged.

2.5. The volatility loading

Three seams, each mirroring something the arrival work already has:

  1. i_stochastic_process gains set_volatility_multiplier(double), the price side of what the operational clock does for arrivals. The default refuses; the processes that can honour it scale their own sigma — a Gaussian mixture scales its stdevs, a short-rate model its sigma — and keep their means.
  2. A feed's series_spec gains volatility_sensitivity beside sensitivity. A feed that follows the market in rate and not in volatility sets it to zero; the default follows the rate loading, because a market that only ticks faster is the artefact this note exists to remove. Both generation-config kinds gain the column, which is a schema change with a migration and a codegen run — the one part of the loading that is not a line of code, and the reason the task under it is sized as it is.
  3. Each feed applies it on its tick, beside the arrival multiplier it already reads.

The law, with the loading written as a volatility multiplier:

M_vol(t) = (sensitivity_vol * A(t))^gamma sigma_effective = sigma * M_vol(t)

and the exponent is what decides which quantity follows activity:

  • gamma = 1/2 gives variance proportional to activity, which is the mixture-of-distributions reading and the default: the same diffusion with more time in it, so Clark's mixture holds and a busy minute is a wider minute.
  • gamma = 1 gives sigma proportional to activity, and variance proportional to its square. That is the right choice for a series whose step count rather than its clock drives the variance — which is what a fixed-step process does today, and therefore the behaviour the first task removes.

The exponent is a knob because the evidence does not settle it; the default is the one the literature supports.

Calibration is the work, not the plumbing. A run's sigma must stay the sigma its configuration states unless a person pins a state. The state's long-run mean is one by construction, so it needs nothing. The heat's is not: it settles at a rate, the event rate times jump/decay, which is the derivation in Carry a market-wide arrival regime. So the volatility margin centres it, with a floor:

A_centred(t) = max(S(t) + (C(t)/R(t) - E[C/R]), epsilon) M_vol(t) = (sensitivity_vol * A_centred(t))^gamma

Subtracting the heat's mean keeps the long-run mean of A_centred at one, so the run's average multiplier is the loading and the sigma stays calibrated. The floor is not cosmetic: without it a calm market with a negative margin can drive the multiplier to zero or below, which makes a price freeze. With the floor the long-run mean is one up to the mass of the draws that hit it, and the note's test must accept that tolerance rather than an exact one.

Two meanings of volatility must be kept apart in every test:

  • the sigma of the process, which is what the loading moves;
  • the sigma a client computes from the ticks published, which also moves with sampling frequency and microstructure noise, and which rises even when the process is unchanged.

2.6. The daily variance

The loading moves volatility within the day. It does not carry a calm or a turbulent state from one day to the next: the heat fades over minutes to hours, and the calm/active chain is a property of the market, not of one pair's history. That memory is the job of the GJR-GARCH variance each FX spot carries, described in Volatility clustering and GARCH models under "Daily GJR-GARCH variance of synthetic FX spot". The two compose by multiplication:

Var(tick) = sigma_d^2 * M_vol(t)^2 * s

where sigma_d^2 is the day's GARCH variance, M_vol the loading above and s the share of the day the tick covers. The loading is calibrated so its long-run mean leaves a run's sigma as configured, so over a day the expected variance is still sigma_d^2: GARCH sets how much variance the day has, and the channel decides where in the day it falls.

The coupling runs one way by construction. A busy day, with the loading high, produces a larger day return, and the GARCH update at the day's end turns it into a larger variance for the next day, so intraday activity reaches the daily variance with no mechanism beyond the two models. Realized GARCH (Hansen, Huang and Shek, 2012) updates the variance from an intraday realised measure instead of the squared day return, which is less noisy; the generated path is known exactly, so that measure is available. The other direction, a high daily variance raising the rate of arrivals, is activity and volatility exciting each other, the bivariate model of "Out of scope: activity and volatility exciting each other".

2.7. The tails

A diffusion whose sigma doubles gives wider returns but the same shape. A panic does not look like that: prices gap, and the kurtosis rises faster than the variance. An FX feed's law is already a Gaussian mixture, so the tail channel changes the mixture rather than the model.

The first design moved weight from the narrow components to the wide ones as A rose, with the stdevs rescaled to hold the variance. That rule does not always fatten the tails. At a fixed variance a scale mixture's kurtosis peaks at a small wide weight, so moving weight past that peak thins the tails. Weights of 0.8 and 0.2 on stdevs in the ratio one to four have a kurtosis of 9.75. When the weight moves at a tilt of 2 ln 2, the kurtosis falls to about 4.4.

The rule adopted spreads the stdevs instead. At a tick, the tilt is tail_loading * ln A, and each stdev becomes stdev ^ (1 + tilt). Then one factor scales all of them, so the mixture's variance is what it was. The weights and the means do not move, so neither does the mean. The kurtosis is 3 E[s^2a] / E[s^a]^2 over the components' variances s, with a = 1 + tilt. That is one plus the squared coefficient of variation of s^a, which rises with a for any mixture whose stdevs differ. So the kurtosis rises with activity. A calm market, A < 1, draws the stdevs together, down to one shared stdev at a tilt of minus one, which is as far as it goes.

The rule is variance-preserving, so it composes with the loading: the tilt sets the shape, and the loading sets the scale. tail_loading is one number for the market. It defaults to zero, which leaves every mixture as configured, and the system tenant sets it beside the market's other numbers. It is refused above ten. At a pace of two, a loading of ten tilts by about seven, and the widest component already carries nearly all the variance. Beyond that, the mixture degenerates to one component and a larger loading changes nothing.

2.8. The control plane

No new verb and no new service. The pieces that exist carry the new number:

  • The switch. synthetic.v1.ops.pin_market_regime stays as it is. Auto, Calm and Active move the rate and the volatility together, because a person pressing Active expects the prices to move, not only the clock.
  • The read. get_market_regime_response gains the volatility multiplier beside the rate multiplier, so the shell's synthetic regime get and the BFF's route report both without a new subject.
  • The screen. The Market regime tab shows both multipliers and the same raster; a feed's Arrivals tab gains one field, volatility sensitivity, beside sensitivity, edited and audited exactly as that one is.
  • Permissions. Unchanged: the same two subjects, the same session rules, the same permissions.

The tests each part must pass:

Part Test
Sampling against time A rate multiplier of two leaves the variance per wall-clock second unchanged for a process that takes the gap, and a fixed-step process is refused or converted before it can be re-rated
The loading, calibration Over a long run with the heat on, the realized sigma equals the configured sigma
The loading, response A pinned active market raises the realized sigma by the feed's loading, and calm lowers it
The tails The kurtosis of returns rises with activity while the mean and the long-run sigma hold
The control plane The switch, the read and the tab carry both multipliers without a new subject or permission

2.9. Out of scope: activity and volatility exciting each other

The complete object is a bivariate Hawkes: activity excites volatility and volatility excites activity, and today's heat is one coordinate of it. The rank-one kernel of the arrival note generalises:

K = diag(n) + m * 1'

becomes a 2x2 block of the same shape, and stability stops being the scalar test max n + sum m < 1 and becomes a spectral radius: the largest eigenvalue of the mean kernel must be below one. That is a model of its own, it depends on all of the above, and it is captured rather than scoped here: Make activity and volatility excite each other.

3. Literature

Every part of this approach is a named idea with a paper behind it, and the ones it deliberately does not adopt matter as much as the ones it does. Grouped by the section that leans on each entry, with one line on what it gives us.

3.1. Activity and volatility are one latent process

  • Clark (1973), A subordinated stochastic process model with finite variance for speculative prices, Econometrica 41(1) — the mixture-of-distributions hypothesis: returns are a mixture over an unobservable information-arrival rate, and tick counts and |returns| are two proxies for it. The paper the loading's "variance proportional to activity" comes from.
  • Easley and O'Hara (1992), Time and the process of security price adjustment, Journal of Finance 47(2) — trading time carries information, so a law indexed by clock time misses the variable that matters.
  • Ané and Geman (2000), Order flow, transaction clock, and normality of asset returns, Journal of Finance 55(5) — near-normal in transaction time, fat-tailed in calendar time. The sharpest case for keeping sampling and time apart, which is the story's first task.
  • Engle (2000), The econometrics of ultra-high-frequency data, Econometrica 68(1) — durations and returns estimated jointly: the statistical shape of what this note proposes.
  • Engle and Russell (1998), Autoregressive conditional duration, Econometrica 66(5) — the durations model the arrival processes echo.
  • Karpoff (1987), The relation between price changes and trading volume: a survey, Journal of Financial and Quantitative Analysis 22(1) — the empirical volume-volatility relation the factor stands in for.
  • Easley, López de Prado and O'Hara (2012), The volume clock, Journal of Portfolio Management 39(1) — sampling on activity rather than on the clock, in practice rather than in theory.
  • Cont, Kukanov and Stoikov (2014), The price impact of order book events, Journal of Financial Econometrics 12(1) — the measured link between event intensity and short-horizon volatility.

3.2. Business time

  • Bochner (1955), Harmonic Analysis and the Theory of Probability — subordinating one process by another: the mathematics of a clock that runs on activity.
  • Mandelbrot and Taylor (1967), On the distribution of stock price differences, Operations Research 15(6) — operation time, the first trading-time formulation.
  • Madan and Seneta (1990), The variance gamma model for share market returns, Journal of Business 63(4) — a time change that already carries the tail, and the prior art for gamma rather than activity as the clock.
  • Carr and Wu (2004), Time-changed Lévy processes and option pricing, Journal of Financial Economics 71(1) — time-changing a process with jumps, which is the honest version of "the tails move with activity".

3.3. Stochastic volatility, regime switching and GARCH

  • Engle (1982), Autoregressive conditional heteroscedasticity, Econometrica 50(4), and Bollerslev (1986), Generalized autoregressive conditional heteroskedasticity, Journal of Econometrics 31(3) — volatility clustering as a process on variance itself. The channel does not model it; the daily GJR-GARCH variance of each spot does, and the two compose as "The daily variance" states.
  • Hull and White (1987), The pricing of options on assets with stochastic volatilities, Journal of Finance 42(2), and Heston (1993), A closed-form solution for options with stochastic volatility, Review of Financial Studies 6(2) — stochastic volatility as a second factor with its own law: vol-of-vol and the leverage effect, neither of which activity-driven variance reproduces.
  • Hamilton (1989), A new approach to the economic analysis of nonstationary time series and the business cycle, Econometrica 57(2) — the regime-switching ancestor of the calm/active chain.

3.4. Hawkes, endogenous activity, and multivariate stability

  • Hawkes (1971), Spectra of some self-exciting and mutually exciting point processes, Biometrika 58(1) — the model, and already the mutually exciting form: activity exciting volatility is a use of it, not an extension.
  • Ozaki (1979), Maximum likelihood estimation of Hawkes' self-exciting point processes — how such a process is fitted, which is what a calibration path would need.
  • Ogata (1981), On Lewis' simulation method for point processes, IEEE Transactions on Information Theory 27(1) — thinning, the method the arrival processes use.
  • Daley and Vere-Jones (2003), An Introduction to the Theory of Point Processes — the reference for the conditions the kernel must satisfy.
  • Bacry, Delattre, Hoffmann and Muzy (2013), Modelling microstructure noise with mutually exciting point processes, Quantitative Finance 13(1) — the closest published model to what the platform runs today.
  • Bacry, Mastromarino and Muzy (2015), Hawkes processes in finance, Market Microstructure and Liquidity 1(1) — the survey that states the multivariate stability conditions.
  • Brémaud and Massoulié (1996), Stability of nonlinear Hawkes processes, Annals of Probability 24(3) — why a scalar rank-one test becomes a spectral radius.
  • Aït-Sahalia, Cacho-Diaz and Laeven (2015), Modeling financial contagion using mutually exciting jump processes, Journal of Financial Economics 117(3) — contagion as two mutually exciting jump processes: the bivariate design with jumps, and its empirical case.

3.5. The tails

  • Merton (1976), Option pricing when underlying stock returns are discontinuous, Journal of Financial Economics 3(1) — the jump-diffusion whose tail a diffusion scale cannot reproduce.
  • Barndorff-Nielsen and Shephard (2006), Econometrics of testing for jumps using bipower variation, Journal of Financial Econometrics 4(1) — how a jump is told from a diffusion in observed data, which is how our tail test should be written.

3.6. Cross-series correlation: asynchrony and the Epps effect

  • Epps (1979), Comovements in stock prices in the very short run, Journal of the American Statistical Association 74(366) — measured correlation falls as the sampling interval shrinks. The limitation on any claim that cross-series correlation rises with the factor: it must be measured over a stated interval.
  • Lo and MacKinlay (1990), An econometric analysis of nonsynchronous trading, Journal of Econometrics 45(1-2) — non-synchronous observations bias cross-series statistics, which is what desynchronising the feeds trades one way and the other.

3.7. Long memory and intraday seasonality

  • Andersen and Bollerslev (1997), Intraday periodicity and volatility persistence, Journal of Empirical Finance 4(2-3) — the intraday U-shape real markets have and the model does not.
  • Admati and Pfleiderer (1988), A theory of intraday patterns, Review of Financial Studies 1(1) — why that shape exists: liquidity traders cluster.
  • Baillie, Bollerslev and Mikkelsen (1996), Fractionally integrated GARCH, Journal of Econometrics 74(1) — the long memory in volatility that a finite-decay heat cannot reproduce.

3.8. Sampling, noise and what "volatility" means in a test

  • Andersen, Bollerslev, Diebold and Labys (2003), Modeling and forecasting realized volatility, Econometrica 71(2) — realized variance as an estimator and its sampling dependence.
  • Hansen and Lunde (2006), Realized variance and market microstructure noise, Journal of Business and Economic Statistics 24(2) — how much of realized variance can be noise at high frequency.
  • Zhang, Mykland and Aït-Sahalia (2005), A tale of two time scales, Journal of the American Statistical Association 100(472) — noise biases realized variance upward, more so the more often you sample. The reason every test must say which volatility it measures.

4. Limitations

What this design does not do, and what the papers above say about it. A note that lists only its support is a sales document.

4.1. Scope: what is not modelled

  • Not a stochastic volatility model. There is no vol-of-vol, no leverage effect (returns feeding back into variance) and no correlation between price and variance as there is in Hull–White and Heston. Variance is a deterministic function of the activity factor, so the generated surface has one source of volatility randomness where a real one has two.
  • No jumps of its own. Activity reweights a static mixture; a jump is not an event that arrives, excites the heat and excites further jumps. Aït-Sahalia et al. and Merton model the jump as a process; this design sets its probability.
  • Two regimes and fixed rates. The calm/active chain is two states with transition rates a person sets; Hamilton's class allows many states and an estimated transition matrix. There is no parameter uncertainty and no regime uncertainty beyond the chain itself.
  • No intraday seasonality and no long memory. Andersen and Bollerslev (1997) and Admati and Pfleiderer (1988) document the U-shape every real intraday series has; Baillie et al. (1996) document the long memory. The factor produces neither, so a generated day is stationary in a way a real day is not.
  • No explicit microstructure noise. The bid-ask bounce that makes real high-frequency data noisy is absent; a client computing realized variance from our ticks gets a cleaner number than from a real feed of the same frequency. Bacry et al. (2013) model that noise explicitly, and Zhang et al. (2005) show why its absence changes the answer.

4.2. Identification: what is assumed rather than estimated

  • The loading is a free parameter. Nothing in the platform estimates it from data; it is set by hand, and calibration means "the long-run sigma is the one the config states", not "the loading matches a market".
  • Variance proportional to activity is a choice, not a measurement. Clark leaves the mixing variable latent; this design makes it an observable factor and fixes the exponent to one. The exponent is a knob because the evidence does not settle it.
  • The heat is not the only latent variable. A real market's information arrival is what Clark's mixture is over; ours is a constructed heat whose jump and decay are demo constants, so the factor is a stand-in for a latent process that in reality is unobserved.

4.3. Measurement: what our own tests cannot see

  • "Volatility" means two things — the process's sigma and the sigma a client computes from published ticks — and sampling frequency moves the second even when the first is unchanged. A test that does not say which one it measures can pass while the product is wrong.
  • Cross-series correlation is interval-dependent. The Epps effect means a claim that a pinned market correlates the series must state the window; measured at tick frequency it will look weaker than at one minute, and desynchronising the feeds changes the number again (Lo and MacKinlay 1990).
  • A synthetic series cannot validate the model. Every statistic here is measured on data the model produced, so calibration is proved against the configuration, never against a market. Fitting the factor to real ticks is outside this story and would need Ozaki's or Bacry's estimation machinery.

4.4. Limits of the cited work, as they apply here

  • Clark's mixture identifies activity only through its proxies; two very different activity processes can produce the same return distribution, so a generated series matching the returns does not prove the activity is right.
  • Hawkes models are stable only inside their kernel's radius; our rank-one condition is necessary for the bivariate case but not sufficient, which is why the stability test has to become a spectral radius before two dimensions exist.
  • The Hawkes literature is fitted to message or trade arrivals, not to a shared heat across asset classes; the enrolment-and-share device this platform uses to keep the heat bounded is an engineering choice with no paper behind it, and its long-run effect on cross-series correlation has not been measured.

5. Deferred, and what would make each matter

None of the limitations above is in scope for the tasks this note scopes, and none should be. They are listed here with the condition that would make each one worth a story, so the decision is taken later on evidence rather than on memory.

Limitation What would make it matter Where it would live
No vol-of-vol and no leverage effect A generated surface has to price an option off the series, so skew and the price/variance correlation are read New story: a second factor with its own law
Jumps reweighted, not arrived A stress scenario needs a gap that spreads across series, not a wider walk in one Extends task "Let the factor reach the tails"
Two regimes with hand-set rates A scenario needs a third state, a rating ladder, or an estimated transition matrix Extends whatever sets the chain's rates
No intraday seasonality Generated ticks feed a realized-volatility or VaR backtest whose window spans a day New task on the synthetic service
No long memory A client compares our volatility persistence against a real instrument's With the seasonality task, or a separate one
No microstructure noise Someone validates our output against a real feed's high-frequency statistics, or prices an engine sensitive to noise New task, following Bacry et al.
The loading is set, not estimated Generated series have to be calibrated to a real instrument rather than to a configuration New story: estimation rather than generation
Cross-series correlation depends on the window A report claims the regime correlates the series, which the arrival story's acceptance already asks for Measurement work inside that report
The rank-one stability test is not sufficient in two dimensions The bivariate Hawkes is taken up The capture for it, in the inbox
The enrolment-and-share device is unpublished The enrolled population grows past a few hundred series, or a client asks why counts correlate as they do An investigation against the shared heat

The first two carry the most weight for a demonstration: a panic that cannot gap and cannot skew is a panic a person recognises as synthetic. The rest become important as the platform's output is used for something other than display.

6. See also

Emacs 29.3 (Org mode 9.6.15)