Skip to content

QT desk: the risk check and the approve gate (C9, desk.proto 1.3.0) - #133

Merged
dominickdupuy merged 2 commits into
mainfrom
qt/desk-risk-check
Oct 14, 2026
Merged

dominickdupuy merged 2 commits into
mainfrom
qt/desk-risk-check

Conversation

@dominickdupuy

Copy link
Copy Markdown
Member

Implements the AlgoLens side of contract C9 (trade-ngin PR #204, commit 7ec6076e, desk.proto 1.3.0 GetDeskRisk).

Vendoring

  • proto/algogators/desk.proto 1.3.0, byte-identical to trade-ngin@7ec6076e; SOURCE updated; stubs regenerated with grpcio-tools 1.84.0; versions.py says desk=1.3.0.

API

  • DeskAgentPort.get_desk_risk / DeskClient.get_desk_risk: a read, not a command. Returns the report as a camelCase dict (state no_book|model|desk|override, auditId, withinLimits, approvedOverride, breaches, m, bindingTerm, overLimitAfterRounding, overLimitByHold, refused, symbols, grossLeverage/netLeverage/marginCushion/equityToMargin (None when unset, via HasField), limits) or raises DeskRiskUnavailable(<status name>).

  • GetDeskState and LookupApproval carry risk: the report, {"unavailable": reason}, or null before the first book. Both now take the agent.

  • Approve gate in PublishDesk, before the row and the engine call. 409 when:

    • a save is still pending or running;
    • the check can't be read (fail closed);
    • state desk and the report's auditId is not the latest done save;
    • state desk, not within limits, no approved override.

    The model book, no book and an approved override pass. A published day is left to the existing C3 refusal. The fallback/system publish paths and the engine are unchanged.

Frontend

  • domain/qt/desk.ts: DeskRisk types, riskBreachReason (part of approveBlockedReason, after the lock and cutoff checks), and pure helpers for the report (badge, binding line, limits vs readings, moved symbols), with unit tests.
  • New components/qt/RiskReport.tsx (theme-aware), rendered under Asked-vs-given on the desk panel and on the approval page.
  • On a breach, the desk panel shows a prompt next to the disabled Approve. It opens the existing override request form.

Tests

  • Use cases: the gate's cases and the risk carried in state and on the approval page.
  • Desk client: an in-process server, the version header, field mapping, HasField nulls, errors.
  • Routes: the 409 body.
  • Integration: NullAgent reports the model book. The rescind test now finishes its save before re-approving and checks that a running save blocks approval.
  • Locally, the API suite with Postgres 16 (561 passed), vitest (150 passed) and the vite build all pass.

Vendor desk.proto 1.3.0 from trade-ngin 7ec6076e (GetDeskRisk) and
regenerate the stubs (grpcio-tools 1.84.0); versions.py says desk=1.3.0.

API: DeskClient.get_desk_risk returns the engine's risk report of the day's
qt book as a camelCase dict (unset optional readings are None) or raises
DeskRiskUnavailable. The desk state and the override approval page carry it
as "risk" ({"unavailable": reason} when the call fails, None before the
first book). PublishDesk refuses (409), before it writes a row or calls the
engine, while a save is still running, while the check cannot be read (fail
closed), while the report is of an older save than the latest done one, and
while the desk's positions breach a risk limit without an approved override.
The model's book, no book and an approved override pass; the fallback
publish and the engine are unchanged.

Frontend: RiskReport shows the badge, the limit that bound, the breaches, the
configured limits against the stored book and the moved symbols (risk vs
trading rule). Approve is closed by riskBreachReason; on a breach the desk
panel points to the existing override request form. The approval page shows
the report too.
Each setting was a card (label, running line, input) in a two-column grid, a
long wall for a strategy's config. Now each section is a collapsible table of
rows (setting, running, pending, new value), opened when it holds pending or
edited values or matches the filter; a filter box narrows by dotted path; a
version's raw changes fold away in the history.
@dominickdupuy
dominickdupuy merged commit efbc163 into main Oct 14, 2026
6 checks passed
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.

1 participant