Skip to content

Add Windows cross-platform support#1

Open
ivandobskygithub wants to merge 21 commits into
malphas-gh:masterfrom
ivandobskygithub:feature/windows-support
Open

Add Windows cross-platform support#1
ivandobskygithub wants to merge 21 commits into
malphas-gh:masterfrom
ivandobskygithub:feature/windows-support

Conversation

@ivandobskygithub

Copy link
Copy Markdown

Summary

  • Rewrite .project/task from bash to Python for Windows compatibility (bash builtins like sed, awk, process substitution don't work reliably on Windows)
  • Add explicit encoding="utf-8" to all file I/O in .project/loop (Windows defaults to system encoding, not UTF-8)
  • Update PROMPT.md to use python .project/task invocations and add venv activation rule supporting both Windows and Linux/macOS paths
  • Update README.md to reflect the Python task runner

Test plan

  • Verify python .project/task next returns the correct next task
  • Verify python .project/task list displays all task states correctly
  • Verify python .project/task <ID> progress and python .project/task <ID> done manage state transitions
  • Run python .project/loop --max 1 to confirm the loop runner works with UTF-8 encoding
  • Test on both Windows and Linux/macOS to confirm cross-platform compatibility

🤖 Generated with Claude Code

ivandobskygithub and others added 21 commits February 21, 2026 15:36
Rewrite task runner from bash to Python for Windows compatibility,
add explicit UTF-8 encoding to all file I/O in the loop runner,
update PROMPT.md to use `python .project/task` invocations, and
add venv activation rule for cross-platform use.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Add schema.sql with all 6 tables (markets, tokens, price_snapshots,
game_states, signals, orders), indexes, and WAL/FK pragmas. Implement
async StateStore class with typed CRUD for all tables and is_fresh()
data freshness helper. 11 passing tests cover round-trips and edge cases.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Add schema.sql with all 6 tables (markets, tokens, price_snapshots,
game_states, signals, orders), indexes, and WAL/FK pragmas. Implement
async StateStore class with typed CRUD for all tables and is_fresh()
data freshness helper. 11 passing tests cover round-trips and edge cases.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
…ities

Gamma API client (httpx) for events/markets discovery, CLOB Level 0
wrappers for order books/midpoints via py-clob-client, parse_event()
for normalizing stringified JSON fields, and odds.py with Kambi/American
conversion functions. 32 new tests, all passing.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
…in application loop

Wire all components into asyncio-based pipeline with bounded queues,
WebSocket listener, REST pollers, signal/order consumers, and coordinated
startup/shutdown sequence.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Parametrized aliasing tests covering all abbreviation conflicts (PHX/PHO,
NOP/NOH, SAS/SA), fixture-based team extraction, market alignment, date
normalization, composite key commutativity, and match_and_persist integration
with in-memory SQLite.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Fix unused Signal import lint error in test_signal_engine.py. Tests were
already implemented by a prior iteration (26 signal engine tests, 14 order
manager tests). All 239 tests pass, lint clean.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
…stem)

Reliability (P0/P1):
- SQLite busy_timeout + retry-on-locked writes (was 120k lock errors)
- Live-auth hard-fail at startup + consecutive-failure trading halt watchdog
  (read-only-client fallback previously failed 1,420 live orders silently)
- Settlement grading validates game finality before booking PnL; losing
  totals get real negative PnL; total_h1 graded on first-half score;
  untrustworthy finals flagged 'unsettled' instead of written off
- Exit lifecycle is place-and-confirm: positions become 'exiting' and only
  book exited_* when the fill tracker confirms the sell matched; hockey ML
  time/OT exits now actually place sells; stale exit sells cancel + reopen
- ARB_DRY_RUN is a hard gate over every per-variant/engine is_live flag
- Live orders gated on Kambi game-state freshness (no trading stale feeds)
- Market WS best bid/ask fixed (was taking worst level), freshness-gated;
  reconnect when new tokens are discovered (resubscribe was a no-op)
- User WS handles maker_orders fills (resting sells), accumulates partials
  volume-weighted, confirms position exits on sell fills
- Restart-safe order dedup via DB; bust-ladder timers and ladder/resting
  sell order IDs persisted on positions; exact signal attribution
- Risk limits in USD (was summing shares), per-game exposure cap,
  real category caps; rotating logs; tracked background tasks

Strategy:
- Per-league live gating: NBA unders disabled (-0.104 EV/$1, n=17,303),
  NCAAB unders stay (+0.125, n=19,886)
- EV-checked taker entries: buy at the ask (FAK) only when
  ask <= Wilson-bound win prob - margin; never rest limits above market
  (median ML fill was +0.58 above signal mid = adverse selection)
- Fractional Kelly stake sizing on Wilson lower bounds from per-game samples
- Clinch sniper: totals lines mathematically clinched are bought
  immediately, sized to book liquidity
- Complete-the-box: buy the opposite token cheap to lock profit while
  liquidity is present; live moneyline price stop-losses (previously none);
  systematic resting take-profit sells for all live positions
- Order book captured at +0s/+2s/+5s to measure edge surviving
  Polymarket's ~2s taker matching delay

Tests: 244 -> 649 passing, ruff clean.

Co-Authored-By: Claude Fable 5 <[email protected]>
Correctness (real-money impact):
- Partial sell fills now reduce the position and keep monitoring the
  remainder instead of closing the whole row (untracked shares had no
  stop-loss/settlement); cumulative vs incremental fill semantics made
  explicit across fill_tracker and user-WS paths
- User WS creates the position on a live BUY fill — marking the order
  'matched' removed it from fill_tracker's scan, leaving real shares
  untracked; box hedges are recognized and never become independent
  positions (a parked take-profit would have silently unwound the box)
- _begin_live_exit cancels competing resting sells first (no dual sells
  against the same shares) and no longer fabricates an exit price on
  zero balance — it links the possibly-filled prior sell for the fill
  tracker to confirm at the real traded price
- _expire_stale_exits does not reopen a position when the cancel fails
  (the sell may have just matched — a second sell would be unbacked)
- Live order dedup split live/dry-run: a dry-run grid variant no longer
  blocks the later live clinch sniper on the same token
- Exposure caps count only committed orders (live/pending/matched) —
  expired GTD entries were consuming the per-game and daily caps
- Live bust ladder now covers total_h1 (the inner H1 guard was dead
  code); dry-run ML positions keep their stop_loss_price (was zeroed,
  skewing paper stats vs live)
- Tick snapping rounds to nearest (float floor dropped a full tick for
  on-grid prices like 0.58); 'other' category cap can actually trigger
- Live signals without win-prob estimates (hockey/football) now EV-check
  at the variant limit and cross the spread or skip — never rest above
  market; per-sport kill switches ARB_HOCKEY_LIVE/ARB_FOOTBALL_LIVE
- main.py requires trading auth whenever not in dry-run (hockey/football
  engines go live outside the basketball variant lists)
- settlement: unknown leagues are never graded with basketball math;
  cross-platform engine freshness tightened to 30s
- unsettled positions surfaced with recurring warnings

Performance / hygiene:
- Index on signals(token_id, signal_type) — dedup lookups were full
  table scans of an 85k+ row table on every poll cycle
- Removed dead ws_client.py (shipped the known-bad best-price logic),
  dead _CATEGORY_PREFIX map, duplicate _FOOTBALL_LEAGUES set; reuse
  per-game exposure within order_consumer; fixed stale ladder comment

Co-Authored-By: Claude Fable 5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant