Reporting#
Reporting is the read side of the system: everything the dashboard, blotter
and history views show. It lives in one place, services/reporting.py
(ReportingService), separate from the services that write (booking, loading,
P&L, risk).
Principles#
Read persisted results, never recompute. P&L and risk screens read the EOD tables written by the batch (see P&L and the EOD batch and Risk calculations). A report shows what was calculated on that date, independent of later trades or price changes.
Compose across databases at the application layer. There are no cross-database joins; the service reads each database in its own session and combines the results in Python.
One entry point. The web layer calls
ReportingServiceonly for reads, so reads can later be pointed at a read replica without touching the write path.Reports are views, not tables. The blotter in particular has no table of its own; it is a query over
trades.
Reports#
Method |
Content |
Source |
Ordering and size |
|---|---|---|---|
|
Latest P&L (5 rows), latest risk metrics (5), recent breaches (10) |
|
Newest first |
|
Trades joined with instrument |
|
|
|
Daily bars including |
|
|
|
EOD P&L rows |
|
|
|
All limits, recent metrics, recent breaches |
|
Metrics and breaches newest first; 200 by default |
The blotter join#
blotter loads recent trades from the trade database, loads all instruments from
the reference database, and pairs them by symbol into BlotterRow(trade, instrument). A trade whose instrument is missing still appears, with empty
instrument fields. This is the application-layer equivalent of the foreign key
that cannot cross databases (see Database).
Return types and serialization#
The service returns detached ORM objects (sessions use expire_on_commit=False,
so loaded attributes remain readable after the session closes) and small
dataclasses (Dashboard, RiskOverview, BlotterRow). Turning them into JSON is
the web layer’s job (web/serializers.py; see Web layer), so reporting has
no knowledge of HTTP.
Known limitations#
No pagination or filtering. Lists are capped (200) and ordered newest first. Date, symbol, book and asset-class filters are the natural next addition.
Not a single snapshot. Each report reads its databases in separate transactions, so the dashboard can show P&L from one EOD run next to risk from another if a batch runs in between.
Simulated data is labelled on prices only.
pricesexposesdata_origin; P&L and risk rows do not yet (see Simulated data: why and how).Per-currency amounts. Reports show P&L in each instrument’s currency with no aggregation across currencies.
No charts or HTML. Output is JSON; see Web layer.