Metadata-Version: 2.4
Name: aiomoexalgo
Version: 1.0.1
Summary: API client for api.moex and iss.moex
Author-email: Pavel Volkov <paul.volkov@proton.me>
License-Expression: MIT
Project-URL: Homepage, https://github.com/complicat9d/aiomoexalgo
Project-URL: Issues, https://github.com/complicat9d/aiomoexalgo/issues
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: niquests[speedups,ws]>=3.20.1
Requires-Dist: pydantic>=2.13.4
Requires-Dist: stomp-py>=9.0.0
Dynamic: license-file

# aiomoexalgo

[![PyPI version](https://img.shields.io/pypi/v/aiomoexalgo.svg)](https://pypi.org/project/aiomoexalgo/)
![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue)

[Документация на русском](README_RU.md)

Library supporting sync/async clients, websockets for [Moexalgo](https://moexalgo.github.io/).

## Problems Addressed by the Library

* Addition of async clients and websockets;
* Pydantic type validation of API responses;
* Static typing of API responses, enabling LSP type hinting;
* Single point of truth for MOEX APIs documentation, in-code doc-strings directly referencing respective resources;
* Technology availability: this project is licensed under MIT license, providing an open source alternative which does not require a user to reimburse the authors of the project in any way.

## Documentation

The documentation for APIs can be found on:

* Moexalgo (Algopack): [moexalgo.github.io](https://moexalgo.github.io/)
* ISS MOEX API: [moex.com](https://www.moex.com/a2193)
* ISS MOEX API Reference: [iss.moex.com](https://iss.moex.com/iss/reference/?lang=en)
* ISS MOEX Developer Manual: [fs.moex.com](https://fs.moex.com/files/6523)
* ISS MOEX Informational Product (Subscriptions via [passport.moex.com](https://passport.moex.com), Data Descriptions): [moex.com](https://www.moex.com/ru/orders?realtime)


## Installation

```shell
# install from PyPI
pip install aiomoexalgo
```

## Usage

The primary API for interacting with Moexalgo is [here](https://moexalgo.github.io/). You can get all necessary information about securities for stock, forex, futures markets and derived features specified in the documentation.

```python
import os
from aiomoexalgo import MOEXClient
from aiomoexalgo.types import ISSMarket


client = MOEXClient(
    api_token=os.environ.get("MOEX_API_TOKEN")
)
response = client.get_rt_market_data("SBER", ISSMarket.STOCK)

print(response["marketdata"][0]["OPEN"])
```

## Async Usage

Simply import async flavour of `MOEXClient` or `WebSocket` and use `await` for each API call:

```python
import os
import asyncio
from aiomoexalgo import AsyncMOEXClient
from aiomoexalgo.types import ISSMarket


async def main():
    client = AsyncMOEXClient(
        api_token=os.environ.get("MOEX_API_TOKEN")
    )
    response = await client.get_rt_market_data("SBER", ISSMarket.STOCK)

    print(response["marketdata"][0]["OPEN"])

asyncio.run(main())
```

## Using Types

All returned objects from clients are TypedDict-typed, what provides static typing and enables LSP type hints. Also, that means the data provided "as-is" without any modifications on the side of the API wrapper with minimal performance costs, and user is free to make modifications (pydantic models, pandas.DataFrame, etc.) with the retrieved object.

**Important note:** no MOEX API documentations explicitly state the methods' response types, especially optional fields, which may cause `pydantic.ValidationError`. If that happens, please [file an issue](https://complicat9d/aiomoexalgo/issues) detailing the type, the field and the value which caused the error. In the meantime, you can set `validate_return` to `False`.

## API Documentations Specifics

This is the part devoted to the specifics of MOEX APIs which are not explicitly stated in the documentations:

* iss.moex.com and apim.moex.com are backwards compatible and share common query params, however, not all of them work. You can check them [here (page 4-5)](https://fs.moex.com/files/6523).
* MOEX APIs do not accept a `Content-Type` header, instead they use file extensions at the end of an endpoint. Available extensions: `.xml`, `.json`. If the extension is not specified, then the default is `.xml`.
* MOEX APIs do not provide correct status codes. What usually happens is that you are redirected to an HTML page stating that an error occurred with status 200.
* It is not possible to verify the validity of an API token. If the token is invalid, you are redirected to an HTML page stating that you need to update it with status 200.

**Note**: if you have passed an invalid token, any method requiring it will fail, and it is not possible to consistently avoid this behaviour on the client side, since there is no status code policy or explicit documentation for error types.

## Engineering Decisions

* `niquests` is used for the client library. `requests` is low performant and currently feature-frozen; `aiohttp` is the fastest python client lib, but recent `niquests` benchmarks give better results than it, and `aiohttp` only supports async clients, whereas `niquests` supports both; `httpx` is rather unstable with the drama involved with the creator and people in the community going as far as forking and maintaining their own forks (e.g [httpx2](https://github.com/pydantic/httpx2), [httpxyz](https://codeberg.org/httpxyz/httpxyz)).
* Query params: `iss.meta=off`, `iss.json=extended`. Metadata placement varies across different `iss.json` responses, which makes it hard to type and later handle these types. Moreover, `iss.json=compact` (orient=split) requires manually transforming the data to be key-value paired, whereas `iss.json=extended` (orient=record) already does this despite the increased size of the data transmitted over the network.

## Requirements

Python 3.12 or higher.

## Contributing

See the [contributing documentation](CONTRIBUTING.md).
