The authoritative current-state snapshot for the weather effort after the pmv2 ecosystem reorg (per Andras’s Miro board) and the carve-out of the Asian-weather (weather_as) lane into its own private repo. This supersedes the single-repo weather-bet framing in weather-bet and weather-bet-live-status: weather-bet is now two repos under a multi-producer / single-executor architecture, and the AS lane is a lean Python producer at end-of-stage-3 (validated prototype, never run live).

Companion note (US-lane / cross-service view)

pmv2-rearchitecture covers the same reorg from the US producer + cross-service side (the limit arm of the contract, US sizing, the dry-test gate saga, the cohort/crypto/notify framing). This note is the Asian-weather (weather_as) producer view — the as_weather_algo module map + the validated-but-never-live AS edge. The two are consistent.

Current state in one place (2026-06-22)

Architecture: pmv2 is now multi-producer → single-executor. position_manager is the SINGLE execution authority — it consumes signals from NATS and owns gate (off/dry/live) + caps/breaker + sign + POST + record; polymarket_fetch retires. Producers own strategy + sizing and publish READY entry-orders: cohort_algo, crypto_algo, us_weather_algo (the former weather-bet), and the new as_weather_algo. telegram_connector rides alongside. Repos: weather-bet was renamed → pmv2-weather-us-algo and moved to /coding/pmv2/us_weather_algo (US engine + the shared research history). The new PRIVATE pmv2-weather-as-algo lives at /coding/pmv2/as_weather_algo (committed e9415dc, pushed) — the lean Python AS producer. AS lane: source=weather_as, subject pmv2.order.weather_as.entry. Pipeline: observe IEM → causal lock → match bucket → convergence-gate ≥0.68 → size ) — but single-season, thin, convergence-selected, and NEVER RUN LIVE (see the maturity warning below). Stage: end-of-stage-3 (validated prototype). The forward dry-run is the next milestone.

1. The pmv2 ecosystem reorg

Andras’s Miro board reshapes pmv2 from a tangle of per-strategy executors into a clean multi-producer / single-executor topology. Strategy and execution are now separated by a NATS wire contract.

position_manager = the SINGLE execution authority

There is now exactly one component that touches the CLOB / signs / spends money: position_manager. Its responsibilities (and only its):

  1. Consume entry-orders off NATS (per-source subjects).
  2. Gate by mode — off (ack-and-skip) / dry (alert + record, no order) / live (place order).
  3. Risk — apply caps + a circuit breaker before anything goes out.
  4. Sign the order with the CLOB-holding wallet identity.
  5. POST to the CLOB.
  6. Record the fill / outcome.

polymarket_fetch (the legacy sibling that previously held both copy-trade signal logic and execution) retires into this — execution moves wholesale to position_manager. This is the single chokepoint where caps, the breaker, and the live/dry/off switch live, so no producer can ever place an order directly.

Producers own strategy + sizing and publish READY entry-orders

Each producer is responsible for its own strategy AND its sizing decision, and emits a READY-to-execute entry-order (not a raw signal the executor has to size). The producers:

ProducerLanePricing kind
cohort_algocopy-trade / cohort first-moverderived (reference_price + conviction → size_usd)
crypto_algocrypto short-termlimit (directive)
us_weather_algoUS weather (the former weather-bet)limit (directive)
as_weather_algoAsian weather (NEW)limit (directive)
telegram_connectoroperator/notify surface

For Agents

The decisive split: position_manager is the only writer to the CLOB. Everything else is a producer that publishes a sized, READY entry-order envelope onto pmv2.order.<source>.entry and never signs or POSTs. The former weather-bet is now the us_weather_algo producer; the new as_weather_algo is its Asian sibling. Both are Directive (limit) sources.

Trade wire-contract — the pmv2-contracts crate

Update (2026-06-22, later same day): pmv2-contracts is now PUBLISHED

The crate has since been published (github.com/wowjeeez/pmv2-contracts) — serde + rust_decimal only; holds the envelope types, the Pricing enum (limit | derived), Side, SCHEMA_VERSION = 2, and subject builders; source is a free String, not an enum (a wrong value silently routes to Mode::Off). This unblocks both lanes’ publisher rewrites. The US-side v2 contract sign-off + field-level detail is in pmv2-rearchitecture; US current state in weather-bet-live-status. The “being designed — not yet built” framing below is from earlier the same day.

The producers and position_manager agree on ONE entry envelope, defined in a shared pmv2-contracts crate. Its shape:

  • A single envelope with a pricing discriminator (tagged union):
    • limit — a directive: the producer states limit_price + size_shares and the executor places that order verbatim. Used by weather (US + AS) and crypto.
    • derived — the producer hands reference_price + conviction + size_usd and the executor derives the actual limit. Used by cohort.
  • Subjects: pmv2.order.<source>.<entry|exit> — e.g. pmv2.order.weather_as.entry, pmv2.order.weather_us.entry, pmv2.order.cohort.entry. Routing is by source in the subject.
  • Weather is entry-only — the strategy is hold-to-settlement, so weather producers publish .entry and never .exit.
  • Time-to-resolution gate is EXEMPT for Directive sources. The executor’s generic TTR guard (don’t enter too close to resolution) does not apply to limit/directive entries — weather deliberately enters late (near settlement), so the directive sources opt out of that gate.

