Metadata-Version: 2.4
Name: wato
Version: 0.1.3
Summary: Build, test, and deploy prediction market trading strategies
Project-URL: Homepage, https://wato.sh
Author: Wato, Inc.
License-Expression: MIT
Keywords: bot,kalshi,paper-trading,polymarket,prediction-markets,trading
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.11
Requires-Dist: aiohttp>=3.9
Requires-Dist: cryptography>=46.0.6
Requires-Dist: httpx>=0.27
Requires-Dist: orjson>=3.9
Requires-Dist: python-socks>=2.8.1
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich-click>=1.7
Requires-Dist: rich>=13.0
Requires-Dist: websockets>=12.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Provides-Extra: kalshi
Requires-Dist: cryptography>=42.0; extra == 'kalshi'
Description-Content-Type: text/markdown

# wato

Build, test, and deploy prediction market trading bots. Strategies are plain Python classes that return declarative trade intents; wato handles order management, risk checks, paper simulation, and live execution against Polymarket and Kalshi.

## Install

```bash
pip install wato
```

Requires Python 3.11+.

## Quick start

Scaffold a new strategy:

```bash
wato init my_bot
cd my_bot
```

This writes `strategy.py` with a stubbed `MarketBot`. Replace it with the minimal market-maker below:

```python
from decimal import Decimal
from wato import MarketBot, StrategyContext
from wato.strategy.intents import Quote, CancelAll
from wato.types import OrderBook


class MidQuoter(MarketBot):
    async def on_book(self, ctx: StrategyContext, book: OrderBook) -> list:
        if not book.bids or not book.asks:
            return []

        mid = (book.bids[0].price + book.asks[0].price) / 2
        return [
            CancelAll(market_id=book.market_id, outcome_id=book.outcome_id),
            Quote(
                market_id=book.market_id,
                outcome_id=book.outcome_id,
                fair_price=mid,
                spread=Decimal("0.02"),
                size=Decimal("10"),
            ),
        ]


strategy = MidQuoter()   # module must expose a top-level `strategy` variable
```

Run it in paper mode against live Polymarket data:

```bash
wato paper strategy.py --exchange polymarket --markets asset_id
```

## Lifecycle handlers

Strategies subclass `MarketBot` and implement async handlers. Each returns a list of intents (`Quote`, `TargetPosition`, `RawOrder`, `CancelAll`, `CancelOrder`).


| Handler                  | Fires on                       |
| ------------------------ | ------------------------------ |
| `on_start(ctx)`          | engine start                   |
| `on_book(ctx, book)`     | new L2 order book snapshot     |
| `on_trade(ctx, trade)`   | public trade print             |
| `on_tick(ctx)`           | periodic tick (default 1000ms) |
| `on_fill(ctx, fill)`     | one of your orders filled      |
| `on_order(ctx, update)`  | order status change            |
| `on_market(ctx, market)` | market metadata update         |
| `on_stop(ctx)`           | shutdown                       |


