Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- run: pip install -e ".[dev]"
- run: ruff check src/ tests/
- run: pytest -q --tb=short
36 changes: 36 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Publish to PyPI

on:
release:
types: [published]

permissions:
id-token: write # OIDC for Trusted Publishers

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install build
- run: python -m build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/

publish:
needs: build
runs-on: ubuntu-latest
environment: pypi
permissions:
id-token: write
steps:
- uses: actions/download-artifact@v4
with:
name: dist
path: dist/
- uses: pypa/gh-action-pypi-publish@release/v1
19 changes: 19 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
__pycache__/
*.py[cod]
*$py.class
*.egg-info/
dist/
build/
.eggs/
*.egg
.venv/
venv/
env/
.env
.pytest_cache/
.ruff_cache/
.mypy_cache/
htmlcov/
.coverage
*.so
.DS_Store
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2026 Itô Markets
Copyright (c) 2026 Ito Markets

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
127 changes: 125 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,125 @@
# ito-python
SDK for Itô Markets - Python
# ito-markets — Python SDK for Ito Markets

Thin, typed Python wrapper for the [Ito Markets public API](https://institutional.itomarkets.com/docs/public-api). Access prediction market baskets, individual market data, historical orderbook snapshots, and run backtests — all with a single `pip install`.

## Install

```bash
pip install ito-markets
# or with pandas support:
pip install ito-markets[pandas]
```

## Quick Start

```python
from ito import ItoClient

client = ItoClient("ito_...") # your API key from Settings

# List all baskets
baskets = client.baskets.list()
for b in baskets["data"]:
print(f"{b['basket_id']}: ${b['stats']['current_price']:.2f}")

# Get a single market
market = client.markets.get("will-btc-reach-100k")
print(market["data"]["title"], market["data"]["last_price"])

# Price history
history = client.markets.history("will-btc-reach-100k", days=90)
for point in history["data"]["series"]:
print(point["date"], point["close_price"])

# Bulk prices for multiple markets
prices = client.data.prices(["market-a", "market-b", "market-c"], days=30)

# Historical L2 orderbook
book = client.data.orderbook(
venue="polymarket",
market="will-btc-reach-100k",
start="2026-06-01T00:00:00Z",
end="2026-06-01T01:00:00Z",
limit=5000,
)

# Run a backtest on a thematic basket
result = client.backtests.run(
strategy_id="crypto_updown_roll_timing",
dataset_id="clickhouse:ito_hot.platform_orderbook_l2",
venues=["polymarket"],
date_range={"start": "2026-05-01T00:00:00Z", "end": "2026-06-01T00:00:00Z"},
basket_id="middle-east-conflict", # only markets in this basket
params={"roll_trigger": "liquidity_spread_score"},
)
print(f"P&L: ${result['data']['metrics']['pnl_usd']:.2f}")
```

## API Key

1. Go to [institutional.itomarkets.com](https://institutional.itomarkets.com)
2. Sign up / log in
3. Go to **Settings** -> generate an API key
4. Use the key (starts with `ito_`) in the client constructor

## Available Endpoints

### Baskets (9 endpoints)
| Method | Description |
|--------|-------------|
| `client.baskets.list()` | All baskets with current prices |
| `client.baskets.get(id)` | Single basket details |
| `client.baskets.price(id)` | Current price + underlyer snapshot |
| `client.baskets.history(id)` | Price time series |
| `client.baskets.chart(id)` | OHLC chart data |
| `client.baskets.metrics(id)` | Returns, volatility |
| `client.baskets.underlyers(id)` | Component markets |
| `client.baskets.overrides()` | Manual overrides |
| `client.baskets.volume_daily()` | Daily traded volume |

### Markets (3 endpoints)
| Method | Description |
|--------|-------------|
| `client.markets.search()` | Filtered listing by volume |
| `client.markets.get(id)` | Single market detail |
| `client.markets.history(id)` | Daily price series |

### Research Data (2 endpoints)
| Method | Description |
|--------|-------------|
| `client.data.orderbook(venue, market)` | Historical L2 snapshots |
| `client.data.prices(market_ids)` | Bulk daily close prices |

### Backtesting (9 endpoints)
| Method | Description |
|--------|-------------|
| `client.backtests.strategies()` | Available strategies |
| `client.backtests.create_strategy(...)` | Create custom strategy |
| `client.backtests.custom_strategies()` | List custom strategies |
| `client.backtests.datasets()` | Available datasets |
| `client.backtests.execution_models()` | Fill models |
| `client.backtests.validate(...)` | Dry-run validation |
| `client.backtests.plan(...)` | Multi-window experiment |
| `client.backtests.submit(...)` | Submit for execution |
| `client.backtests.run(...)` | Submit + poll to completion |

## Features

- **Typed**: Full type hints for IDE autocompletion
- **Retries**: Automatic retry with exponential backoff on 429/5xx
- **Errors**: Typed exceptions (`ItoAuthError`, `ItoRateLimitError`, etc.)
- **Context manager**: `with ItoClient(...) as client:` for clean resource management
- **Lightweight**: Only dependency is `httpx`

## Development

```bash
git clone https://github.com/Ito-Markets/ito-python.git
cd ito-python
pip install -e ".[dev]"
pytest
```

## License

MIT
54 changes: 54 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "ito-markets"
version = "0.1.0"
description = "Python SDK for the Ito Markets public API — prediction market data, baskets, and backtesting."
readme = "README.md"
license = "MIT"
requires-python = ">=3.10"
authors = [
{name = "Ito Markets", email = "dev@itomarkets.com"},
]
keywords = ["prediction-markets", "backtesting", "quant", "research", "polymarket", "kalshi"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Scientific/Engineering :: Information Analysis",
"Typing :: Typed",
]
dependencies = [
"httpx>=0.25,<1.0",
]

[project.optional-dependencies]
pandas = ["pandas>=2.0"]
dev = [
"pytest>=7.0",
"pytest-cov>=4.0",
"respx>=0.21",
"ruff>=0.4",
]

[project.urls]
Homepage = "https://itomarkets.com"
Documentation = "https://institutional.itomarkets.com/docs/public-api"
Repository = "https://github.com/Ito-Markets/ito-python"
Changelog = "https://github.com/Ito-Markets/ito-python/releases"

[tool.hatch.build.targets.wheel]
packages = ["src/ito"]

[tool.pytest.ini_options]
testpaths = ["tests"]

[tool.ruff]
target-version = "py310"
line-length = 100
21 changes: 21 additions & 0 deletions src/ito/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""Ito Markets Python SDK — prediction market data, baskets, and backtesting."""

from ito.client import ItoClient
from ito.exceptions import (
ItoAPIError,
ItoAuthError,
ItoNotFoundError,
ItoRateLimitError,
ItoValidationError,
)

__all__ = [
"ItoClient",
"ItoAPIError",
"ItoAuthError",
"ItoNotFoundError",
"ItoRateLimitError",
"ItoValidationError",
]

__version__ = "0.1.0"
Loading
Loading