This crate is the precondition for the AS lane’s publish leg (see §3): as_weather_algo’s publisher.py still emits the legacy wx-signal envelope, and must be rewritten to the pmv2-contracts envelope before position_manager can consume it.

2. Repos — weather-bet is now two repos

RepoPathVisibilityRole
pmv2-weather-us-algo (renamed from weather-bet)/coding/pmv2/us_weather_algoThe US engine (wx-signal Rust crate) + the shared research history (research/, research/reports/). The original repo, renamed and moved under pmv2/.
pmv2-weather-as-algo (NEW, PRIVATE)/coding/pmv2/as_weather_algoprivateThe lean Python AS producer. Committed e9415dc, pushed. Self-contained — no imports back into any research/ tree.
  • The US wx-signal engine, its Supabase migration, the NATS NKey auth work, and the entire research/ corpus (decypher, lag, gate, net-cost, win-label, shadow-rehearsal) stay in us_weather_algo. All the vault notes whose repo pointers say research/... now resolve under /coding/pmv2/us_weather_algo/research/....
  • The AS producer is a copied, untangled subset — every module is a local copy, deliberately decoupled from the research tree so it can ship as a standalone private producer.

Stale path references across the vault

Older notes (weather-bet-live-status, weather-bet, and the research notes) say github.com/wowjeeez/weather-bet and /Users/levander/coding/weather_bet. Those are the old repo identity. The repo is now pmv2-weather-us-algo at /coding/pmv2/us_weather_algo (US + research) with the AS lane split into pmv2-weather-as-algo at /coding/pmv2/as_weather_algo. Treat the new paths as canonical.

3. The Asian-weather (weather_as) lane

A self-contained Python producer for Asian-afternoon late-settlement weather markets, carved out of the shadow-rehearsal research into its own repo. It runs the full signal end-to-end and self-measures, independent of execution.

  • Source: weather_as
  • Subject: pmv2.order.weather_as.entry
  • Modes: OFF / dry

Pipeline

observe (IEM/METAR running-max)
  -> causal lock (hour >= 15 + no-rise 90 min)        # lock.causal_lock, LOCK_HOUR=15, NO_RISE_SECS=5400
  -> match bucket (Gamma event/bucket -> YES token)   # engine.build_signal
  -> convergence-gate >= 0.68 (sklearn pkl)           # gate/predict.py, GATE_THRESHOLD=0.68
  -> size $10-30 clip (gate-score-scaled notional)    # config.notional_for
  -> publish (NATS JetStream entry-order)             # publisher.py  [WAITS ON pmv2-contracts]
  -> self-measure record / settle (fill + net P&L)    # selfmeasure.py

Module map (/coding/pmv2/as_weather_algo/)

ModuleRole
config.pycities/stations loader, endpoints, lock constants (LOCK_HOUR=15, NO_RISE_SECS=5400), gate threshold 0.68, notional band $10–30, notional_for(gate_score) clip sizing
lock.pycausal_lock + running-max series (copied from the research engine)
metar.pyIEM ASOS obs fetch + running-max-of-day builder
buckets.pytemperature-bucket label parsing + winning-label resolution
stations.pyGamma slug builder + station/resolution parsing
engine.pyGamma event fetch, bucket→degree match, YES token, CLOB price ladder (/price/midpoint/book), build_signal
gate/predict.py + gate/gate_model.pklthe convergence gate is loaded here (featurize + predict_proba); pickled with sklearn 1.9.0 / pandas 3.0.3, loads on CPython 3.13+
shadow_engine.pyorchestrator: --rehearse / --self-test / --dry-print / --smoke / --live / --settle
publisher.pyNATS JetStream entry-order publisher + offline dry_printstill emits the legacy envelope (see below)
fillability.pycausal price-history fetch + causal snap (for self-measure fills)
selfmeasure.pyrecord_signal + settle (fill + resolution + net P&L) only — no baseline benchmarking
asia_stations.jsonAsian (+ a few EU/US) station map: ICAO, IEM id, unit, tz

Standalone vs NATS — the two legs

  • Self-measure runs standalone. --rehearse / --self-test / --dry-print / --settle and the forward dry-run (record_signal + settle) need no NATS--dry-print needs no network at all (the deps are still required to unpickle the gate). The dry-run measures fill + resolution + net P&L per row independently of execution.
  • The publish leg waits on pmv2-contracts. --smoke / --live publish to NATS and are dormant unless NATS_URL is set (plus optional WEATHER_SIGNAL_SUBJECT, NATS_NKEY_SEED). But publisher.py was copied as-is and still mirrors the legacy wx-signal SignalPayload (source = "weather_shadow", subject weather.shadow, additive mode / gate_score fields). Before it can publish into pmv2 it needs the pmv2-contracts envelope rewrite + a position_manager that routes on source and tolerates the additive fields. This is the blocking dependency for the live wire.

