Metadata-Version: 2.4
Name: jgtpricedb
Version: 0.1.1
Summary: Database-backed incremental price store for the JGT trading platform (PDSP heir)
Requires-Python: >=3.10
Requires-Dist: pandas>=1.5
Requires-Dist: sqlalchemy>=2.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == 'dev'
Provides-Extra: postgres
Requires-Dist: psycopg[binary]>=3.1; extra == 'postgres'
Description-Content-Type: text/markdown

# 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

- **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`..`H1` stay on UTC, where they measurably
  already were. The session is stated per market, resolved inside `bar_key`, and
  recorded on the series; `tests/test_session_grid.py` is the measurement, run
  against the real holdings. See `rispecs/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. `CsvSource` reads the
  existing `full/` CSVs through the exact same upsert path as `BrokerSource`
  live updates. The system can always rebuild itself from its own sources.
- **CSV compatibility export** (PDSP spec 75 pattern): consumers (`jgtpy`,
  `jgtml`, `jgt-data-server`) keep reading the same file paths while the
  database becomes authoritative underneath. Nothing breaks on day one.
- **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.toml` with a **static version** — deliberately avoiding the
  `setup.py` circular-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 | Refresh CLI (`jgtpdscli`) replacing `refresh_data.sh` | 72, 74 |
| 3 | CSV export bridge — DB authoritative, downstream untouched | 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 library
- `docker-compose.yml` — optional Postgres for deployment; SQLite needs nothing
