Authoritative current-state snapshot of crypto-shortterm as of 2026-06-26, mirroring the repo HANDOVER.md (/Users/levander/coding/pmv2/crypto_algo/HANDOVER.md). Supersedes the prior Phase-1 narrative: the producer is LIVE, dry-validate PASSED end-to-end, the VM moved Frankfurt→Zurich to clear a Polymarket geolock, and the architecture is now v2 / Pattern B (wowjeeez/pmv2-crypto-algo).
For Agents
Single source of truth = the repo doc
/Users/levander/coding/pmv2/crypto_algo/HANDOVER.md. This note mirrors it. Major narrative deltas vs the older notes: (1) emit is live and dry-validated end-to-end (not “blocked, fired 0×”); (2) the autotrade “didn’t work” because of a geolock, NOT latency — so the ~128ms latency-capturability question is STILL UNTESTED; (3) v2 architecture = producer-only, repo renamed, executor is @positionmanager on streamPMV2_ORDERS, subjectpmv2.order.crypto_shortterm_latency_test.entry; (4) v1 is UP-only by design.
What this is
Rust producer trading BTC on Polymarket 5-min Up/Down markets via a fair-value (oracle-lag) model. Repo wowjeeez/pmv2-crypto-algo at /Users/levander/coding/pmv2/crypto_algo. babylon handle crypto. Isolated Supabase schema crypto_shortterm (NEVER touch pmv2 public/pm_*). Runs on the polymarket-infra VM — now Zurich (moved from Frankfurt to clear a Polymarket order geolock). See crypto-shortterm-repo-rename-pmv2-rearch.
Architecture (v2 / Pattern B — producer-only, two binaries one image)
- observe (
shortterm-crypto-algo-observe) — Phase-0 recorder: Binance trades + on-chain Chainlink BTC/USD (Polygon dRPC) + Polymarket L2 book → fair value →crypto_shortterm.observations. Keep running. - emit (
shortterm-crypto-algo-emit) — Phase-1 producer: on the validated regime, publishes a pmv2-contracts schema_2 EntryOrder to NATSpmv2.order.crypto_shortterm_latency_test.entry(JetStream + PubAck), records tocrypto_shortterm.emitted_signals. @positionmanager (PM) consumes on streamPMV2_ORDERSand executes.
Wire contract
source = crypto_shortterm_latency_test;id=Nats-Msg-Id=crypto_shortterm_latency_test|<window_id>(PM dedup key); Limit arm;size_shares = 5. pmv2-contracts is a private git dep (rev1f05fff). Executor = @positionmanager (NOT @polymarket). GAR imageapps/pmv2-crypto-algo:latest. main =36592cd+ (Docker + rename + v2 emit + ci-auth-fix).
Status
Phase-1 producer: LIVE on the Zurich VM — dry-validate PASSED end-to-end
emit fires → publishes the v2 EntryOrder → PM consumes on
PMV2_ORDERS→ eff=Dry → DryRehearsed (build+sign, NO POST, no money) → telegram notify. The whole producer→executor seam is proven.EMIT_MAX_FIRESraised 50→1000 for continuous operation (PM’sdaily_spend_cap_usd=$100is the real live-money bound).
Live (real money): NOT armed — and latency is STILL untested
Autotrade was geolock-blocked in Frankfurt — Polymarket blocked the orders by location. The VM moved to Zurich → geolock cleared. Critical correction to the prior narrative: the autotrade “didn’t work” because of the geolock, NOT latency. The orders never got far enough for ~128ms latency to matter, so the latency-capturability question is STILL UNTESTED. Andras placed manual trades in Zurich = net profit (small sample — validates the signal, not yet the strategy at scale). A live arm now (global→live AND source→live; PM resolves
min(global,source), ignoresenabled) finally tests latency. That flip is Andras’s explicit switch only.
Phase-0 offline edge gate: PASSED
Regime = τ∈[60,150)s AND |p_cal−0.5|≥0.30 (calibrated conviction). Survived purged/embargoed walk-forward + depth-aware re-run at the multiple-testing bar (t≥3); edge is real and depth-survivable (median touch ~$666). Latency budget ≈ 128ms (p90), <50ms ideal — REST execution is likely too slow (polymarket’s own assessment). See crypto-shortterm-phase0-depthaware and crypto-shortterm-phase1-latency-budget.
The validated edge — do not silently change
Frozen 20-bin calibration.json (include_str!). Fires once/window when τ∈[60,150)s AND |p_cal−0.5|≥0.30.
v1 = UP-only by design (
EMIT_BOTH_SIDES=false)Buys the Up/Yes token when
p_cal>0.5(→ p_cal≥0.80). Down-conviction windows are skipped (“DOWN skipped - UP-only v1”). Rationale: emit only polls the Up-token book; trading Down would need the Down-token book or a synthetic-complement approximation that is deliberately avoided to keep the latency test clean. This leaves ~half the (symmetric) edge on the table — Down is a deferred upgrade (poll the No/Down-book + flip the flag). Changing the τ band / threshold / calibration breaks what the analysis validated — re-run the gate if you must.
Hard gotchas (already bit us)
Durable gotchas
- Polymarket token IDs are u256 (77-digit) — never
parse::<u128>()/i64 (caused the 0-fire bug; see crypto-shortterm-polymarket-token-overflow-fix).- Gamma fields: tick =
orderPriceMinTickSize(real 0.01), min size =orderMinSize(NOTtickSize/minSize).conditionIdis a real0x….- EMIT_MAX_FIRES (env, default 50): emit hydrates
total_firesfromemitted_signalson boot → stale rows can max the cap and pause emit (truncate to reset, or raise the env). Hydration is one-shot at boot — TRUNCATE alone does NOT clear it without a restart. See crypto-emit-max-fires-cap-clear-2026-06-25.- PM mode =
min(global, source), ignoresenabled. eff=Dry → DryRehearse (no money); eff=Off → Skip. Live needs BOTH global+source = live.- Pure rustls (no openssl). Isolated
crypto_shorttermschema.- babylon MCP plugin is flaky locally — fall back to HTTP via
python3+ the token from.mcp.json(initialize → notifications/initialized → tools/call). DM to deploy reaches them; channel posts sometimes don’t.
Operational notes
- Health check (location-independent):
export DATABASE_URLfrom.env;cargo run -q -p observe --bin counts(observe freshness) +cargo run -q -p observe --bin emit_check(emit fires). Latest window within ~5min = observe healthy;emitted_signalsgrowing = emit firing. - CI: green;
build-push→GAR (apps/pmv2-crypto-algo:latest) green; main =36592cd+. Gate CI needs thePMV2_REPO_MASTER_KEYrepo secret (added) for the private pmv2-contracts dep. - Pattern B apps.yml two-container (observe + emit) cutover finishing on deploy’s side; retire Pattern A.
Open items / next steps
- The real open question: latency capturability. Now testable in Zurich (geolock gone). A small live 200 was reversed — bet stays ~5sh, cap stays $100; see crypto-shortterm-phase1-bet-sizing.)
- Down side (
EMIT_BOTH_SIDES) — the validated regime is symmetric, so UP-only leaves ~half the trades on the table. Proper build = poll the Down-token book too (discovery already resolvestoken_down) + mirror the fire logic, NOT the synthetic complement. Offered, not built. - Forward-test reconciliation — join
emitted_signals(58+ v2 fires) tooutcomesfor the actual Up-bet win rate; compare against Andras’s profitable manual fills. - Pattern B apps.yml two-container cutover finishing on deploy’s side; retire Pattern A.
Related
- crypto-shortterm — project index.
- crypto-shortterm-repo-rename-pmv2-rearch — repo rename
wowjeeez/pmv2-crypto-algo, dir-per-producer pmv2 layout, executor split. - crypto-shortterm-phase1-execution-decision — the producer/executor split + the original 128ms-vs-REST latency-test framing.
- crypto-shortterm-phase1-latency-budget — the ≈128ms / <50ms publish→fill budget the live arm will finally measure.
- crypto-shortterm-phase0-depthaware — the offline gate PASSED (edge survives depth-capped sizing).
- crypto-shortterm-phase1-emit, crypto-shortterm-emit-guardrails, crypto-shortterm-emit-prelive-pass2 — the emit producer and its pre-live hardening.
- crypto-shortterm-polymarket-token-overflow-fix — the u256 token-id overflow (never u128).
- crypto-emit-max-fires-cap-clear-2026-06-25 — EMIT_MAX_FIRES boot-hydration gotcha + restart requirement.