jgt-pricedb
The persistence layer of the next-generation Price Service: bars live in a database with an incremental, anchor-based refresh — CSV files become an export, not the source of truth.
Lineage: implementation of the PDSP specifications reverse-engineered from
the Caishen .NET stack — caishen/rispecs/PDSP/ (specs 70–77) — translated
into the jgt ecosystem's shapes.
Structural Tension
- Current reality: price data as flat CSVs (
$JGTPY_DATA/pds/<INSTR>_<TF>.csv); every refresh rewrites whole files and downstream recomputes whole series. - Desired state: a database-backed store where refresh finds the anchor (the single forming bar per series) and writes only forward; downstream learns which bar changed and computes incrementally.
Decisions
Production ownership (2026-09-04)
The projection contract is in production: jgtpdb derive-cds
(jgtpricedb-util 0.2.0) materializes indicator-complete CDS from a PDS
export, and the jgt-data-server updater builds its rolling CDS through the same
materialize_cds seam. The Williams engine (jgtpy) is a dependency of that
job alone; no chart service imports it.
PDS (today: written by the updater's broker fetch, jgtfxcon)
-> jgtpdb derive-cds / materialize_cds -> indicator-complete CDS -> chart
What is not yet true: the store is not the production PDS writer. The
updater's fetch still writes current/pds; jgtpricedb export becomes that
source at the cutover gated by the shadow REFEREE log (handoff 014). One
writer at a time. Phase 5 (database-native derived tables) is still future.
The chart reads CDS rows for indicators and falls back to PDS prices only where
no CDS covers a timestamp, drawing those bars without AO rather than skipping
time.
- Periods are cut on the broker's trading session, not on UTC midnight
(0.1.1). The feed publishes H4, D1, W1 and M1 bars on a 17:00
America/New_York boundary — 21:00Z in summer, 22:00Z in winter — so a UTC grid
renamed 100% of them, silently.
m1..H1stay on UTC, where they measurably already were. The session is stated per market, resolved insidebar_key, and recorded on the series;tests/test_session_grid.pyis the measurement, run against the real holdings. Seerispecs/01-price-store.spec.md, The Session Grid. - Portable schema (SQLite for local-first dev, PostgreSQL for deployment);
the anchor invariant is enforced by a partial unique index
(
UNIQUE(series_id) WHERE is_forming), not by application discipline. - No standalone importer. Backfill is the refresh engine's bootstrap path
(PDSP spec 72, Algorithm C) fed by a source adapter.
CsvSourcereads the existingfull/CSVs through the exact same upsert path asBrokerSourcelive updates. The system can always rebuild itself from its own sources. - CSV compatibility export (PDSP spec 75 pattern, 0.1.2): consumers
(
jgtpy,jgtml,jgt-data-server) keep reading the same file paths while the database becomes authoritative underneath. The format is measured rather than assumed — quotes keep the double the feed published, the derived columns are quantized at display precision +1 and +2 (with builtinround, which is not the one pandas reaches for), and the line terminator belongs to the file being replaced. A holdings file read in and written back out is byte-for-byte itself: 89 of 89 live files, 13 instruments, all seven timeframes, 95 208 bars. Seerispecs/03-csv-export.spec.md. - Redis pub/sub (already in the jgt-data-server stack) carries bar-completed events in Phase 4 — the role Rebus/MSMQ played in Caishen.
pyproject.tomlwith a static version — deliberately avoiding thesetup.pycircular-import pattern that blocks other jgt packages from installing in containers.
Phases
| Phase | Creates | PDSP spec |
|---|---|---|
| 1 | Schema + store core + bootstrap-backfill through source adapters | 70, 71, 72 |
| 2 | Jobs (jgtpdb) replacing refresh_data.sh — shipped as jgtpricedb-util |
72, 74 |
| 3 | CSV export bridge — DB authoritative, downstream untouched (0.1.2) | 75 |
| 4 | Redis events → incremental IDS/CDS recompute | 73, 77 |
| 5 | Serving from DB; indicator tables; strategy layer (SpiderDb heir) | 76 |
Layout
rispecs/— jgt-native specifications (the buildable truth; start here)src/jgtpricedb/— the librarydocker-compose.yml— optional Postgres for deployment; SQLite needs nothing../jgt-pricedb-util/— the sibling package (jgtpricedb-util): the jobs an operator runs against a store — bootstrap, refresh, a bounded forming-bar loop, an OANDA fetch on this session grid, and the freshness and relabel probes. This repository is the store; that one is the steward.
Release files for jgtpricedb 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jgtpricedb-0.2.0.tar.gz | 130.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jgtpricedb-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 182.6 kB
Release files / jgtpricedb-0.2.0.tar.gz
| Download URL | jgtpricedb-0.2.0.tar.gz |
|---|---|
| Size | 130.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3abcfb8ea614e7b1c53e9424893e4fdff274d156ddaf70416b8094678e14c728
|
|
BLAKE2b-256 checksum How to use checksums |
1f6e8b7f666986a4b693cb32dd56d0cb1cb548ef960d3404abe413f8f80f4a22
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.4
|
Release files / jgtpricedb-0.2.0-py3-none-any.whl
| Download URL | jgtpricedb-0.2.0-py3-none-any.whl |
|---|---|
| Size | 52.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b328d77ea8de42df9d5cf5e945aee2a861a7bec159fe7af067fd7c402ce8d5e8
|
|
BLAKE2b-256 checksum How to use checksums |
f596d2d36cce33448c34ab364f88e4740b26e818200724ac5e95f4ac577ca350
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.4
|