Commit Graph

171 Commits

Author SHA1 Message Date
jgrusewski
2ca1e9541b fix(ci): enable workflow-level archiveLogs for cockpit builds
spec.archiveLogs:false was the real kill-switch — it disabled archival for the whole workflow regardless
of the per-template MinIO-reachability fix. Flip to true so logs actually land in the argo-logs bucket.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 21:59:18 +02:00
jgrusewski
2379b465b7 fix(ci): label cockpit workflow pods part-of=argo-workflows so MinIO ingress admits them → logs ARE archived
Root cause of months-long missing CI logs: MinIO's ingress netpol allows part-of in {foxhunt,foxhunt-ci,
argo-workflows}; the cockpit build/deploy pods carried neither label → MinIO denied the wait-sidecar's
log upload (i/o timeout) → builds errored. Using 'argo-workflows' (not 'foxhunt') admits them to MinIO
WITHOUT triggering argo-base-egress (which would block registry:5000/git:2222). Reverts the earlier
archiveLogs-disable approach — logs are now SAVED, not skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 21:54:52 +02:00
jgrusewski
07cd72533e fix(orchestration): schedule default_status=RUNNING (auto-arm on fresh deploy) + Argo archiveLogs=false per-template (build no longer fails on unreachable MinIO log-sink)
Both latent bugs: a recreated Dagster instance would silently not arm the nightly schedule; and the
Argo build marked Error on the MinIO log-sink (masking real failures + skipping the auto-deploy step).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 21:23:22 +02:00
jgrusewski
10b6bfb6da merge: warehouse bulk ingest (one-transaction, ~50x faster)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 19:20:30 +02:00
jgrusewski
5000333aeb perf(warehouse): bulk ingest in one transaction (~50x faster crypto ingest on PVC)
write_features_bulk writes many symbols in a single transaction (one fsync/checkpoint vs one per
symbol); ingest_crypto_pit collects all 155 symbols then one bulk call. Equivalence test proves
identical result. Targets the ~52min nightly crypto ingest in the Dagster combined-book run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 19:20:30 +02:00
jgrusewski
c7b71616e3 merge: lifecycle B0 — Dagster orchestration of the combined-book forward track (deployed + cut over)
CombinedBookSource port (Warehouse/Raw + A->B equivalence), warehouse read_panel, 4 Dagster assets
(fetch+ingest crypto/futures -> warehouse SSOT -> combined-book NAV -> cockpit), Definitions + daily
schedule, cluster deploy (one-pod webserver+daemon+tailscale, pg storage). Cron suspended; reversible.
Follow-up: batch the ~52min warehouse ingest. 297 tests, mypy-strict clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 18:00:05 +02:00
jgrusewski
d939f9b33f fix(orchestration): assets fetch fresh data before ingest (crypto daily, futures Sunday) — track advances
The B0 assets only ingested existing files → forward track froze on stale data. Mirror the retired
cron: crypto_bars fetches crypto_pit (Binance, free, daily, best-effort); futures_bars fetches via
Databento on Sundays (cost-capped, key-gated) before the silver→warehouse ingest.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 16:52:25 +02:00
jgrusewski
f628d78cbb fix(orchestration): serialize futures_bars after crypto_bars (DuckDB single-writer lock)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 15:15:48 +02:00
jgrusewski
bf2029868b deploy(orchestration): Dagster manifest (single-pod webserver+daemon+tailscale, pg storage) + Argo deploy + Dockerfile extra
Task 10 repo prep: one-pod Dagster (RWO surfer PVC shared by webserver+daemon), tailnet-private UI,
storage in cockpit Postgres `dagster` DB, FXHNT_COMBINED_BOOK_DATA_SOURCE=warehouse. Argo build-deploy
extended to apply+roll dagster. Cron suspend = deliberate post-verify cutover step (RWO-forced).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 12:47:38 +02:00
jgrusewski
8efb78ab15 style(orchestration): drop dead type-ignore comments on @asset (strict-mypy clean)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 11:58:12 +02:00
jgrusewski
f4cfec0f73 feat(orchestration): Definitions + daily combined-book schedule
Wire the 4 B0 assets into combined_book_forward_job and a
ScheduleDefinition (cron 30 23 * * *, UTC) via a Dagster Definitions
object; dagster definitions validate passes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 11:51:55 +02:00
jgrusewski
c0a4932de9 feat(orchestration): B0 Dagster assets (crypto/futures bars -> nav -> cockpit) + forward_ingest extract
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 11:40:39 +02:00
jgrusewski
2d7d7470fd build(orchestration): add dagster optional-dependency extra
Pins adjusted from >=1.8,<1.9 to >=1.12,<1.13 (dagster-webserver matching)
and >=0.28,<0.29 (dagster-postgres) — the 1.8.x/1.9.x/1.10.x lines cap at
Python <3.13 and the 1.11.x line caps at <=3.13.3; 1.12.x is the nearest line
that supports Python 3.13.6 (the venv runtime).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 11:30:55 +02:00
jgrusewski
5a75effd8d feat(combined-book): FXHNT_COMBINED_BOOK_DATA_SOURCE flag + source factory; wire CLI
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 11:27:24 +02:00
jgrusewski
c3c90881e0 refactor(combined-book): read via injected CombinedBookSource (default RawFileSource)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 11:24:19 +02:00
jgrusewski
c66bffabef feat(combined-book): WarehouseSource reads SSOT; equivalence test proves A->B faithful
- Extend FeatureStore protocol with catalog() and read_panel() so WarehouseSource
  can be typed against the port (mypy strict clean)
