Skip to main content

Data Model: YU06; EOD Price Production + Overnight Batch Chain

All new tables live in the real runtime schema; the k8s database-init ConfigMap (kubernetes-runtime/manifests/base/database-init-configmap.yaml), not the dead database/initialSchema.sql (see research.md gotcha). MariaDB, lowercase identifiers.

eod_price_session (header; one row per produced version)​

ColumnTypeNotes
session_dateDATEThe trading session being closed.
versionINT1-based; incremented per re-production/override for the same date.
statusVARCHAR(16)DRAFT (produced, not yet gated) β†’ PUBLISHED (gated, event emitted). Immutable once PUBLISHED.
instrument_countINTInstruments priced in this version.
flagged_countINTUnresolved STALE/SPIKE/MISSING in this version (must be 0 to publish).
created_atDATETIMEProduction wall-clock (audit only, not a consistency key).
published_atDATETIME, nullableSet when status β†’ PUBLISHED.

PK (session_date, version). A published version's rows are never updated; a correction writes a new (session_date, version+1).

eod_price_snapshot (the versioned closing prices; immutable)​

ColumnTypeNotes
session_dateDATEFK part β†’ eod_price_session.
versionINTFK part β†’ eod_price_session.
securityVARCHAR(16)Ticker.
closing_priceDECIMAL(18,6), nullableLast trade price at close; null iff quality = MISSING and not overridden.
qualityVARCHAR(16)OK / STALE / SPIKE / MISSING / OVERRIDDEN.
source_tick_millisBIGINT, nullableEvent-time of the sample the price came from (staleness evidence).
override_reasonVARCHAR(255), nullableSet only for OVERRIDDEN.

PK (session_date, version, security). This is the single source of truth every downstream job reads; keyed by the exact (session_date, version) the gate event names.

Quality classification (computed at production time against eod.quality.* config):

QualityMeaning
OKFresh sample, move within bounds.
STALENewest sample older than eod.quality.staleness-seconds before session close.
SPIKE`
MISSINGInstrument in the expected universe with no sample at all (closing_price null).
OVERRIDDENAn operator supplied a corrected price for a previously flagged instrument (new version).

The expected universe for MISSING detection is eod.universe (config; default = every ticker PriceHistoryStore has observed this session). An instrument in the config list with no sample is MISSING; the fail-safe blocks publication until it is overridden or removed.

eod_position_pnl (consumer output; immutable, position-service)​

Written by the position-service EOD consumer when it processes an EOD_PRICES_READY event.

ColumnTypeNotes
session_dateDATEFrom the event.
versionINTFrom the event; ties the mark to the exact price version used.
account_idINTAccount marked.
securityVARCHAR(16)Held security.
quantityINTPosition quantity at mark time.
closing_priceDECIMAL(18,6)The (session_date, version, security) snapshot price used.
market_valueDECIMAL(20,6)quantity Γ— closing_price.
marked_atDATETIMEConsumer wall-clock (SLA evidence).

PK (session_date, version, account_id, security). Immutable/idempotent: reprocessing the same event (durable redelivery) is a no-op via INSERT ... ON DUPLICATE KEY UPDATE-guarded upsert with identical values, so at-least-once delivery is safe. An account with any halted (missing/flagged) holding writes no rows for that account (fail-safe) and is counted in eod_pnl_halted_total.

Events (NATS JetStream, durable; stream TRADERX_EOD, file storage)​

eod.prices.ready (EOD_PRICES_READY); producer β†’ consumers​

{ "sessionDate": "2026-07-08", "version": 3, "instrumentCount": 42,
"publishedAtMillis": 1751990400000 }

Published by trade-processor after the snapshot rows for (sessionDate, version) are committed and status is PUBLISHED. Durable so a consumer that boots after publish still receives it.

{ "sessionDate": "2026-07-08", "version": 3, "accountsMarked": 17,
"accountsHalted": 1, "completedAtMillis": 1751990460000 }

Emitted when the consumer finishes a session. This is the next link the teammate's VaR batch or YU05 NAV can subscribe to (not consumed within this state).

Config (namespace eod.*)​

KeyDefaultWhereMeaning
eod.quality.staleness-seconds300trade-processorSample-age threshold for STALE.
eod.quality.max-move-pct20trade-processorAbs % move vs. prior close for SPIKE.
eod.universe(empty = all seen)trade-processorExpected instrument list for MISSING detection.
eod.session.auto-publishtruetrade-processorAuto-publish on close when zero flags.
eod.streamTRADERX_EODbothJetStream stream name.
eod.subject.prices-readyeod.prices.readybothGate-event subject.
eod.subject.pnl-doneeod.pnl.doneposition-serviceChain-link subject.
eod.consumer.durableeod-pnlposition-serviceDurable consumer name.

Reused, unchanged​

  • PriceHistoryStore (trade-processor, YU05); per-ticker bounded time-ordered (price, timestampMillis) samples; the closing price is its newest sample per ticker. Read-only reuse.
  • JwtAuthenticator / AuthController (trade-processor, YU05); admin gate for all EOD endpoints.
  • JetStreamControlFeedPublisher pattern (account-service, YU04); the durable-publish blueprint.
  • Position / PositionRepository (position-service); the positions to mark.