Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

📈 IG trading

PyPI Python Version CI

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. AsyncClient is built on aiohttp and Client on requests, 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)

Source distribution for ig-trading 1.0.0b2
File Size Uploaded
ig_trading-1.0.0b2.tar.gz 35.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ig-trading 1.0.0b2
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

1.0.0b2 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page