Skip to content

The orders table has no surface — the console never shows what keel actually bought or sold #659

Description

@eaitbrahim

Repository.get_orders() exists (keel/data/repository.py:302). Nothing in the console calls it. No web payload reads the orders table at all; the only two modules that touch it are doctor (partial-fill findings) and research (the pooled review).

So there is no surface anywhere that answers "what did keel actually buy and sell, and at what price."

What the console shows instead, and why neither is this

view shows
Status → Open positions what is held right now — 2 BTC dca tranches on the live book
Activity cycles and events parsed from the log file (commands/activity.pyresolve_log_path / read_log_window)

Activity is a cycle viewer, not a transaction record. It reads the log, so a cycle that did not log, or a rotated log, shows nothing. Neither view ever reads orders.

Why this is more than a missing convenience

keel's pitch is auditability, and orders is the audit trail. Per row it holds:

  • side, product_id, qty, status, order_type, limit_price
  • expected_fill vs actual_fill — what the engine sized against vs what the venue gave
  • fee — the number the whole cost argument rests on. The three live fills are the only direct evidence that taker_pct: 0.012 is right (measured 1.1838% effective), and keel stores nothing that measures spread, and at this deployment's clip size spread IS the cost #626 is filed because spread is the term nothing records
  • confirmationautonomous or a human's approval. "Did I approve this, or did keel place it on its own?" is the single most important question about an order on a deployment with autonomy: ON, and it is answerable nowhere in the UI
  • raw_response — the venue's own JSON, including the real order id
  • rule_id — which rule caused it

Reading any of that currently means opening SQLite by hand. On the live book that is 4 rows; on the paper book, 14.

This is the same shape as #639, #640, #641 and #642: keel knows, and does not say.

Scope

A payload over get_orders() and one console view. Specifically:

  • confirmation is displayed prominently, not as a trailing column. autonomous on a live BUY is the row an operator most needs to find.
  • expected_fill vs actual_fill side by side, with the divergence visible. That difference is realised slippage — the quantity keel stores nothing that measures spread, and at this deployment's clip size spread IS the cost #626 wants and the reason _record_observed_fill_quantity exists.
  • fee shown as paid, not as a percentage the layer computes. A derived rate here would be the presentation layer doing arithmetic it must not do (test_console_thinness.py); if a rate is wanted, a service computes it.
  • Newest first. get_orders returns oldest-first by id; the view wants the opposite, and reversing in the service — not in the renderer — keeps the thinness pin honest.
  • Scoped like Activity is, so the view does not grow unbounded on a long-running book.

raw_response must not be rendered raw. It is venue JSON of unbounded size and it is the one field that could carry something unexpected into the page. Surface the venue order id if anything.

Constraints

  • keel/web/*.py is scanned by tests/commands/test_console_thinness.py — no compute in the presentation layer, Decimal arithmetic is display-only, no broker construction. The service does the work; the payload places values.
  • The view is read-only and must add no route reachable from tests/web/test_server.py's disjointness pin, and no keel/capabilities.py row.
  • Money renders through the existing money() helper — strings, presentation-ready, no float.
  • Both surfaces where it makes sense: a keel orders-style terminal listing and the web view should not disagree, the way status.py and payload.py are kept in step for the bracket column (Paper positions render an unactionable 'NO bracket' warning — the state paper can never leave #641).

Acceptance

  • A console view lists orders from get_orders(), newest first, scoped.
  • confirmation, expected_fill, actual_fill and fee are all visible on a row.
  • raw_response is never rendered wholesale.
  • The thinness pin and the disjointness pin both stay green; no capabilities row is added.
  • Mutation-verified pins, per this repo's habit.

Notes

Found by reading the live console and asking where the transactions were. Related: #626 (spread is the unmeasured cost term these rows would evidence), #641 (the same two renderers kept in step), #639/#640/#642 (the same silence).

Activity

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

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions