This release is a pre-release and may not be stable for production use.
📈 IG trading
A fully-typed Python client for IG's trading REST API, with both an async and a sync API.
🚀 Usage
import asyncio
import ig_trading as ig
async def main() -> None:
async with ig.AsyncClient() as client:
# Credentials default to the IG_API_KEY, IG_IDENTIFIER and IG_PASSWORD
# environment variables if not passed explicitly.
positions = await client.positions.list()
for position in positions:
print(position.position.deal_id, position.market.epic)
deal_reference = await client.positions.otc.create(
currency_code="GBP",
direction="BUY",
epic="CS.D.EURGBP.CFD.IP",
expiry="-",
force_open=True,
guaranteed_stop=False,
order_type="MARKET",
size=1,
)
print((await client.confirms.get(deal_reference)).reason)
asyncio.run(main())
ig.Client is the sync equivalent (built on
requests instead of
aiohttp), with the same API minus await:
import ig_trading as ig
def main() -> None:
with ig.Client() as client:
positions = client.positions.list()
for position in positions:
print(position.position.deal_id, position.market.epic)
deal_reference = client.positions.otc.create(
currency_code="GBP",
direction="BUY",
epic="CS.D.EURGBP.CFD.IP",
expiry="-",
force_open=True,
guaranteed_stop=False,
order_type="MARKET",
size=1,
)
print(client.confirms.get(deal_reference).reason)
main()
Every Async-prefixed class (AsyncClient, AsyncAccountsResource, ...) has a
sync counterpart with the same name minus the prefix (Client,
AccountsResource, ...) and an identical API.
Each resource on client (accounts, application, categories,
client_sentiment, confirms, history, markets, positions, prices,
session, watchlists, working_orders) can also be used standalone with your
own aiohttp.ClientSession/requests.Session, e.g. for testing or for
composing your own login flow:
async with ig.AsyncSession() as http_session:
requester = ig.AsyncAPIRequester(http_session=http_session, key="...")
session = ig.AsyncSessionResource(requester)
account = await session.create(identifier="...", password="...")
with ig.Session() as http_session:
requester = ig.APIRequester(http_session=http_session, key="...")
session = ig.SessionResource(requester)
account = session.create(identifier="...", password="...")
🔑 Environment variables
| Variable | Description |
|---|---|
IG_API_KEY |
API key |
IG_IDENTIFIER |
Username |
IG_PASSWORD |
Password |
These can be set directly or via a .env file in the working directory.
💡 Why
The existing IG API clients on PyPI/GitHub are, for the most part, only
partially typed and expose the API as a flat grab-bag of methods. This project
exists because none of the popular, actively-maintained alternatives (e.g.
trading-ig, the most widely used
one) offer all of the following together:
- Fully typed. Every request and response is a
pydantic model, so responses are validated at
the boundary and you get real autocomplete/type-checking instead of dicts of
Any. - Async and sync.
AsyncClientis built onaiohttpandClientonrequests, each with a background task/thread that automatically refreshes the OAuth token before it expires, so you don't have to babysit sessions. - Clean, resource-oriented usage. The client is organised as typed
sub-resources that mirror the shape of the API itself (
client.positions,client.markets,client.working_orders, ...) rather than one flat object with dozens of loosely related methods bolted on.
A couple of other things fell out of that design along the way:
- The library mirrors IG's own API versioning (
v1,v2,v3, ...) with a matching submodule for each version, so it's clear exactly which version of an endpoint/model you're using. - Errors are typed too: IG's error codes are mapped to specific exception
classes (e.g.
ExceededAPIKeyAllowanceError,OAuthTokenInvalidError) instead of a single generic HTTP error.
🛠️ Development
The dev environment is a Docker container with everything needed (uv, Python,
Vim, Claude Code) pre-installed. Start it with:
docker compose run --build --interactive --remove-orphans --rm vim
This mounts the repo into the container and drops you into a shell with the
.venv already synced (uv sync has run as part of the image build).
From there:
# Run the test suite. Tests hit IG's real demo API (no mocking), so this
# needs IG_API_KEY, IG_IDENTIFIER and IG_PASSWORD set, e.g. via .env.
uv run pytest
# Lint and type-check.
uv run ruff check
uv run mypy .
# Build the docs; output goes to docs/_build/html.
uv run sphinx-build docs public
If you don't want to use the container, the same commands work locally as long
as you have uv installed — just run uv sync first.
Release files for ig-trading 1.0.0b2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ig_trading-1.0.0b2.tar.gz | 35.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ig_trading-1.0.0b2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 98.7 kB
Release files / ig_trading-1.0.0b2.tar.gz
| Download URL | ig_trading-1.0.0b2.tar.gz |
|---|---|
| Size | 35.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fdb6583254de16e8a5bc2b69d9aee4c8e3b40b5feb87146755c400d428dee988
|
|
BLAKE2b-256 checksum How to use checksums |
7d395d6ff714118a62d05f26f354151d77ecd125d31715910af5762735f06431
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.
Transparency logRelease files / ig_trading-1.0.0b2-py3-none-any.whl
| Download URL | ig_trading-1.0.0b2-py3-none-any.whl |
|---|---|
| Size | 63.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c728eaa881a1d769ff968eaa5f7a6bf6f848b5922fedd34b9bdddc41040c45c0
|
|
BLAKE2b-256 checksum How to use checksums |
fabb711d60248c3805d1d142cf50b5d7741c7c8d1035487ae899dcf2a50d67bf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.
Transparency log