Sizing — gate-score-scaled clip

config.notional_for(gate_score) maps the gate probability across the $10–30 band: frac = (gate_score − 0.68) / (1 − 0.68), clamped to [0,1], notional = round(10 + frac·20, 2). So a just-admitted entry (0.68) clips at 30.

Cohort & exclusions

  • 9 of 11 engine cities covered in replay (atlanta, busan, chengdu, paris, qingdao, san-francisco, seoul, shenzhen, taipei). tokyo + wuhan uncovered — IEM rate-limited the China stations before reaching them (alphabetically last).
  • Hong Kong is excluded from the runnable cohort: it resolves to the Hong Kong Observatory at 0.1°C precision, not an airport METAR, so it cannot be IEM-rehearsed (iem_id=null, caveat in asia_stations.json).

4. Validated edge + honest maturity

The edge is the product of a six-stage research chain, each link a separate validated note. Read in order: weather-top50-decypher-2026-06-19weather-lag-distribution-2026-06-19weather-exante-gate-2026-06-19weather-netcost-precheck-2026-06-19weather-gate-winlabel-2026-06-19weather-asia-shadow-rehearsal-2026-06-19.

StageNoteWhat it established
decypherweather-top50-decypher-2026-06-19the money is in capacity, not return; “detect, don’t mirror”; ≤0.95 fillable edge plausible but not proven
lagweather-lag-distribution-2026-06-19unbiased reprice-lag (~34.4% unconditional reach@15); winners pay a ~2-tick PREMIUM not a discount; gate must be ex-ante
gateweather-exante-gate-2026-06-19lean ex-ante P(tradeable) classifier, OOS AUC 0.795, dominant feature local_hour; threshold ~0.68
net-costweather-netcost-precheck-2026-06-19gated EV +0.140/ pessimistic; gate lift +0.317/$; edge concentrates in Asian-afternoon cities
win-labelweather-gate-winlabel-2026-06-19re-scoring the gate on P(WIN) (not convergence) gives only +0.0604/$, which loses to a per-city win-rate lookup (+0.0939) — the convergence EV is an optimistic ceiling
shadow-rehearsalweather-asia-shadow-rehearsal-2026-06-19fill-degradation survives (gated net EV ~+0.14/$ at L=5 vs per-city +0.09 vs ungated +0.06); CONDITIONAL GO on a live dry-run, NO-GO on Rust productionization

The edge is real on backtest — gated net-of-cost EV ~+0.14/$ beats the per-city +0.09 and ungated +0.06 baselines, and survives the worst modelled cost corner.

NEVER RUN LIVE — the maturity caveats are load-bearing

This is a validated prototype, not a live strategy. No capital has ever traded. Five caveats hold it there:

  1. Single season. The entire edge is measured on ~11 days of June 2026 daily-high markets. No out-of-season / regime-shift evidence whatsoever.
  2. Thin cohort. Anchored n = 14–19 per latency; per-city n = 1–5. CIs are wide — a feasibility signal, not a sized backtest.
  3. The gate is convergence-selected ⇒ optimistic ceiling. It selects on tradeable_10 = P(book converges toward ~1.0), not P(win). The win-label re-score (weather-gate-winlabel-2026-06-19) collapses the EV from ~+0.14/ and shows the model does not beat a per-city win-rate lookup. Treat the headline EV as an upper bound, gate scores as a research artifact, not a calibrated live probability.
  4. The book reprices past us ~40–50% of the time. On the locked days, the book is already > 0.95 at entry 40.6% (L=1) / 45.7% (L=5) / 49.7% (L=15) of the time — adverse selection: we miss roughly half the opportunities, and the ones we can enter are the genuinely-uncertain ones.
  5. Stage = end-of-stage-3 (validated prototype). The next milestone is the forward dry-run (self-measure against live signals), NOT capital. Rust productionization is NO-GO until a larger live sample reproduces positive EV, the gate is re-scored against a true WIN/+EV label, and tokyo + wuhan coverage is filled.

5. Pending / next

Open items (2026-06-22)

  1. Move the research record into the AS repo — a cross-repo push the user is authorizing (research currently lives in us_weather_algo; the relevant slice is being carried into as_weather_algo).
  2. pmv2-contracts crate — design + build the shared entry-envelope crate (the pricing limit/derived discriminator, pmv2.order.<source>.<entry|exit> subjects, Directive TTR exemption).
  3. Publisher rewrite — rewrite as_weather_algo/publisher.py (and the US engine’s publisher) from the legacy weather.shadow / weather_shadow envelope to the pmv2-contracts envelope; position_manager consumes it routed on source.
  4. @deploy guidance — deployment guidance for the AS producer.
  5. Forward dry-run — run as_weather_algo in dry against live signals to measure realizable fillability + reject rate. This is the capital gate, not the backtest. The self-measure leg can start now (NATS-independent); the publish-into-pmv2 leg unblocks once pmv2-contracts lands.