Safe, typed synchronous and asynchronous clients for IG Trading APIs
Project description
IG Trading Library v3
Safe, typed synchronous and asynchronous IG REST and streaming clients.
Install
pip install ig-trading-lib
Python 3.11–3.13 is supported.
Start safely
Use a demo account while building an agent. Credentials are explicit, immutable objects and are redacted from representations and error diagnostics.
from ig_trading_lib import Environment, IGClient, IGConfig, SessionCredentials
config = IGConfig(
environment=Environment.DEMO,
credentials=SessionCredentials(
api_key="…",
identifier="…",
password="…",
),
)
with IGClient(config) as client:
markets = client.markets.search("EURUSD")
for market in markets.items:
print(market.epic, market.market_status)
The synchronous and asynchronous clients expose matching service namespaces:
| Sync | Async |
|---|---|
IGClient(config) |
AsyncIGClient(config) |
client.markets.search("EURUSD") |
await client.markets.search("EURUSD") |
client.positions.list() |
await client.positions.list() |
client.positions.create(...) |
await client.positions.create(...) |
from ig_trading_lib import AsyncIGClient
async with AsyncIGClient(config) as client:
accounts = await client.accounts.list()
print(accounts.items)
Live-trading boundary
Guarded live mutations require an explicit permit in addition to Environment.LIVE. A missing permit fails before authentication or network I/O.
from ig_trading_lib import Environment, IGClient, IGConfig, TradingPermit
live_config = IGConfig(environment=Environment.LIVE, credentials=config.credentials)
client = IGClient(live_config, trading_permit=TradingPermit())
# Position create, update, and close operations are guarded.
client.positions.create({"epic": "CS.D.EURUSD.TODAY.IP", "direction": "BUY", "size": "1"})
The guarded typed surfaces are positions.create, positions.update, positions.close, accounts.update_preferences, and mutation methods on watchlists, working_orders, costs, and applications. ResourceClient instances without a guard are not covered by this boundary.
Do not retry a failed mutation yourself. The client raises AmbiguousExecutionError when a network failure means IG may have accepted it; resolve that outcome with the deal reference or a confirmation before issuing another order.
REST services
Canonical services normalise provider keys to snake_case and paginate with Page plus lazy iter_pages / async iter_pages methods.
with IGClient(config) as client:
for activity in client.activity.iter_pages(item_key="activities"):
print(activity)
position = client.positions.get("DEAL_ID")
confirmation = client.confirms.get("/DEAL_REFERENCE")
The endpoint catalog is maintained in ig_trading_lib.endpoint_catalog and contract-tested against the maintained DOCUMENTED_ENDPOINTS catalog.
Streaming
Streaming is lazy: no Lightstreamer session is opened until iteration begins. IG requires CST/XST security tokens even for OAuth users; the client obtains them when needed, preserves subscriptions during SDK recovery, and exposes terminal stream errors instead of silently dropping data.
from ig_trading_lib import StreamSubscription
subscription = StreamSubscription(
key="eurusd",
mode="MERGE",
items=("MARKET:CS.D.EURUSD.TODAY.IP",),
fields=("BID", "OFFER", "UPDATE_TIME"),
)
with IGClient(config) as client:
updates = client.streaming.iter_updates(subscription)
try:
for update in updates:
print(update.item_name, update.changed_fields)
finally:
updates.close()
async with AsyncIGClient(config) as client:
async for update in client.streaming.aiter_updates(subscription):
print(update.changed_fields)
Errors and observability
Operational failures derive from IGError. Errors carry a safe provider request ID, a client operation ID, retry timing when supplied by IG, and redacted details. LiveTradingPermissionError is a separate PermissionError raised by the live-mutation guard.
from ig_trading_lib import AmbiguousExecutionError, RateLimitError, TransportError
try:
client.markets.search("EURUSD")
except RateLimitError as error:
print(error.retry_after_seconds)
except TransportError as error:
print(error.operation_id)
except AmbiguousExecutionError as error:
print("Resolve the deal outcome before retrying", error.operation_id)
Successful requests emit ig.http.response through the ig_trading_lib.transport standard-library logger. The structured record includes method, path, status, retry count, provider request ID, and client operation ID; passwords and tokens are never logged.
Tests and development
poetry sync --with dev
poetry run pytest tests/unit/v3
poetry run ruff format --check src tests scripts examples
poetry run ruff check src tests scripts examples
poetry run pyright
poetry run python scripts/check_documentation_contract.py
poetry run mkdocs build --strict
poetry run playwright install chromium
poetry export --only main --without-hashes --output /tmp/ig-trading-lib-requirements.txt
poetry run pip-audit --strict --requirement /tmp/ig-trading-lib-requirements.txt
poetry build
The default test suite is deterministic and has no IG network dependency. Demo integration runs are deliberately separate and must be invoked only with explicit credentials and opt-in approval. Never store credentials in the repository.
Versioned releases
Documentation and packages are validated on pull requests, main, and develop, but those runs never publish release artifacts. Publishing is restricted to a pushed SemVer tag beginning with v.
| Tag | Published documentation | latest and root redirect |
|---|---|---|
v3.0.0 |
https://evgesha9400.github.io/ig-trading-lib/3.0.0/ |
Updated to 3.0.0 |
v3.1.0-rc.1 |
https://evgesha9400.github.io/ig-trading-lib/3.1.0-rc.1/ |
Unchanged |
Each versioned site is immutable: a tagged workflow rejects an existing version before mike deploys it. Publish a corrected release under a new SemVer tag instead of changing published documentation.
If a tagged run partially succeeds, maintainers may use the manual release_tag recovery input. The workflow verifies documentation provenance, retains existing immutable Pages content, skips existing PyPI artifacts only during explicit recovery, and completes the remaining release steps.
git tag -a v3.0.1 -m "Release v3.0.1"
git push origin v3.0.1
The tagged workflow publishes immutable documentation, uploads the validated package to PyPI, creates the GitHub Release record, and dispatches evgesha9400/evgesha9400.github.io's rebuild-library-pages.yml workflow. Configure PYPI_API_TOKEN for package publication and LIBRARY_PORTAL_DISPATCH_TOKEN for the portal hand-off.
Disclaimer
This project is not affiliated with IG. Trading involves material risk. Review IG’s REST reference, REST guide, and streaming guide before connecting an agent to an account.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ig_trading_lib-3.0.1.tar.gz.
File metadata
- Download URL: ig_trading_lib-3.0.1.tar.gz
- Upload date:
- Size: 21.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1cc99c34acd69055854f6dcc69e7d8255ff7d18b3a2c3c2d9595fbea37f1444e
|
|
| MD5 |
409751b4b0d3d6c554745b4aa4fbd407
|
|
| BLAKE2b-256 |
7a1a74b35b36129142da053db52f7a3fc2babf810f674cdaba4ccfad6d05b556
|
File details
Details for the file ig_trading_lib-3.0.1-py3-none-any.whl.
File metadata
- Download URL: ig_trading_lib-3.0.1-py3-none-any.whl
- Upload date:
- Size: 24.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
378ec7572347a5c7c8666e3a68013de882ed487872f70d28b430cd7ee27a4405
|
|
| MD5 |
d15bef5c263be4a45db76a2b9762f671
|
|
| BLAKE2b-256 |
521b16908937cd8de1f4f4893c70423c3883cb29111422e54fc1180543bd93d5
|