Metadata-Version: 2.4
Name: coingecko-pandas
Version: 0.1.3
Summary: Pandas API client for CoinGecko
License-Expression: Apache-2.0
Keywords: coingecko,crypto,pandas,api-client
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: <3.14,>=3.11
Description-Content-Type: text/markdown
Requires-Dist: cachetools>=5.3
Requires-Dist: httpx>=0.28
Requires-Dist: orjson>=3.10
Requires-Dist: pandas[computation,output-formatting,performance]>=2.2
Requires-Dist: pandera>=0.22
Requires-Dist: tqdm>=4.66
Provides-Extra: ws
Requires-Dist: websocket-client>=1.8; extra == "ws"
Requires-Dist: websockets>=13.0; extra == "ws"
Provides-Extra: explorer
Requires-Dist: streamlit>=1.30; extra == "explorer"
Requires-Dist: plotly>=5.0; extra == "explorer"
Provides-Extra: mcp
Requires-Dist: fastmcp>=2.0; extra == "mcp"
Requires-Dist: tabulate>=0.9; extra == "mcp"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-httpx>=0.35; extra == "dev"
Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
Requires-Dist: ruff>=0.9; extra == "dev"
Requires-Dist: mypy>=1.11; extra == "dev"
Requires-Dist: pandas-stubs>=2.2; extra == "dev"
Requires-Dist: types-cachetools>=5.3; extra == "dev"
Requires-Dist: python-dotenv>=1.0; extra == "dev"

# coingecko-pandas

> Pandas API client for CoinGecko

A pandas-style Python client for the CoinGecko REST and WebSocket APIs. Every list endpoint returns a `pandas.DataFrame`, every dict endpoint returns a `TypedDict`, and every shape is enforced by a `pandera` schema. Sync + async, with optional Streamlit explorer and FastMCP server extras.

## Install

```bash
uv pip install coingecko-pandas              # core
uv pip install "coingecko-pandas[ws]"        # + WebSocket
uv pip install "coingecko-pandas[explorer]"  # + Streamlit dashboard
uv pip install "coingecko-pandas[mcp]"       # + FastMCP server
uv pip install "coingecko-pandas[dev]"       # + test/lint toolchain
```

## Quickstart

### Sync

```python
from coingecko_pandas import CoinGeckoPandas

with CoinGeckoPandas() as client:
    # Top 10 by market cap
    df = client.coins_markets("usd", per_page=10, page=1)
    print(df[["id", "symbol", "currentPrice", "marketCap"]])

    # Bitcoin OHLC last day
    ohlc = client.coins_id_ohlc("bitcoin", vs_currency="usd", days="1")
    print(ohlc.tail())
```

### Async

```python
import asyncio
from coingecko_pandas import AsyncCoinGeckoPandas

async def main():
    async with AsyncCoinGeckoPandas() as client:
        markets, ohlc = await asyncio.gather(
            client.coins_markets("usd", per_page=10, page=1),
            client.coins_id_ohlc("bitcoin", vs_currency="usd", days="1"),
        )
        print(markets.head())
        print(ohlc.tail())

asyncio.run(main())
```

## Authentication

CoinGecko offers two API tiers. The repo ships an `.env.example` — copy it to `.env`, fill in your keys, and any example/test that calls `load_dotenv()` will pick them up automatically:

```bash
cp .env.example .env
$EDITOR .env
```

Or set them directly in your shell:

```bash
# Demo (free) tier
export COINGECKO_DEMO_API_KEY=...

# Pro tier (auto-switches base URL to pro-api.coingecko.com)
export COINGECKO_PRO_API_KEY=...
```

Or pass via the constructor:

```python
CoinGeckoPandas(api_key="demo-key")
CoinGeckoPandas(pro_api_key="pro-key")
```

The Pro key takes precedence and switches the base URL to `https://pro-api.coingecko.com/api/v3/`. The client reads env vars in `__post_init__`, so as long as `.env` is loaded before instantiation, you don't need to pass anything explicitly.

## Endpoints

All 41 CoinGecko Demo API endpoints are exposed across 14 mixin classes (one per OpenAPI tag):

| Mixin | Methods |
|---|---|
| `PingMixin` | `ping_server` |
| `SimpleMixin` | `simple_price`, `simple_token_price`, `simple_supported_currencies` |
| `CoinsMixin` | `coins_list`, `coins_markets`, `coins_id`, `coins_id_tickers`, `coins_id_history`, `coins_id_market_chart`, `coins_id_market_chart_range`, `coins_id_ohlc` |
| `ContractMixin` | `coins_contract_address`, `contract_address_market_chart`, `contract_address_market_chart_range` |
| `AssetPlatformsMixin` | `asset_platforms_list`, `token_lists` |
| `CategoriesMixin` | `coins_categories_list`, `coins_categories` |
| `ExchangesMixin` | `exchanges`, `exchanges_list`, `exchanges_id`, `exchanges_id_tickers`, `exchanges_id_volume_chart` |
| `DerivativesMixin` | `derivatives_tickers`, `derivatives_exchanges`, `derivatives_exchanges_list`, `derivatives_exchanges_id` |
| `NFTsMixin` | `nfts_list`, `nfts_id`, `nfts_contract_address` |
| `ExchangeRatesMixin` | `exchange_rates` |
| `SearchMixin` | `search_data` |
| `TrendingMixin` | `trending_search` |
| `GlobalMixin` | `crypto_global`, `global_defi` |
| `PublicTreasuryMixin` | `entities_list`, `public_treasury_entity`, `public_treasury_transaction_history`, `public_treasury_entity_chart`, `companies_public_treasury` |

