Skip to content

bryanchang/yello-world

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

yello

Cross-venue arbitrage trading bots for crypto (Binance, Coinbase) and prediction markets (Polymarket, Kalshi), in Python. Paper-trading only for the initial build — simulated fills against live orderbooks, no real capital at risk.

"Beat the market" doesn't mean pretty demos. It means a system that is honest about fees, slippage, and latency — so when it says there's an edge, you can trust it before risking a dollar.

What it does

  • Streams orderbooks from every enabled venue in parallel.
  • Detects cross-venue arbitrage opportunities:
    • Crypto: buy BTC/ETH on the cheaper venue, sell on the richer one.
    • Prediction (YES+NO): buy YES on venue A and NO on venue B when their combined cost is strictly below $1 (risk-free guaranteed payout at settlement).
    • Prediction (same side): classic cross-venue arb when the same outcome trades at different prices.
  • Walks the books level-by-level to compute the maximum profitable size, stopping at the first loss-making increment.
  • Applies a honest-slippage haircut: configurable latency penalty, exchange-specific taker fees (including Kalshi's exact per-contract formula), and a cap on how much of top-of-book depth you can eat in one shot.
  • Runs every opportunity through a risk gate stack (min net edge, per-trade notional, daily loss kill switch, gross exposure).
  • Executes paper fills against the real book and writes every fill, skip reason, and balance delta to SQLite.
  • yello pnl prints realized/unrealized PnL, balances, recent fills, and — critically — a histogram of why opportunities were skipped.

Quick start

# clone, cd, then:
uv venv --python 3.11
uv pip install -e ".[dev]"
cp .env.example .env     # paper mode needs no real keys

# verify the build
uv run pytest tests/unit -q

# sanity-check live endpoints
uv run yello doctor

# one-shot scan: prints top-of-book and any net edge for a config pair
uv run yello scan --pair BTC-USDC

# full loop (Ctrl-C to stop)
uv run yello run

# report
uv run yello pnl --hours 1

Project layout

src/yello/
  core/       models, money, fees, clock
  adapters/   Binance, Coinbase, Polymarket, Kalshi
  matching/   cross-venue symbol registry + fuzzy prediction matcher
  arb/        walk-book edge math + opportunity detectors + sizer
  execution/  paper fill simulator + settlement poller
  risk/       gate functions + persistent kill-switch state
  runtime/    async loop, book bus, feeds
  pnl/        realized/unrealized accounting + rich CLI tables
  storage/    SQLite schema + typed repo
  cli.py      typer entry points
config/
  yello.yaml       venues, fees, pairs, risk, execution
  market_map.yaml  confirmed prediction market pairs (source of truth)
tests/unit/   46 deterministic, offline unit tests

Milestones

M1 (crypto, shipped): Binance + Coinbase adapters, crypto arb detector, walk-book paper executor, risk gates, full CLI, PnL reporting, 46 unit tests.

M2 (prediction, shipped): Polymarket + Kalshi adapters, YES+NO and same-side arb math, fuzzy title matching for yello markets suggest, YAML-confirmed pairs as source of truth for trading.

M3 (not shipped): Full risk state persistence across restarts, Coinbase level2 WebSocket with sequence-gap handling, yello backtest from recorded book snapshots, prediction-market settlement poller.

Honest limitations (read this before you get excited)

  • Retail fees kill the crypto arb edge. Coinbase retail taker is 60 bps; BTC cross-venue spreads rarely exceed 30–50 bps. Expect the paper PnL curve to be slightly negative at retail tiers. That is a feature — it's the system telling you the edge isn't there. Bump yourself to an advanced fee tier in config/yello.yaml to see how the numbers change.
  • USDT ≠ USD. Binance is USDT-denominated and Coinbase is USD. They're not the same asset. Either price the basis into the edge, or trade USDC-on-both pairs (the shipped config does the latter).
  • Prediction market matching is semantically hard. Polymarket and Kalshi frequently phrase "the same" event with different resolution sources, cutoff times, and rounding. yello markets suggest proposes candidates via fuzzy title match, but never auto-trades fuzzy matches — a human has to confirm each pair into config/market_map.yaml.
  • Kalshi fees are dynamic per-contract, not a flat percentage. The exact formula ceil(0.07 * price * (1 - price) * contracts * 100) cents is implemented in src/yello/core/fees.py.
  • Polymarket live trading needs Polygon USDC and wallet signatures. Paper mode deliberately does not support that. Level-0 (unauth) public reads work fine.
  • Coinbase level2 WebSocket has sequence gaps in long-running sessions. The M1 implementation polls REST at ~1 Hz to sidestep this; full WS handling lands in M3.
  • Clock skew matters. A REST-snapshot arb that looked profitable 300 ms ago may be gone. The book_latency_ms haircut is the defense. Crank it up if you're suspicious of ghost edges.

Configuration

All non-secret config lives in config/yello.yaml. Secrets (if any) live in .env. Every number that affects PnL is tuneable:

execution:
  book_latency_ms: 150      # how much top-of-book depth to treat as stale
  taker_only: true
  walk_fraction_cap: 0.25   # max fraction of top-5-level depth per trade

risk:
  max_notional_per_trade_usd: 500
  daily_loss_limit_usd: 100
  min_net_edge_bps_crypto: 5
  min_net_edge_usd_prediction: 0.01

Testing

uv run pytest tests/unit -q          # 46 tests, no network, sub-second

The test suite covers: crypto walk-book math, prediction YES+NO and same-side math, fill simulator, fee schedules (including exact Kalshi formula), crypto symbol normalization, risk gates, and SQLite repo smoke tests.

License

MIT.

About

the first project

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages