Commit Graph

70 Commits

Author SHA1 Message Date
jaxperro c7c88e5084 reject ledger joins the bot's self-commit set (REJECTED bucket needs the rows on the Mac)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 14:57:36 -04:00
jaxperro 85954d8021 #25 dark flag: conviction_scope trade|position (rolling net-USD aggregate per wallet-token; clip-built conviction fires at the floor crossing). Default trade — no behavior change.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 13:18:23 -04:00
jaxperro d4fff27ab9 tick-size conformance retry on live orders + #24 v1 reject-logging (in-set BUY filter skips leave rows)
Tick bug: precision inferred from the input price's decimals rejects
VWAP-priced bounds on coarser-tick markets; the venue's rejection names
the real tick — requantize (tighten-only) and retry once.
Reject rows: copybot_rejects[.live].jsonl — splits reconciliation
UNSEEN into screen-vs-universe (the 1kto1m clip class becomes visible).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 13:07:35 -04:00
jaxperro 2c9faf8584 copybot: expected-resolution ETA on open bets (display metadata only)
Feed builder enriches open bet records with end_ts via the cached
_market lookup — one fetch per position lifetime, <=8 per publish pass,
fetched-but-unknown marked to prevent refetch loops. No execution-path
change; both dashboards render it under the LIVE pill with the
in-play-resolves-earlier tooltip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 15:43:41 -04:00
jaxperro e2621fa53d copybot: #20/#21 dark flags — entry_mode maker + exit_mode hold (defaults unchanged: taker/mirror)
entry_mode=maker (#20): GTC limit at the sharp's own price via
place_limit_order; live bids park in the pending registry with
maker_ttl_s=60 (registry-side cancel — venue GTD needs >=3min); instant
partial crosses cancel their remainder (07-10 invariant). Paper leg: a
paper_maker registry filled from RTDS prints <= bid, expired by heartbeat
sweep into honest misses. maker_stats counters; fills rows tagged maker;
ba_at_signal recorded (taker counterfactual).

exit_mode=hold (#21): _handle_their_sell choke-point returns without
ordering; every ignored sell -> copybot_ignored_exits[.live].jsonl +
state tail (the mirror counterfactual's forward control). Reconcile
logs hold-through once per position (no backstop spam, no EXIT-STUCK
alarms in hold mode).

Dark by default: real configs boot byte-identical banners; all 8 test
scripts pass; flip = one config change at Friday's read per the
pre-registrations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 13:30:32 -04:00
jaxperro a2933bb6ba feed: per-wallet missed totals in wallet_pnl + unified name resolution
wallet_pnl gains miss_n / miss_pnl (every skip ever, state + archive).
Missed display names now resolve via current follow set THEN names stored
on bet records — a retired wallet (LSB1) was splitting into an address-
prefix twin card. Verified: per-wallet miss_pnl sums exactly to the
feed's missed_pnl (+1173.65 across 199 skips).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 14:32:38 -04:00
jaxperro f4cba587cc feed: lifetime wallet_pnl, last_fill, full-history companion feed
Dashboard cards were summing the rolling 100-bet window client-side —
AIcAIc read -5.62 while lifetime (both its addresses) is -15.84/10. The
feed now publishes:
- wallet_pnl: lifetime per-NAME rollup (state + spooled archives), so
  address changes and window rotation can't skew the cards
- last_fill: stamped in _drain_fills for the bot-health strip
- <feed>_full.json: EVERY bet + EVERY miss ever (state + archives),
  written under the same change-gate, published alongside
Misses now spool to copybot_missed_archive.*.jsonl instead of silent
deletion at the 200 cap (settled rows spool first — open misses must stay
in state for the missed-settle resolver); state was at 199/200, nothing
lost. Archives join the publish set so history survives machine loss.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 14:19:20 -04:00
jaxperro e909c3a050 copybot: _token_market falls back to gamma's closed=true view (#18 follow-up)
Gamma's default /markets listing HIDES closed markets — the resolved
Odyssey market returns [] without &closed=true. Closed markets are
exactly the population repair_market_meta exists for (resolved-but-stuck
positions), so the gamma-only lookup left the paper book's own Odyssey
copy (178.57sh, resolved won) and its France-WC position permanently
cond-less; both verified resolving via the closed view. The fetch edge
is factored into _gamma_markets so the variant order, caching, and
error-then-fallback paths are unit-tested.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 11:49:46 -04:00
jaxperro 41ba871629 copybot: enrich metadata-less RTDS seeds + repair cond-less books each settle pass (closes #18)
Root cause of the 07-20 CASH≠CHAIN -$1.75: some markets stream RTDS
trades with empty title/outcome/conditionId; the seed stored them
verbatim, on_wallet_activity's 'tok not in self.conds' guard made the
empty value sticky, and settle_resolved's 'if not cond' skip left the
position silently unsettleable until the venue auto-redeemed it.

Three-layer fix:
- RTDS seed: when the payload lacks conditionId/title, enrich from the
  token id via _token_market (gamma, cached) before dispatch; the copy
  still goes through on a miss.
- conds write: falsy-overwrite instead of key-presence, so a later,
  richer source repairs an empty entry.
- repair_market_meta (called at the top of every settle pass, holding
  the lock): re-resolves empty conds for my_pos AND open missed entries,
  backfills position/bet/missed records, 300s per-token lookup backoff,
  and a once-per-token alarm when a position has sat unsettleable >1h.
  A repaired token settles in the SAME pass — the Odyssey bet would have
  self-healed the moment the market resolved.

The paper book currently carries 4 empty conds and both books have
cond-less open missed entries — the repair pass fixes those on the first
cycle after deploy. tests/test_meta_repair.py covers backfill, backoff,
the single alarm, recovery, and the end-to-end repair->settle un-stick;
full suite 8/8.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 11:31:38 -04:00
jaxperro 377192c4bf copybot: per-niche FAK re-quote waits from measured crater-refill times
The flat 10s retry was calibrated to nothing; the tape now says craters
refill at very different speeds (research requote_timing, 775k crater
prints): crypto 94% within 4s, esports 83% within 10s, sports only 70% at
10s but 76% by 25s, geo/politics tails run minutes (price guard is the
protection there, not the retry). Waits move to FAK_RETRY_NICHE_DEFAULT
{crypto 4, esports 10, sports/geo/politics/other 25}, classified by the
validated research niche patterns (esports before sports so 'LoL: A vs B'
doesn't fall through on ' vs '). cfg fak_retry_niche_s overrides per key;
fak_retry_s stays the fallback (tennis: no measurement yet) and 0 still
disables the feature. Paper-parity: same map both bots. test t8 covers the
map, first-match classing, fallback, and config override.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 17:45:32 -04:00
jaxperro 01687f4a44 copybot: one-shot 10s re-quote retry for FAK no-match OPENs
'no orders found to match with FAK order' is the #1 miss class (13 of the
last 48h's misses) — the copy lands in the crater the sharp just swept,
before makers requote. Instead of recording the miss at the first
rejection, hand the OPEN to Copybot.fak_requote_retry: sleep fak_retry_s
(default 10, 0 disables) OUTSIDE the bot lock, then re-run the whole gated
buy path (fresh quote, price guard, depth gate) exactly once, mirroring
the webhook call site's fill drain so a retry fill books lag + bet rows.
A second rejection records the miss tagged 'twice (re-quote retry)'.
Paper-parity: the hook is installed in both modes, and PaperExecutor's
FAK model re-decides on the fresh book. tests/test_fak_retry.py covers
hook scheduling, no-double-count sizing (their_size=0 re-entry), ADD and
non-FAK bypasses, and the end-to-end retry thread.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 14:52:16 -04:00
jaxperro b62557a798 memory caps: skipped tx registry recency-bounded, settled bets >30d spool to an archive ledger with drift-invariant compensation (closes #9)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:51:10 -04:00
jaxperro ab56b2aa4b reconcile_entries cadence 5m→30m (closes #12); tape transport sftp-first with base64 fallback (closes #11)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:46:28 -04:00
jaxperro 5070c234f2 redeemer rewritten for the pUSD stack: gasless redeemPositions from the deposit wallet via the executor's SecureClient, measured-delta reporting, calldata proven by on-chain simulation; auto_redeem re-enabled (closes #4)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:43:09 -04:00
jaxperro 2744b67587 chain-balance gates in reconcile_exits + retry queue — ghosts dropped, sells clamped to chain (closes #7); tape ingest pings the daily channel at start + finish
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:34:52 -04:00
jaxperro ca0e0bbd80 hardening trio: listeners start after seed (closes #5), rpc-down heartbeat flag (closes #8), publish-failure alert (closes #10)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:29:47 -04:00
jaxperro 23083c7aa7 dead-code sweep: retire copytrade CLI + LiveExecutor (archived stack), dedupe _book_snapshot→book_depth, dead keys, honest docstrings; fly.value.toml → value/ (closes #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:14:35 -04:00
jaxperro baa4182343 audit hardening: book fully serialized, chain-gated sweep, boot-id single-writer guard, TLS on user-ws, atomic valuebot state, hot-path throttle, newest-kept seen_tx, daily lock, ingest txn, AIcAIc pin
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 14:07:43 -04:00
jaxperro c91e9a8c2a dust sweep: redeem branch — untracked resolved winners collect via try_redeem, booked as adjustment
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 23:44:18 -04:00
jaxperro afaf4e461f dust sweep: daily reclaim of untracked exit residue — sells booked as adjustment, never P&L
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 23:26:12 -04:00
jaxperro 646139dfa3 paper FAK parity: no ask inside the protected band -> honest miss, not a pretend fill
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 23:48:58 -04:00
jaxperro 50fc76781a chain seed: the code for 5e97b13 — fills_from_tx + hint_txs funnel (autostash dropped it from the prior commit)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 00:10:03 -04:00
jaxperro 933d2656d8 RTDS seeds the funnel directly — copy fires at ~1s regardless of data-api indexer
Diagnosis of the 122s paper avg (user report): RTDS SAW every slow fill at
~0.3s (shadow ledger proof) but the copy landed 130-305s later — because
on_wallet_activity threw the RTDS payload away and re-fetched from the
data-api, whose indexer lagged that long on badaf/1kto1m crypto+index
markets, so the push was wasted and the 300s backstop poll did the copy.

Fix (option B as augmentation): the RTDS message carries every field
handle_trade needs, so seed it into on_wallet_activity's candidate set
(deduped by tx). The re-fetch + fill-split merge still run — the seed just
guarantees the trade is present at ~1s. detect_lag now reflects true RTDS
delivery (~1s) instead of indexer lag. 3 stub paths pass (seed-copies-on-
empty-data-api, dedup, no-seed-backstop-unaffected).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 11:13:50 -04:00
jaxperro 95dcc93b15 cursor cold-start stays fresh; lag visible on the dashboard; phantom purge
- _fetch_since_cursor cold start (no cursor) now seeds at now-600s like the
  pre-cursor fetch — the 02:10 boot walked 500 rows/wallet of history through
  the funnel and spammed ~230 phantom 'too slow (20,000m late)' missed rows
  per book (user saw them on the dashboard). Purged from both books
  (116 paper + 114 live; genuine misses remain).
- feed lag tile falls back to the LIFETIME average when the 24h window is
  empty (the live page showed '—' after a copy-less day).
- bet records now carry lag_s so the dashboard shows per-copy exec lag.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 10:57:08 -04:00
jaxperro 4aa795f9b9 protected prices conform to the book's tick (quote-precision bound)
The 4dp bound (sub-penny fix) violated tick conformity on 1c books —
'max_price must conform to tick size 0.01' failed a winning SPX copy at
14:36Z. The quoted price is always a tick multiple, so its own decimal
count is the finest safe precision: bound rounds to quote precision
(coarser is always valid on finer ticks, never the reverse). Verified
across 2dp/3dp/sub-penny quotes both sides.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 10:48:11 -04:00
jaxperro 14aa3f67f1 docs: sweep for the RTDS era, depth gate, curated set, gotcha 17-corollary + 18
System-today table: T0 RTDS detection (~1s) on both workers, own-fill push
+ depth gate on the real-money row, clone-guard note. Calibration section:
Set E rev 2 (5 wallets, drops explained, bench of 4 in backtest). Model
section: guard validation evidence + the depth-gate bullet. Data sources:
RTDS + CLOB user-channel rows. Gotcha 17 gains the 2026-07-12 corollary
(balance-diff is a fallback, one pending per token); gotcha 18 documents
the RTDS stream's two quirks (broken filters, silent-stale) and the
heartbeat-fields-over-boot-logs lesson. copybot.py docstring reflects the
layered trigger stack.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 23:39:17 -04:00
jaxperro 97eedd6c9f heartbeat shows user-ws status (like rtds) — boot 'connected' line scrolls out
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 23:27:25 -04:00
jaxperro e0679a40d9 items 2-4: depth gate + guard validated + clob_user own-fill push
DEPTH GATE (copytrade.book_depth + gate in _handle_their_buy, fitted on
131 book-annotated fills): pre-order, skip if spread>0.08 (market mid-move,
median |slip| ~14%) or ask5c<$50 (dust books mispriced every fill), else
cap the stake at 10% of 5c ask depth (keeps impact <~2%; >20% of depth made
>+2% slip 33-50% likely). Fail-open: a failed book fetch declines to bind.
This is what lets stakes scale — binds mainly on slow-market wallets like
0xbadaf319 (median 23% of depth at $40-100 stakes). config.depth_gate;
paper+live inherit DEFAULT_CONFIG.

GUARD: counterfactuals VALIDATED the 0.05 absolute guard — it sits at the
EV knee (0.05-0.10 moves ≈ breakeven, >0.10 = -20% ROI). No change, comment
records the evidence. (The +9-14% lag-drift tail in deep esports books is a
detection-lag problem the depth gate can't see; RTDS ~1s already addresses
it — protected max_price is the backstop.)

CLOB_USER: UserFillsListener streams our order/trade lifecycle from
ws-subscriptions-clob/ws/user (auth = client.credentials, the SDK's derived
L2 creds; all-markets, no per-market mgmt). A matching order id triggers an
IMMEDIATE resolve_pendings() — in-play holds adopt on match, not on the 60s
tick. Events only TRIGGER; get_order stays the arbiter (2026-07-12
anti-phantom-cash invariant intact). resolve_pendings now re-entrancy-locked
(ws + heartbeat race). 60s poll stays as the fallback; ws failure degrades
to today. Live role only.

Also: sub-$1 BUY amount bumped to the $1 venue minimum (share-flooring
shaved gated $1.00 stakes to $0.99 — 7 of 13 live rejections).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 23:18:54 -04:00
jaxperro 476c1059c8 overnight batch: H3 cursor fetch, Bearer clone-guard, SDK preflight, 5c drift alarm
- H3 (burst overflow): per-wallet trade cursor + paginated activity fetch
  (up to 5×100, walks back to the last processed timestamp) — a gkmg-scale
  clip burst can no longer scroll past a single newest-100 page. Cursor
  only advances after a fetch; 600s overlap re-serves boundary rows into
  the seen-tx dedupe. offset pagination verified against the data-api.
- clone-guard: Bearer auth (fine-grained PATs reject the 'token' scheme)
  with unauthenticated fallback + 40-hex sanity on the answer — Fly's
  shared egress IPs rate-limit the anonymous path.
- preflight_live.py rewritten for the unified SDK: deposit-wallet auth,
  pUSD collateral, order-book reach, RTDS stream delivery, geo verdict.
- ledger-drift ALARM floor 1c → 5c (4dp fill rounding accumulates pennies
  across 60+ copies; the check stays for real bugs — it caught $15.45 and
  $7.24. The self-heal path keeps its own threshold.)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 22:00:41 -04:00
jaxperro c88618f220 no price floor: min_price 0.01 → 0 (both books), cap stays 0.95
User call 2026-07-13 after a big 0.001 longshot was floor-blocked (the
same band class that blocked the 16x Hive copy at 0.05). Executor's
protected prices now round to 4dp and scale with the price — the old 2dp
rounding zeroed the bound on sub-penny books (BUY never bounds below the
quoted cross; SELL never above the quoted bid; verified at 0.001/0.002).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 21:48:20 -04:00
jaxperro 8951556e30 FIX: pending-adoption oversell — bounded arbiter + per-token serialization
2026-07-12 phantom-cash incident (+$7.86 book-only, alarms caught it):
overlapping pendings on one token each read the same balance drop via
max(matched, diff) — one real 1.48-share sell booked 3×. No real money
moved wrongly (the CLOB rejects oversells); the book just self-inflated.

Fixes: (1) order's own size caps every adoption fill; (2) the balance
diff is consulted ONLY when the exchange no longer answers for the order
(a definitive killed/0 is final); (3) SELL adoptions cap at book
holdings; (4) ONE outstanding pending per token — engine buy/sell and
exit-retries refuse while the resolver owns a token. Regression suite:
the incident scenario books exactly the real fill; phantoms zero.

Surgery (machine stopped): cash → chain $11.206, the two poisoned bets
corrected from real chain fills (residual adjustment −$0.08), drift 0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 21:38:35 -04:00
jaxperro e07ef9e68f rtds: silent-stale guard — force reconnect after 120s without messages
2026-07-11 04:00Z: the socket sat 'up' delivering nothing for 35 min with
no close event, so the on-close reconnect never fired (backstops covered
detection). The ping thread now force-closes a 120s-silent stream to
trigger the clean reconnect path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 02:04:21 -04:00
jaxperro 3784b288cd hardening trio: exit-retry (1.6), RTDS shadow ledger, boot clone-guard
- failed mirror-exits queue for up to 10 heartbeat retries (recovered
  exits ping Discord; exhaustion pages ⚠ EXIT STUCK and the position
  rides knowingly; in-play holds hand to the pending registry). 3 stub
  paths pass incl. the 1.6 spec's fail-fail-fill.
- every RTDS Set E detection appends a durable shadow-ledger row
  (lat_s + which trigger won) that rides the publish commit — the 24h
  go/no-go data for flipping RTDS on the live app.
- start.sh verifies the boot clone's HEAD against the GitHub API and
  re-clones stale replicas (bit twice today).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 18:43:22 -04:00
jaxperro fb945be2e4 T0 detection: RTDS trade stream listener (~1s, wallet-attributed)
Polymarket's real-time data socket (wss://ws-live-data.polymarket.com,
topic activity/type trades — undocumented but official: powers the site's
live feed, spec'd in Polymarket/real-time-data-client) streams every
platform trade with proxyWallet attribution. Probe 2026-07-10: median
0.8s delivery over 22k msgs, ~45/s at peak, zero drops in 45 min.

RtdsListener: unfiltered subscribe (server-side filters broken, RTDC#34),
client-side Set E match → the same on_wallet_activity funnel as the
Alchemy push (locks internally). Capped-backoff reconnect forever; if the
lib or stream is missing, detection degrades to the existing backstops
(Alchemy ~3s, 300s poll, reconcile janitor) — never to zero. Heartbeat
shows 'rtds up Ns' / '⚠ rtds down'. Paper role: ON by default (24h shadow
run starts now). Live role: OFF until the shadow validates —
RTDS_DETECT=1 enables. 5 stub paths pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 18:23:41 -04:00
jaxperro f9a4b51a4d docs: sweep everything stale after the 2026-07-10 go-live day
README system-today gains the REAL-MONEY worker row (armed, push mode,
pending registry, Discord pings); /live marked live; cheat-sheet covers
both apps + disarm/re-arm + the stale-clone verify rule; guard bullet and
safety paragraph reflect the absolute +0.05 guard and retired caps; file
map adds fly.live.toml + the bridge/probe/flatten utilities. copybot/
copytrade module docstrings drop the archived py-clob-client story.
LIVE_ROLLOUT gets a status banner (executed through Phase 4; rule 0.6
superseded; Phase 5 matrix still worth running).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 17:31:51 -04:00
jaxperro 77a944cba8 pending adoptions ping Discord like any other placement
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 17:24:59 -04:00
jaxperro 705f8b2c39 live retune (user 2026-07-10): caps off, 4% paper-parity, abs guard, pending registry
1. Caps retired: risk block mirrors the paper sentinels; sizing is the
   paper bot's 4%-of-equity (class_pct 0.04/0.12), floored at the venue's
   $1 min order (4% of a $22 book is $0.89 — sub-min stakes died at the
   gate). bankroll rebased to the real $22.28 equity; spend tracker reset
   (the confusing $35 is gone with the daily cap).
2. Price guard is now ABSOLUTE +0.05 (both books): 0.14→0.15 follows,
   0.14→0.20 skips. The relative 5% blocked one-tick moves on cheap
   in-play books.
3. Pending-order registry: in-play 'delayed' holds are no longer cancelled
   at 20s — the executor hands them to state.pending_orders with full copy
   context; the heartbeat resolver adopts the fill whenever it lands
   (bets/my_pos/cash/ledger, TTL 600s → cancel + honest miss). Recovers
   Rune-Eaters-class holds (+$7.50 forfeited by the old cancel).
   5 stub-client paths pass incl. adopt + expire.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 17:17:26 -04:00
jaxperro 56fe0dee92 INCIDENT FIX: in-play 'delayed' acceptances were logged as misses and filled untracked
2026-07-10 09:10-13:14Z: six $5 in-play esports copies returned AcceptedOrder
status 'delayed' with zero matched; the executor read matched==0 as a
rejection, recorded honest misses, and forgot the orders — which then filled
at the exchange minutes later. Book went blind (6 untracked fills, ~$30 real
spend vs $5 booked), caps stopped binding, exits never mirrored. Net damage
contained by the CLOB's own balance checks: −$2.7 incl fees, two legs won.

Executor invariant now: NO order outlives _order() untracked. Zero-matched
acceptances poll get_order → cancel remainder → measure truth via the
exchange's CONDITIONAL balance diff; exception paths sweep open orders on
the token the same way. 5 stub-client unit paths pass.

State surgery (machine disarmed first): cash reset to chain ($10.03), six
fills adopted as bets (4 settled −$4.38 w/ fees, Aurora G2 open+won), spend
tracker set to the real $35/day, false miss rows purged, one documented
-0.59 adjustment (bank-vs-deposit + probe).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 11:25:10 -04:00
jaxperro c5b87afcab live executor ported to the unified SDK (polymarket-client)
py-clob-client is archived; the CLOB rejects its orders globally. New
LedgerLiveExecutor: SecureClient.create(private_key) — deposit wallet
auto-resolves, no api_key at runtime; place_market_order FAK/FOK with
protected prices (quoted ±live.max_slippage_pct, default 5%, clamped to
[0.01,0.99]); fills parsed from AcceptedOrder (BUY: making=USD given,
taking=shares got; SELL reversed — semantics PROVEN by today's $5 round
trip: buy matched 7.35294 @ 0.68, sell matched 7.35 @ 0.67). Still never
raises into the trade loop. chain_cash_gap repointed at the deposit
wallet's pUSD (was the emptied legacy proxy → CASH≠CHAIN +24.73 alarm).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 01:08:18 -04:00
jaxperro bf11de9759 live executor crash-proofed + baseline stops eating fresh trades + poll guard
Root cause of zero live placements: the FIRST two qualifying signals
(Kruto 21:21, badaf Epic 21:53) each CRASHED the bot inside the
unguarded live order path (machine events: exit_code=1 seconds after
each signal; tick-size rejection the likely thrower — price was rounded
to 3dp on 1c-tick books). Fly restarted it and boot baseline marked the
fresh trades seen-without-copying: crash -> restart -> trade eaten,
twice. Fixes: _order never raises (failures return ok:False and feed
the new missed-row instrumentation); tick-size-aware pricing (cached
get_tick_size, buys ceil / sells floor, 0.01 fallback valid on every
book); size floored to 2dp; per-wallet poll guard (parity with the push
handler); baseline exempts trades younger than the stale window so a
restart can never eat a copyable trade again. host/order_probe.py =
controlled end-to-end placement proof (~$2 round trip).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 20:14:38 -04:00
jaxperro 8d0b087dd1 missed rows settled at resolution get one exit-print re-check
Fast in-play markets can resolve before the 5-min pass sees the sharp's
sell (and pre-2026-07-09 rows predate exit-aware settling) — won/lost
stamps hid real pre-resolution sells. A redeem prints exactly the
payout; an exit print >2c away revalues the counterfactual at the
sharp's exit. Idempotent via exit_checked.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 14:10:25 -04:00
jaxperro 8b91893fc9 missed bets settle at the sharp's EXIT when they sold pre-resolution
The missed ledger valued everything hold-to-resolution — the wrong
counterfactual for a mirror strategy (Kruto's 3c Hive entry: he banked
16x selling at 48c; the paper book mirrored for +$722; the live book's
missed row would have shown the map result instead). Three affirmative
facts before settling (same as reconcile_exits), their reconstructed
exit price, entry+exit taker fees. Also: the reconcile miss reason is
now honest — 'not copied in the detection window (reconciled)'.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 14:04:32 -04:00
jaxperro 6995b4e8d8 copybot: never clobber a settled bet record on re-entry (+ restore the two vanished)
bets{} is keyed by token; re-entering a settled market OVERWROTE the old
record and its pnl left 'realized' — the drift alarm caught it same-day
(WTI −9.97, Dota Game-1 +19.30 recovered from state history and restored
as archive keys). All three record-writers now archive settled records
to token#settled_ts keys first; aggregators iterate values() so archived
rows keep counting. NOTE: restoring truth WIDENS displayed drift — a
second, opposite-sign residual (~−11) remains under investigation
(morning forensics queued in HANDOFF); the alarm stays red on the paper
book intentionally. Live book unaffected (0 trades, drift 0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 13:53:19 -04:00
jaxperro 0b4f9158da copybot: merge fill-split conviction bets before the floor gate
A sweep or rapid clip entry splits ONE bet into several sub-floor fills:
gkmg's $612 MOUZ entry today read as 3×$204 same-second rows, every
clip below his $304 floor — the bot skipped a bet the backtest's
position-level view takes (he sold +60% five minutes later). Same-token
BUY rows within 120s now merge into the bet the sharp actually made
(weighted price, summed size, all component txs marked processed);
SELLs stay per-fill for the proportional mirror. reconcile_entries
applies the same clustering to its not-a-miss verdict so downtime
fill-splits count as real misses. Applies to BOTH books identically.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 13:45:08 -04:00
jaxperro 97a1138f49 live bot: per-fill Discord pings via DISCORD_WEBHOOK env secret (paper stays digest-only)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 00:52:17 -04:00
jaxperro d4eacbd72b publish_feed: publish untracked (first-ever) feed files — real-money feed was stuck at 404
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 00:50:08 -04:00
jaxperro 95998aaca4 live env credentials: strip pasted whitespace; bankroll = actual $24.73 deposit
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 00:30:07 -04:00
jaxperro 8ce616349e reconcile: accumulated sub-floor positions are not 'missed · bot offline'
The live path gates PER TRADE; reconcile_entries gated on POSITION size,
so 0xbadaf319's paired YES+NO arb clips ($6-37 each, all correctly
skipped below his $45 floor) accumulated into $40+ positions that read
as downtime misses while the bot was demonstrably UP. Now a miss needs
some SINGLE buy on the market to pass the same follow filter (market-
filtered /trades, full history); sub-floor accumulations log-and-skip
with a persisted verdict (state.no_miss_toks). Four phantom records
removed from the book; their hypothetical P&L never belonged in the
missed counterfactual.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 18:12:28 -04:00
jaxperro f19cc8d168 copybot: capture order-book snapshot (spread + 5c depth) on every copy
New 'book' field in the fills ledger: {bb, ba, spread, bid5c, ask5c}
from CLOB /book at fill time. The calibration experiment's weakest
assumption is the flat SLIP haircut; weeks of these snapshots give an
empirical fill model for the backtest and a depth gate before real
money sizes up (today's probe: a  stake vs $77 of bids within 5c).
Best-effort, never blocks a copy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 17:56:20 -04:00
jaxperro 82f62124e7 copytrade.py moves out of archive/ + Fly health check (watchdog layer 1)
The execution engine was load-bearing from archive/ — the one thing in
there that wasn't retired. Now at repo root next to copybot.py; the two
archived scripts that imported it as a sibling get a parent-path shim.
fly.toml gains an http /health check so Fly restarts a dark machine
(self-heal); the notify half is the GH Actions watchdog (next commit).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 17:34:36 -04:00