Use `PortfolioBot` instead of `MarketBot` for strategies that need to coordinate across multiple venues. See the [docs](https://wato.sh) for the full context API, intent reference, and risk-limit catalog.

## CLI

```
wato init [NAME]            Scaffold a new strategy project
wato paper STRATEGY.py      Run a strategy in paper mode (simulated fills)
wato live STRATEGY.py       Run a strategy with real Kalshi orders
wato run CONFIG.yaml        Run a strategy from a YAML config (paper, live, or portfolio)
wato skills install         Install the Claude Code skill for wato bots
wato login                  Authenticate with the wato dashboard
wato logout                 Remove stored credentials
wato whoami                 Show current auth status
```

Run `wato <command> --help` for per-command flags.

### Paper trading

Paper mode **never sends real orders**. The engine replays live order books and applies a fill simulator (default: mid-touch) so you can test logic and risk against real prices.

**Polymarket** — public data only; no API keys.

```bash
wato paper strategy.py --exchange polymarket --markets asset_id
```

**Kalshi** — the feed is an authenticated WebSocket, so you need a Kalshi API key and an RSA private key in **PKCS#8 PEM** form (`-----BEGIN PRIVATE KEY-----`), registered under Kalshi Settings → API.

- **Demo vs production data:** The WebSocket host follows `KALSHI_ENVIRONMENT`: use `demo` with credentials created on the [Kalshi demo](https://demo.kalshi.com) stack (`demo-api.kalshi.co`). Production keys only work against the production feed; mixing them returns 401s.
- **`wato paper` does not take `--kalshi-environment`.** Set `KALSHI_ENVIRONMENT=demo` (or leave unset for production data). In YAML configs, use `kalshi.environment` instead (see below).
- **`.env` is not loaded automatically** — `export` variables or `source .env` in your shell.

```bash
export KALSHI_API_KEY="your-uuid"
export KALSHI_PRIVATE_KEY_PATH="$HOME/.kalshi/key.pem"
export KALSHI_ENVIRONMENT=demo   # optional; omit for production market data

wato paper strategy.py --exchange kalshi --markets KXBTC-25DEC31
# Multiple tickers: --markets KXBTC-25DEC31,KXOTHER-TICKER
```

Optional flags: `--balance` (starting paper cash), `--tick-interval`, `--tui` (terminal dashboard), `--fill-model mid`.

From a config file (handy when you want `environment: demo` without shell exports):

```yaml
# wato.yaml
mode: paper
strategy: strategy.py
exchange: kalshi
markets:
  - KXBTC-25DEC31
balance: 10000
kalshi:
  api_key: your-uuid        # or rely on KALSHI_API_KEY
  private_key: ~/.kalshi/key.pem
  environment: demo         # or prod (default if omitted resolves like live)
```

```bash
wato run wato.yaml
```

**Paper vs Kalshi demo “live”:** Paper = simulated fills only. To place **real resting orders on Kalshi’s demo exchange** (fake money, real matching engine), use `wato live ... --kalshi-environment demo` with demo API credentials instead.

### Live trading (Kalshi only)

```bash
wato live strategy.py \
  --markets KXBTC-25DEC31 \
  --kalshi-api-key "$KALSHI_API_KEY" \
  --kalshi-private-key /path/to/key.pem \
  --kalshi-environment demo \
  --max-capital 5
```

`--kalshi-environment` defaults to `prod` (real money). Always pass `demo` until you trust the strategy. See the [live trading docs](https://wato.sh) for the full credential setup and shutdown behavior.

## Risk limits

Cap downside before going live:

```bash
wato live strategy.py --markets KXBTC-25DEC31 \
  --max-loss 200 --max-position 100 --max-capital 500 \
  --kalshi-api-key $KALSHI_API_KEY \
  --kalshi-private-key ~/.kalshi/key.pem
```

Or programmatically:

```python
from decimal import Decimal
from wato.risk.limits import MaxPosition, MaxLoss, MaxCapitalAtRisk

risk_checks = [
    MaxPosition(max_size=Decimal("100")),
    MaxLoss(max_loss=Decimal("200"), initial_balance=Decimal("1000")),
    MaxCapitalAtRisk(max_capital=Decimal("500")),
]
```

## Claude Code skill

wato ships a [Claude Code skill](https://code.claude.com/docs/en/skills) that teaches Claude how to write, run, and debug wato bots. Install it once:

```bash
wato skills install
```

After restarting Claude Code, ask Claude to "write me a wato market-maker bot" and the skill auto-loads with the full SDK reference, intent API, and Kalshi gotchas.

## Dashboard

Authenticated runs stream traces, orders, fills, errors, and P&L to [dash.watolabs.com](https://dash.watolabs.com) for real-time observability. Set a `version` attribute on your strategy class to track deployments:

```python
class MyBot(MarketBot):
    version = "2.1.0"
```

## License

MIT