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 stream PMV2_ORDERS, subject pmv2.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 NATS pmv2.order.crypto_shortterm_latency_test.entry (JetStream + PubAck), records to crypto_shortterm.emitted_signals. @positionmanager (PM) consumes on stream PMV2_ORDERS and 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 (rev 1f05fff). Executor = @positionmanager (NOT @polymarket). GAR image apps/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_FIRES raised 50→1000 for continuous operation (PM’s daily_spend_cap_usd=$100 is 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), ignores enabled) 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 (NOT tickSize/minSize). conditionId is a real 0x….
  • EMIT_MAX_FIRES (env, default 50): emit hydrates total_fires from emitted_signals on 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), ignores enabled. eff=Dry → DryRehearse (no money); eff=Off → Skip. Live needs BOTH global+source = live.
  • Pure rustls (no openssl). Isolated crypto_shortterm schema.
  • 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_URL from .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_signals growing = emit firing.
  • CI: green; build-push→GAR (apps/pmv2-crypto-algo:latest) green; main = 36592cd+. Gate CI needs the PMV2_REPO_MASTER_KEY repo 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

  1. 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.)
  2. 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 resolves token_down) + mirror the fire logic, NOT the synthetic complement. Offered, not built.
  3. Forward-test reconciliation — join emitted_signals (58+ v2 fires) to outcomes for the actual Up-bet win rate; compare against Andras’s profitable manual fills.
  4. Pattern B apps.yml two-container cutover finishing on deploy’s side; retire Pattern A.