Skip to content

fix: zero turnover limit, CAE/SAE minibatch edge cases, attention with no neighbors or long lag - #56

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

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

Conversation

@quantum-like

Copy link
Copy Markdown

Owning issue

Closes #55

Outcome

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

  • A turnover limit of 0 liquidated the previous book. Zero now holds the previous weights; negative or non-finite limits raise. Test: tests/test_financial_correctness.py::test_zero_turnover_limit_holds_the_previous_book, ::test_negative_turnover_limit_is_rejected. (2a32358)
  • CAE reported converged=True when hidden units were set and every minibatch had one row, so no step ran and the random initialization was returned. It now raises. The existing skip of a trailing singleton minibatch is unchanged. Test: tests/test_cae.py::test_cae_rejects_fits_that_never_update_parameters. (b0d261a)
  • SAE could yield a one-row final minibatch, which crashed BatchNorm mid-fit. That tail is folded into the previous batch, and a sample with fewer than two observations is rejected. Test: tests/test_sae.py::test_sae_trains_when_the_last_minibatch_would_be_a_single_row, ::test_sae_rejects_a_single_training_row. (95557c0)
  • Graph attention produced NaN outputs and gradients for a node with no available neighbor. It now falls back to self-attention. Test: tests/test_financial_correctness.py::test_graph_attention_stays_finite_when_a_node_has_no_neighbors, ::test_graph_attention_ignores_a_masked_only_neighbor. (7312029)
  • Cross-sectional attention wrapped the slice when the lag exceeded the window. It now uses an all-pad key sequence. Test: tests/test_financial_correctness.py::test_cross_attention_lag_longer_than_the_window_does_not_wrap. (077948a)

Compatibility

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

A turnover limit of 0 now means "hold" rather than "liquidate", and invalid limits raise. Other changes affect only edge cases that previously crashed or produced NaN.

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
  • ty passes
  • Test suite passes: pytest tests/: 422 passed before, 431 passed after. ruff and ty were clean in the review environment.
  • 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:30
A non-positive turnover cap replaced the target book with zeros, which
liquidates an existing portfolio instead of forbidding trades. A zero cap
now scales weight changes to the previous holdings, and a negative cap is
rejected.

Co-authored-by: quantum-like <quantum-like@users.noreply.github.com>
Hidden beta networks skip one-row minibatches because BatchNorm cannot
train on them. When every batch was a single row, fit still returned a
converged model whose weights were the random initialization. That fit
now fails instead of emitting an untrained beta surface.

Co-authored-by: quantum-like <quantum-like@users.noreply.github.com>
A configured batch size that left a one-row tail, or a single valid
training row, crashed inside BatchNorm during training. Singleton tails
are folded into the previous batch, and a one-row sample now raises a
clear error before any update.

Co-authored-by: quantum-like <quantum-like@users.noreply.github.com>
A fully blocked adjacency row, or a node whose only neighbors are missing,
produced NaN attention and NaN portfolio weights. Those queries now attend
to themselves when present, and otherwise use a finite fallback.

Co-authored-by: quantum-like <quantum-like@users.noreply.github.com>
When the lag exceeded the window length, the history slice used a
negative stop and either crashed or read the end of the same window.
Lags that reach past the start of the window now see an empty history.

Co-authored-by: quantum-like <quantum-like@users.noreply.github.com>

This branch has not been deployed

No deployments
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]: Zero turnover limit liquidates, CAE reports convergence without training, SAE BatchNorm crash on one-row batch, attention NaN/wrap edge cases

2 participants