## WebSockets (Pro tier)

CoinGecko publishes 4 channels (Pro only):

| Method | Channel | Code |
|---|---|---|
| `subscribe_simple_price` | CGSimplePrice | C1 |
| `subscribe_onchain_token_price` | OnchainSimpleTokenPrice | G1 |
| `subscribe_onchain_trade` | OnchainTrade | G2 |
| `subscribe_onchain_ohlcv` | OnchainOHLCV | G3 |

```python
from coingecko_pandas import CoinGeckoPandas, CoinGeckoWebSocket

client = CoinGeckoPandas(pro_api_key="...")
ws = CoinGeckoWebSocket.from_client(client)

with ws.subscribe_simple_price(coins=["bitcoin"]) as session:
    ...
```

> The exact WebSocket connection URL and subscribe payload format are not in the public docs at the time of generation. Verify against the CoinGecko Pro dashboard before relying on this in production.

## Error handling

```python
from coingecko_pandas import (
    CoinGeckoAPIError,
    CoinGeckoAuthError,
    CoinGeckoRateLimitError,
)

try:
    df = client.coins_markets("usd")
except CoinGeckoAuthError:
    ...
except CoinGeckoRateLimitError:
    ...
except CoinGeckoAPIError as e:
    print(e.status_code, e.url, e.detail)
```

## Development

```bash
uv pip install -e ".[dev]"
uv run pytest tests/test_unit.py tests/test_async_unit.py -v
uv run ruff check coingecko_pandas
uv run mypy coingecko_pandas
```

CI runs the same checks on every push and PR via `.github/workflows/ci.yml` across Python 3.11, 3.12, and 3.13.

To run the live integration tests:

```bash
PYTEST_LIVE=1 uv run pytest tests/test_integration.py -v
```

## Releasing

Releases are cut by pushing a `v*` tag. `.github/workflows/release.yml` then:

1. **Runs the test job first** — ruff + mypy + pytest. If this fails, the build, publish, and release jobs are all skipped automatically. A red test prevents the deploy.
2. Builds sdist + wheel via `uv build`
3. Publishes to PyPI via [trusted publishing](https://docs.pypi.org/trusted-publishers/) (OIDC, no API token in secrets)
4. Creates a GitHub release with the built artifacts attached

**One-time setup** (before the first release):

1. Reserve the `coingecko-pandas` name on PyPI.
2. Visit `https://pypi.org/manage/account/publishing/` and add a pending publisher:
   - PyPI project name: `coingecko-pandas`
   - Owner: `sigma-quantiphi`
   - Repository: `coingecko-pandas`
   - Workflow: `release.yml`
   - Environment: `pypi`
3. In the GitHub repo settings, create an `Environment` named `pypi`.
4. Add `COINGECKO_DEMO_API_KEY` to the **same `pypi` environment** (Settings → Environments → pypi → Environment secrets, **not** repository secrets). Both the `test` and `publish-pypi` jobs run inside the `pypi` environment, so the secret is visible to both. The release workflow's test job runs `PYTEST_LIVE=1 pytest tests/test_integration.py` against the real CoinGecko API, and this secret is how it authenticates. **No release can publish until the live tests are green.**

**To cut a release:**

```bash
# 1. Move [Unreleased] entries under a new version header in CHANGELOG.md
# 2. Bump version in pyproject.toml
# 3. Commit, tag, push
git commit -am "Release v0.1.1"
git tag v0.1.1
git push origin main --tags
```

**To force a release when the test job is broken (not the code):**

Use the `workflow_dispatch` escape hatch:

```bash
gh workflow run release.yml -f tag=v0.1.1 -f skip_tests=true
```

Or via the GitHub UI: **Actions → Release → Run workflow**, fill in `tag` and tick `skip_tests`. This skips the test job and runs build → publish → release directly. Use sparingly — it exists only for cases where the test infrastructure itself is broken (CI runner outage, transient package-index failure, etc.), not as a way to merge red code.

## Generated by

This package was scaffolded by the [api-pandas](https://github.com/sigma-quantiphi/claude-skills/tree/main/api-pandas) Claude Code skill from the official CoinGecko OpenAPI spec.

## License

Apache-2.0
