Skip to content

fix: tick-rule sign carry, run-bar threshold units, GARCH look-ahead, Roll spread covariance - #71

Closed
quantum-like wants to merge 5 commits into
ml4t:mainfrom
quantum-like:review/fixes
Closed

quantum-like wants to merge 5 commits into
ml4t:mainfrom
quantum-like:review/fixes

Conversation

@quantum-like

Copy link
Copy Markdown
Contributor

Owning issue

Closes #69

Outcome

5 correctness fixes, one commit each, each with a focused test:

  • The effective tick rule stored an unchanged price as 0 before forward-fill, so flat trades (and order-flow imbalance, which reuses it) never carried the previous sign. The previous sign is now carried. Test: tests/features/test_microstructure.py::test_effective_tick_rule_carries_previous_sign. (e7e7622)
  • Volume and dollar run bars initialized the expected-run threshold in value units but updated it with tick counts, so after warm-up bars closed almost every tick. The update now stays in value units. Test: tests/bars/test_run_bars.py::test_volume_run_expectation_does_not_collapse_to_tick_counts, ::test_dollar_run_expectation_stays_in_dollar_units. (d587c6a)
  • The GARCH forecast initialized variance from the next 20 returns (look-ahead) and ignored the current return. It now uses past data only. Test: tests/features/volatility/test_volatility_comprehensive.py::test_forecast_ignores_future_returns. (a20fee6)
  • Roll's spread averaged products demeaned by mismatched trailing means instead of using the window covariance. It now uses the covariance of the current window. Test: tests/features/test_microstructure.py::test_roll_spread_matches_window_covariance. (2833f1e)
  • Follow-up: the registered Roll warm-up is now period + 1 to match the corrected estimator. Test: covered by existing lookback tests. (5b47b7a)

Compatibility

  • No public compatibility impact
  • Compatibility impact is documented in the owning issue and migration guidance

GARCH forecast and Roll spread outputs change numerically, and run bars are larger after warm-up. These are corrections, but downstream results built on them will move.

Verification

  • Tests reproduce the prior failure or verify the requested behavior (each listed test fails on main and passes with its fix)
  • Ruff lint and format checks pass (ruff format --check is clean on the changed files and ruff check reports nothing new in them versus main, but I did not run the full pre-commit suite)
  • ty passes (not run on this branch)
  • Test suite passes: pytest (57 perf tests deselected): 3940 passed before, 3945 passed after.
  • Package build passes when applicable (not run)
  • Strict MkDocs build passes when documentation is affected (no documentation changes)
  • Ecosystem qualification passes (not run)

Documentation and release

No documentation changes. The behavior changes above may be worth a line in the next patch-release notes.

Amir

cursoragent and others added 5 commits October 7, 2026 07:31
Unchanged prices were stored as 0 before forward-fill, so the fill never
replaced them and flat trades were classified as no trade. Zero changes now
keep the previous nonzero tick, including in order-flow imbalance.

Co-authored-by: quantum-like <[email protected]>
The run-bar expectation was initialized as E[T] times average trade value,
then updated with the bar's tick count. After warmup the threshold collapsed
by about the average trade size and later bars closed almost every tick.

Co-authored-by: quantum-like <[email protected]>
The initial variance was the sample variance of the next 20 returns, so a
future shock raised earlier forecasts. The horizon recursion also ignored
the current return. Initialization now uses only the first return, and the
forecast at each row uses information available at that row.

Co-authored-by: quantum-like <[email protected]>
The estimator subtracted each bar's own trailing mean and then averaged
those products, which is not the covariance of the current window. The
spread now uses E[xy] - E[x]E[y] over that window.

Co-authored-by: quantum-like <[email protected]>
The registered warm-up was twice the window because the old estimator
nested two rolling means. The window covariance is first defined one bar
after the lag is available.

Co-authored-by: quantum-like <[email protected]>
@stefan-jansen

Copy link
Copy Markdown
Contributor

The four useful fixes now have focused owning records: tick sign #78/#79, run-bar units #80/#81, GARCH look-ahead #82/#83, and Roll covariance #84/#85. Original contributor commit authorship is retained. The GARCH replacement includes a public-expression regression that fails on the base. Closing this bundle as superseded; the focused PRs still require hosted qualification and independent merges.

@quantum-like

Copy link
Copy Markdown
Contributor Author

Thanks for splitting these into focused PRs and keeping the authorship, and for adding the public-expression regression for the GARCH look-ahead fix. I'll keep an eye on #78-#85 and am glad to answer questions on any of them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Tick rule loses sign on flat trades, run bars collapse after warm-up, GARCH forecast uses future returns, Roll spread not a window covariance

3 participants