Phase 2: realized volatility, volume and VWAP metrics#1
Merged
Conversation
Extend the windowing pass to compute more microstructure metrics alongside order-flow imbalance and persist them to a unified table. - rename ofi.rs -> metrics.rs; OfiBucket -> MetricsBucket now carries trade_count, vwap and realized_volatility - realized volatility is continuous across window boundaries, so the per-window variances sum to the whole tape's realized variance and a single-tick window still records its move away from the prior trade - storage writes one wide `metrics` row per (bucket_start_ns, window_ns) - unit tests assert every field against hand-computed known data
Read the engine's unified `metrics` table through a shared _query_metrics helper and expose one view per metric family. - /metrics/ofi keeps its Phase 1 response contract - /metrics/volatility returns realized_volatility and trade_count - /metrics/volume returns buy/sell/total volume and VWAP - tests cover projection, limit capping/validation and the missing/empty-database 503s across every endpoint
Check off Phase 2 in the roadmap, add curl examples for the new volatility and volume endpoints, and document three calls: the unified metrics table, continuous cross-window realized volatility, and folding VWAP into the same pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 2 of the roadmap: extend the engine beyond order-flow imbalance to a full set of
per-window microstructure metrics, persisted to a single table and served through the API,
all covered by tests against hand-computed known data.
What changed
Engine (Rust) —
ofi.rs→metrics.rsOfiBucket→MetricsBucket, now carryingtrade_count,vwapandrealized_volatilityalongside buy/sell volume.
consecutive trades is attributed to the later trade's window. This means per-window
variances sum to the whole tape's realized variance, and a single-tick window still records
its move away from the previous trade.
metricsrow per(bucket_start_ns, window_ns), idempotent on rerun.Backtest (Python / FastAPI)
_query_metricshelper reads the unifiedmetricstable./metrics/ofikeeps its Phase 1 response contract./metrics/volatility(realized volatility + trade count) and/metrics/volume(buy/sell/total volume + VWAP) endpoints.
Docs
curlexamples for the new endpoints, and design-decisionentries for the unified table, continuous realized volatility and VWAP.
Design decisions
metricstable instead of one table per metric — every metric shares the samewindow key and is produced in one pass, so a wide row is the natural shape.
silently discard boundary moves and understate volatility.
Σ price·sizealready touchedper tick.
Verification
cargo fmt --check,cargo clippy --all-targets -- -D warnings,cargo test— 10/10.ruff check,ruff format --check,pytest— 15/15.total_volume == buy_volume + sell_volume, no negative volatility,ofi ∈ [-1, 1], and VWAPwithin the tape's price range. All three endpoints return
200with the expected columns.Generated by Claude Code