- Add silver_ingest_helpers.ingest_crypto_pit — shared bronze→silver→warehouse
  write path for assets and tests
- Implement WarehouseSource in combined_book_source.py; delegates crypto panel
  to read_panel+_panel and futures to WarehousePriceProvider
- Add equivalence test: warehouse-fed panel == raw-file-fed panel (A→B gate)
- 291 tests pass, 0 regressions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 11:16:25 +02:00
jgrusewski
9ecb24f82c feat(combined-book): CombinedBookSource port + RawFileSource (existing path) 2026-06-15 11:13:21 +02:00
jgrusewski
7a33082020 feat(warehouse): read_panel — per-symbol epoch-day matrix for one feature
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 11:11:57 +02:00
jgrusewski
461b89eba6 refactor(crypto): extract _panel builder (shared by raw + warehouse sources)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 11:10:13 +02:00
jgrusewski
83a6ce57dd plan(lifecycle): bite-sized B0 plan — Dagster foundation + combined-book via warehouse
10 tasks: _panel extract, warehouse read_panel, CombinedBookSource port (Raw/Warehouse,
equivalence test = A->B guarantee), CombinedBook source-injection, config flag+factory,
dagster extra, 4 assets, Definitions+schedule, cluster deploy (webserver+daemon+pg+tailnet)
+ suspend the fxhnt-forward cron. Reversible cutover via FXHNT_COMBINED_BOOK_DATA_SOURCE.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 10:57:18 +02:00
jgrusewski
9878207ecd docs(lifecycle): design spec — B0 Dagster foundation + combined-book via warehouse
Sub-project B increment 0: stand up Dagster on the cluster + migrate the combined-book
paper-forward track end-to-end as an asset graph reading the warehouse SSOT (proves A->B),
replacing the fxhnt-forward cron. CombinedBookSource port (Warehouse/Raw), 4 assets,
cockpit ingest, reversible cutover. B1-B4 (other tracks, gauntlet, promote/live) deferred.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 10:40:42 +02:00
jgrusewski
ddaf755594 merge: unified data layer increment 1 (warehouse-SSOT)
Daily bars (futures continuous-front + crypto close-only) flow bronze->silver->gold
into the point-in-time warehouse; WarehousePriceProvider reads them back via the
DataProvider port (--data-source warehouse, reversible); catalog/freshness view.
285 tests, mypy-strict clean on all new files. Polygon (incr 2) + news (incr 3) deferred.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 00:49:11 +02:00
jgrusewski
58d73960cd docs(cli): document warehouse as a --data-source option
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 00:47:45 +02:00
jgrusewski
f1e58c3d31 fix(cli): validate warehouse-ingest args before opening store; try/finally close (no DuckDB leak)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:44:21 +02:00
jgrusewski
c76bae9d05 feat(cli): warehouse-ingest + warehouse-catalog commands; warehouse data source
Adds the `warehouse` branch to `_data_provider` (the cutover seam for
hunt/run --data-source warehouse), plus two new commands: `warehouse-ingest`
(bronze→silver→gold for futures and crypto) and `warehouse-catalog`
(per-symbol inventory/freshness view of the SSOT).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 00:38:17 +02:00
jgrusewski
6089139857 fix(warehouse): type read_features params list[str|int] (strict mypy)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 00:35:43 +02:00
jgrusewski
6f9fb9a9f6 feat(warehouse): catalog/freshness inventory (store.catalog + format_catalog)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 00:34:55 +02:00
jgrusewski
c203df8d09 fix(warehouse): ingest_bars rejects symbol mismatch (prevent mislabeled bars)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 00:32:42 +02:00
jgrusewski
ecb9fba115 feat(warehouse): WarehousePriceProvider reads bars as PriceSeries (DataProvider)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 00:28:40 +02:00
jgrusewski
11fda08fc8 feat(warehouse): WarehouseIngest gold-write service (idempotent) 2026-06-15 00:26:44 +02:00
jgrusewski
fec4a78a83 feat(warehouse): silver_crypto normalizer (close-only daily bars) 2026-06-15 00:25:36 +02:00
jgrusewski
47603755a1 feat(warehouse): silver_futures normalizer (reuses continuous_front_adjust)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 00:24:41 +02:00
jgrusewski
bd0f6d78fb refactor(dbn_local): extract continuous_front_adjust + read_front_arrays for reuse
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 00:23:05 +02:00
jgrusewski
ec8b05bfaa feat(warehouse): BarRecord canonical daily-bar value object 2026-06-15 00:20:48 +02:00
jgrusewski
fd1310fc46 feat(config): add warehouse_path setting 2026-06-15 00:19:29 +02:00
jgrusewski
7c5b1bd3e5 plan(data): bite-sized implementation plan — unified data layer / warehouse-SSOT
9 TDD tasks: config warehouse_path, BarRecord, factor dbn_local (shared adjust),
silver_futures/silver_crypto normalizers, WarehouseIngest, WarehousePriceProvider,
catalog, CLI (warehouse-ingest/catalog + warehouse data source). Increment-1 bars {close,high,low}.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 00:15:32 +02:00
jgrusewski
30c82f2a01 docs(data): design spec — unified data layer / warehouse-SSOT (platform sub-project A)
Increment 1: daily bars (futures+crypto) bronze->silver->gold into the existing
point-in-time FeatureStore, consumed via the DataProvider port (WarehousePriceProvider),
plus a catalog/freshness view. Funding + retiring the other data homes are later increments.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 00:09:12 +02:00
jgrusewski
c857fbfd95 merge: single-market kinds (seasonality/breakout/vol_managed_momentum) + OHLC contract
Sub-project A: grows available() 3->6 with three structurally-distinct single-market
kinds, and extends PriceSeries with high/low filled by all 4 adapters (databento/
yahoo/dbn_local/duckdb migration) for a true Donchian. 269 tests, mypy-strict clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 23:51:37 +02:00
jgrusewski
d0e9772dd7 feat(duckdb): migrate + round-trip high/low (COALESCE fallback to close)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 23:40:56 +02:00
jgrusewski
fd81f1b6c6 feat(dbn_local): ratio-adjusted synthetic high/low via pure _front_to_series helper
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 23:35:59 +02:00
jgrusewski
5651a503aa feat(yahoo): adjustment-scaled high/low via pure _build_series helper
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 23:28:33 +02:00
jgrusewski
cd9dc4a504 refactor(databento): TYPE_CHECKING pandas annotation + column-absent fallback test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 23:26:47 +02:00
jgrusewski
63b78da87f feat(databento): fill NaN-guarded high/low via pure _df_to_series helper
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 23:23:53 +02:00
jgrusewski
c174c74ad7 feat(strategies): register breakout/seasonality/vol_managed_momentum (3->6 kinds)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 23:21:08 +02:00
jgrusewski
1b83390e26 feat(strategies): vol_managed_momentum kind (Moreira-Muir, de-risk only)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 23:18:09 +02:00
jgrusewski
45fab8c1a9 feat(strategies): seasonality kind; move seasonal_signal to domain (DRY, no shift)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 23:14:32 +02:00
jgrusewski
10f63192b2 feat(strategies): breakout kind (true Donchian channel)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 23:09:15 +02:00
jgrusewski
543e4c9f43 feat(strategies): causal rolling_max/rolling_min helpers 2026-06-14 23:06:33 +02:00
jgrusewski
90c25d70b1 fix(models): PriceSeries high/low — copy-on-default (immutability) + strict-mypy field type + test gaps
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 23:05:03 +02:00
jgrusewski
7262238193 feat(models): PriceSeries gains high/low fields defaulting to close 2026-06-14 22:59:51 +02:00