Metadata-Version: 2.4
Name: stonepy
Version: 0.3.0
Summary: Python client for the StoneX (CIAPI) v2 trading API
Project-URL: Homepage, https://github.com/aaronmgn/stonepy
Project-URL: Repository, https://github.com/aaronmgn/stonepy
Project-URL: Documentation, https://aaronmgn.github.io/stonepy/
Project-URL: Issues, https://github.com/aaronmgn/stonepy/issues
Project-URL: Changelog, https://github.com/aaronmgn/stonepy/blob/main/CHANGELOG.md
Author-email: Aaron Morgan <aaron@dvops.io>
License-Expression: MIT
License-File: LICENSE
Keywords: ciapi,cityindex,stonex,trading
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: httpx<1.0,>=0.27
Requires-Dist: pydantic<3.0,>=2.7
Requires-Dist: simplejson<4.0,>=3.19
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pre-commit>=3.7; extra == 'dev'
Requires-Dist: pytest-cov>=5; extra == 'dev'
Requires-Dist: pytest>=9.1.1; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff>=0.15.20; extra == 'dev'
Requires-Dist: twine>=5; extra == 'dev'
Requires-Dist: types-simplejson; extra == 'dev'
Requires-Dist: unasync>=0.6; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mike>=2.1; extra == 'docs'
Requires-Dist: mkdocs-gen-files<0.7,>=0.5; extra == 'docs'
Requires-Dist: mkdocs-literate-nav<0.6.4,>=0.6; extra == 'docs'
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.27; extra == 'docs'
Requires-Dist: ruff>=0.5; extra == 'docs'
Description-Content-Type: text/markdown

# stonepy

