Repository navigation
feat(signals): Kronos forecast and crypto funding/OI, shadow-scored (#144) - #150
Merged
Merged
Conversation
#144) Two new Sources, journaled on every decide and scored before any Bot reads them. - kronos: the symbol's last 400 1h bars go to a Kronos-small sidecar (infra/kronos/, its own GPU container, TRADER_KRONOS_URL); N sampled paths come back un-averaged and the journal keeps share up, median, p10 and p90 at TRADER_SIGNAL_HORIZON_BARS. Weights and model code pinned by revision. The trader decides as usual when the sidecar is down. - crypto_derivatives: BTC/ETH perp funding, open interest and its 24h change, and mark-vs-index basis from Binance/Bybit/OKX via ccxt public endpoints. Fetch-on-tick; reads nothing in replay. - decisions.signals (migration 0019) records every reading, in the prompt or not. A subscription reaches the prompt only with params.in_prompt (off by default); set_signal_prompt on services, API, MCP and CLI flips it as an audited Bot version. Bot #1 subscribes journal-only with TRADER_SHADOW_SIGNALS_ENABLED. - signal_scores: Kronos band coverage and hit rate, funding/OI/basis rank IC against the forward return, bars fetched on use. - Runbook docs/runbooks/shadow-signals.md, glossary, architecture, settings. Claude-Session: https://claude.ai/code/session_01UDNLNu854ULHbHSL59UJKu
kronos and crypto_derivatives slices now carry an availability time: a Kronos forecast is available once the last bar it saw has closed, a live derivatives reading when it is fetched (replay still reads none). Both get a look-ahead case in tests/test_point_in_time.py: Kronos with a bar planted at the step, crypto_derivatives asserting a replay step reads nothing while a live read serves it. Claude-Session: https://claude.ai/code/session_01UDNLNu854ULHbHSL59UJKu
Both sidecars sit side by side in compose; SOURCE_NAMES, build_sources, the prompt lanes and the point-in-time cases keep both sides. Claude-Session: https://claude.ai/code/session_01UDNLNu854ULHbHSL59UJKu
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Two new Sources, both shadow signals: computed and journaled on every decide of a Bot that subscribes, scored against later bars, and kept out of the decide prompt unless a per-Bot toggle is on (off by default).
kronos(src/trader/data/kronos.py,KronosSource): sends the symbol's last 400 1h bars to a Kronos-small sidecar over HTTP. The sidecar runs each path as its own batch row withsample_count=1, so the N sampled paths stay separate instead of being averaged. The trader summarises them as share of paths up, plus median, p10 and p90 returnTRADER_SIGNAL_HORIZON_BARS(24) bars ahead. The model code is pinned by commit and the weights by Hugging Face revision; the trader journals that revision with each forecast.crypto_derivatives(src/trader/data/derivatives.py,CryptoDerivativesSource): BTC and ETH USDT-perp funding rate, open interest and its 24h change, and mark-vs-index basis from Binance, Bybit and OKX through ccxt public endpoints (no keys; ccxt added as a dependency). Fetched on each tick and never stored as market data. A venue that fails drops out of the reading. Replay reads nothing from it, because today's venue numbers are not point-in-time.decisions.signals(migration 0019) holds{source: {version, as_of, in_prompt, reading}}for every reading, in the prompt or not. Replay steps record it too.set_signal_prompt(name, source, in_prompt)on services, API (POST /bots/{name}/signal-prompt), MCP and CLI (trader bot signal NAME kronos --in-prompt). Each flip is a new, audited Bot version. Bot Flip briefs into the decide lane (was EAI-192) #1 is refused: it follows Settings and subscribes journal-only withTRADER_SHADOW_SIGNALS_ENABLED.signal_scores(GET /signals/scores, MCPget_signal_scores,trader signal-scores) scores the journal against bars fetched for that call only:infra/kronos/{Dockerfile,server.py}plus a compose service under thekronosprofile. It hasmem_limit: 2g, a GPU reservation and a port bound to localhost only. Runbook:docs/runbooks/shadow-signals.md.ops/config.py(regenerateddocs/configuration.mdand.env.example), the "Shadow signal" glossary entry, and an architecture note.Acceptance criteria
GET /healthreportspeak_rss_mb. The runbook also says to checkdocker statsandnvidia-smion the unified-memory box. This needs the operator to run it; CI has not run it.kronos_forecastline per call withinference_ms. The trader logskronos_forecastand journalsreading.inference_ms.test_the_toggle_*).test_the_sidecar_down_drops_only_its_reading).How to switch it on
KRONOS_BASE_IMAGE=nvcr.io/nvidia/pytorch:<tag>-py3 docker compose -f infra/docker-compose.yml --profile kronos up -d --build kronos.TRADER_KRONOS_URL(http://kronos:8095orhttp://localhost:8095).TRADER_SHADOW_SIGNALS_ENABLED=truefor Bot Flip briefs into the decide lane (was EAI-192) #1, or subscribe a store-defined Bot tokronos/crypto_derivatives.trader signal-scores --days 14. Only then considertrader bot signal <bot> kronos --in-prompt, through the decide-change gate.With nothing set, this deploys with no change to any prompt or decision.
Tests
tests/test_shadow_signals.py: 22 tests covering the clients (HTTP and ccxt mocked), the Sources (point-in-time Kronos bars), context and journal, the Bot spec and toggle, scoring, and the toggle and scores through every surface. Full suite: 953 tests, ruff clean, config reference--checkclean.Closes #144
https://claude.ai/code/session_01UDNLNu854ULHbHSL59UJKu