[![PyPI version](https://img.shields.io/pypi/v/stonepy.svg)](https://pypi.org/project/stonepy/)
[![Python versions](https://img.shields.io/pypi/pyversions/stonepy.svg)](https://pypi.org/project/stonepy/)
[![CI](https://github.com/aaronmgn/stonepy/actions/workflows/ci.yml/badge.svg)](https://github.com/aaronmgn/stonepy/actions/workflows/ci.yml)
[![Docs](https://img.shields.io/badge/docs-online-blue.svg)](https://aaronmgn.github.io/stonepy/)
[![License: MIT](https://img.shields.io/badge/license-MIT-yellow.svg)](https://github.com/aaronmgn/stonepy/blob/main/LICENSE)

Python client for the StoneX (CIAPI) v2 trading API.

📖 **Documentation:** <https://aaronmgn.github.io/stonepy/>

## Features

- **Fully typed.** Every request and response is a [Pydantic](https://docs.pydantic.dev/) v2
  model, and the package ships a `py.typed` marker, so editors autocomplete fields and `mypy`
  checks your calls.
- **Sync and async.** Identical APIs on `StoneXClient` and `AsyncStoneXClient`.
- **Complete coverage.** All 128 documented CIAPI endpoints across 19 resource groups, using the
  v2 variant of every endpoint that has one.
- **Batteries included.** Automatic session refresh, configurable retries, client-side rate
  limiting, secret redaction in logs, and a clear exception hierarchy.

> **Project status:** `stonepy` is pre-1.0 (alpha). The public API may change between minor
> releases until 1.0; pin a version for production use.

## Installation

```bash
pip install stonepy
```

Or with [uv](https://docs.astral.sh/uv/):

```bash
uv add stonepy
```

Requires Python >= 3.11. `stonepy` ships type information (PEP 561 `py.typed`), so it works out
of the box with `mypy` and `pyright`.

## Quickstart

```python
from stonepy import ClientConfig, StoneXClient
from stonepy.models import ApiLogOnRequestDTO

config = ClientConfig(base_url="https://ciapi.cityindex.com/TradingAPI")

with StoneXClient(config) as client:
    session = client.session.log_on(
        ApiLogOnRequestDTO(
            UserName="username",
            Password="password",
            AppKey="app-key",
            AppVersion="stonepy",
            AppComments="",
        )
    )
    print(session.status_code)
```

Environment-based configuration is also available:

```python
from stonepy import ClientConfig, StoneXClient

config = ClientConfig.from_env()

with StoneXClient(config) as client:
    print(client.session)
```

`ClientConfig.from_env()` reads `STONEX_BASE_URL`, `STONEX_APP_KEY`, `STONEX_USERNAME`,
and `STONEX_PASSWORD`. `STONEX_BASE_URL` is required unless `base_url=` is passed.

## Authentication and Sessions

Calling `client.session.log_on(...)` establishes the authenticated session token that the
client attaches to every subsequent request. The token is held by the client for the life of
its context manager.

If you supply `app_key`, `username`, and `password` on `ClientConfig` (directly or via
`ClientConfig.from_env()`), the client also refreshes the session automatically: it
re-authenticates in the background before the token expires, controlled by
`ClientConfig.proactive_refresh_seconds` (default `1080.0`, i.e. 18 minutes), and transparently
re-logs-on if a request is rejected with an expired-session error. Without those credentials you
must call `log_on` yourself and manage re-authentication.

```python
config = ClientConfig(
    base_url="https://ciapi.cityindex.com/TradingAPI",
    app_key="app-key",
    username="username",
    password="password",
)  # credentials present -> automatic proactive session refresh
```

## Async Usage

```python
from stonepy import AsyncStoneXClient, ClientConfig
from stonepy.models import ApiLogOnRequestDTO

config = ClientConfig(base_url="https://ciapi.cityindex.com/TradingAPI")

async with AsyncStoneXClient(config) as client:
    session = await client.session.log_on(
        ApiLogOnRequestDTO(
            UserName="username",
            Password="password",
            AppKey="app-key",
            AppVersion="stonepy",
            AppComments="",
        )
    )
    print(session.status_code)
```

Use `aclose()` for async clients when not using `async with`; use `close()` for sync clients.

## Error Handling

All library exceptions inherit from `StoneXError`.

```python
from stonepy import (
    ClientConfig,
    RateLimitError,
    StoneXAPIError,
    StoneXClient,
    StoneXError,
)
from stonepy.models import ApiLogOnRequestDTO

config = ClientConfig(base_url="https://ciapi.cityindex.com/TradingAPI")

try:
    with StoneXClient(config) as client:
        client.session.log_on(
            ApiLogOnRequestDTO(
                UserName="username",
                Password="password",
                AppKey="app-key",
                AppVersion="stonepy",
                AppComments="",
            )
        )
except RateLimitError as exc:
    print(exc.retry_after)
except StoneXAPIError as exc:
    print(exc.http_status, exc.error_code, exc.error_message)
except StoneXError as exc:
    print(exc)
```

Important subclasses include `AuthenticationError`, `RateLimitError`,
`OrderRejectedError`, `OrderStatusUnknownError`, `ResponseParseError`, `StoneXAPIError`, and
`TransportError`.

## Pagination

Paginated API methods return the page DTO documented by StoneX. For example,
`client.market.list_market_search_paginated(...)` accepts `page`, `page_size`, and
`order_by` keyword arguments and returns `ListMarketSearchPaginatedResponseDTO`:

```python
page = client.market.list_market_search_paginated(
    "gold",
    search_by_market_code=False,
    search_by_market_name=True,
    spread_product_type=True,
    cfd_product_type=True,
    binary_product_type=False,
    ascending_order=True,
    include_options=False,
    client_account_id=12345,
    page=0,
    page_size=100,
)
print(page.total_number_of_results)
```

## API Reference

Full documentation - the guides and a complete API reference - is published at
<https://aaronmgn.github.io/stonepy/>.

## Development

```bash
uv venv
uv sync --extra dev
uv run pytest -q
uv run ruff check .
uv run ruff format --check .
uv run mypy
```

See [CONTRIBUTING.md](CONTRIBUTING.md) for the full contributor guide and
[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md), and [CHANGELOG.md](CHANGELOG.md) for release notes.

## Support

- Questions and bug reports: [GitHub issues](https://github.com/aaronmgn/stonepy/issues).
- Security: please report vulnerabilities privately - see [SECURITY.md](SECURITY.md).

## AI Use Disclaimer

Portions of this project, including the generated API bindings, DTO models, and documentation,
were produced with the assistance of AI tooling and reviewed by a human maintainer. The library
is tested against the StoneX CIAPI v2 contract but is provided "as is", without warranty of any
kind (see [LICENSE](LICENSE)).

`stonepy` is **unofficial** and is not affiliated with, endorsed by, or supported by StoneX,
City Index, or GAIN Capital. Trading carries financial risk; validate all behaviour against the
[official API documentation](https://docs.labs.gaincapital.com/) before using it with a live
account.
