iqair
An unofficial Python wrapper for IQ Option's websocket trading API.
This is v1.0 - a ground-up rebuild of an older, long-unmaintained
iqoptionapi fork. Every endpoint listed as "implemented" below has been
independently re-verified against the live backend (never assumed from
old code or documentation), typically by capturing real trade traffic
from IQ Option's own web UI (HAR capture) and matching this library's
requests against it byte-for-byte. Where something is confirmed vs.
presumed, the docstring on the relevant method says so explicitly - see
iqair/broker.py's module docstring for the full picture.
This talks to a real trading account. Every example below and every
test in tests/ runs against the PRACTICE balance only - never REAL. Use
your own judgment before pointing this at anything else.
Install
pip install -e .
Requires Python 3 and requests, websocket-client (see setup.py).
Quickstart
from iqair.client import IQOptionClient
api = IQOptionClient("you@example.com", "your-password")
check, reason = api.connect()
if not check:
raise SystemExit(f"connect failed: {reason}")
api.change_balance("PRACTICE")
# Low-level: place a turbo option directly
check, order_id = api.buy(1, "EURUSD", "call", 1) # $1, 1-minute turbo
The OOP wrapper (api.broker)
For most use cases, api.broker is friendlier than the low-level
per-mode methods - one trade()/.close() interface across every mode:
from iqair.broker import TradeMode, TradeSide
trade = api.broker.trade(
mode=TradeMode.TURBO,
asset="EURUSD",
side=TradeSide.CALL,
amount=1,
expiration=1,
)
trade.wait() # blocks until the trade settles
print(trade.pnl)
# Margin modes (forex/crypto/cfd) need `leverage`; `amount` is margin,
# not stake, for these:
trade = api.broker.trade(
mode=TradeMode.FOREX,
asset="EURUSD",
side=TradeSide.BUY,
amount=10, # margin, in dollars
leverage=100,
)
print(trade.state, trade.pnl)
trade.close()
For the full end-to-end guide (every mode, streaming, positions/P&L,
error handling), see docs/USAGE.md. For finding valid
ticker strings specifically, see docs/TICKERS.md -
the short version is api.get_asset_metadata().
Using this with an LLM orchestrator / agent
iqair.agent wraps the library as flat JSON-in/JSON-out tools for
LLM function-calling (direct import, a generic call_tool(name, args)
dispatcher, or an optional HTTP server via pip install iqair[agent]).
See docs/AGENT.md.
Supported trading modes
| Mode | Open | Close | Notes |
|---|---|---|---|
| Turbo / Binary | ✅ live-verified | ✅ live-verified | api.buy() / api.sell_option() |
| Digital options | ✅ live-verified | ✅ live-verified | api.buy_digital_spot() / api.close_digital_option() - resolves a real, currently-tradable instrument server-side rather than constructing one client-side |
| Forex (margin) | ✅ live-verified | ✅ live-verified | api.buy_forex_market() / api.close_margin_position() |
| Crypto (margin) | ✅ live-verified | ✅ live-verified | api.buy_crypto_market() |
| CFD (margin) | ✅ live-verified | ✅ live-verified | api.buy_cfd_market() - covers commodities, stocks, indices, AND ETFs; IQ Option has no separate mode for any of these, they're all marginal-cfd |
All six are also available through api.broker.trade(mode=TradeMode.*, ...).
The old buy_order() / close_position() / close_position_v2()
methods are confirmed dead (they send flat, non-namespaced message
names IQ Option's backend no longer responds to at all) and are kept
only for backwards compatibility - they emit a DeprecationWarning.
Use the methods in the table above instead.
Streaming (api.stream)
for candle in api.stream.candles("EURUSD", timeframe=60):
print(candle)
for tick in api.stream.price("EURUSD"):
print(tick.bid, tick.ask)
for update in api.stream.trade_updates(): # all position-changed events
print(update)
for event in api.stream.connection(): # connection state changes
print(event)
api.stream.payout() and api.stream.asset_status() are poll-based
(IQ Option doesn't push these two live) rather than true push streams;
api.stream.news() is a documented stub - a live news feed wasn't
captured/confirmed during this project.
Every stream returns a Subscription - iterate it directly, or call
.close() to unsubscribe early.
Positions, history, P&L
ok, positions = api.get_positions("digital-option") # or "turbo-option", "marginal-forex", etc.
ok, history = api.get_position_history_v2("marginal-cfd", limit=10, offset=0)
pnl = api.get_pnl(positions["positions"][0]) # takes a raw position dict
Matching a position back to the order id that opened it is not always a
plain equality check - digital and margin positions key external_id as
the position id, not the order id (order ids live in a separate list).
Use IQOptionClient.position_matches_order_id() rather than comparing
external_id directly if you're writing your own matching logic;
get_digital_position() / get_margin_position() / Trade.refresh()
already do this correctly.
Testing
See tests/README.md for the full test suite - it
runs against the real backend (PRACTICE balance), gated behind
IQ_EMAIL/IQ_PASSWORD and opt-in flags (IQ_ALLOW_TRADE,
IQ_ALLOW_DIGITAL, IQ_ALLOW_MARGIN) for anything that places a trade.
export IQ_EMAIL="you@example.com"
export IQ_PASSWORD="your-password"
pytest # read-only tests
IQ_ALLOW_TRADE=1 IQ_ALLOW_DIGITAL=1 IQ_ALLOW_MARGIN=1 pytest # everything
Project layout
iqair/
client.py high-level client (IQOptionClient) - most users start here
broker.py OOP wrapper (api.broker) - Trade/TradeMode/TradeSide
streaming.py api.stream namespace
api.py low-level request/response plumbing
models.py typed dataclasses (Position, Candle, etc.)
ws/ websocket client + per-endpoint request builders
agent/ LLM tool-calling / orchestrator integration (tools, dispatcher, HTTP server)
docs/
USAGE.md full end-to-end usage guide
AGENT.md orchestrator / LLM tool-calling integration guide
TICKERS.md how to find valid ticker strings per trading mode
tests/ live-backend test suite (see tests/README.md)
Disclaimer
This is an unofficial, community-maintained wrapper, not affiliated with or endorsed by IQ Option. IQ Option's API is undocumented and can change without notice - endpoints that work today may not tomorrow. Use at your own risk, and always test against the PRACTICE balance before trusting anything with real funds.
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 iqair-1.0.0.tar.gz.
File metadata
- Download URL: iqair-1.0.0.tar.gz
- Upload date:
- Size: 88.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
001237669577e35ca8c413d236556b29e06122048f81e6675bab03c65d007406
|
|
| MD5 |
2a5cb67f21f8b8e4b5cb88f7d2c486e6
|
|
| BLAKE2b-256 |
8edc9c709f7258eee0f2dc136d14ae5d33ed76096fe02c22acddeb6eeb264462
|
Provenance
The following attestation bundles were made for iqair-1.0.0.tar.gz:
Publisher:
publish.yml on Omerhrr/iqair
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
iqair-1.0.0.tar.gz -
Subject digest:
001237669577e35ca8c413d236556b29e06122048f81e6675bab03c65d007406 - Sigstore transparency entry: 2341301709
- Sigstore integration time:
-
Permalink:
Omerhrr/iqair@65c1b86341eabb390ccbe7b72466dcf11d878640 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/Omerhrr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@65c1b86341eabb390ccbe7b72466dcf11d878640 -
Trigger Event:
release
-
Statement type:
File details
Details for the file iqair-1.0.0-py3-none-any.whl.
File metadata
- Download URL: iqair-1.0.0-py3-none-any.whl
- Upload date:
- Size: 98.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b0ec8aebfd8b6a6b9880b1fe896786b6545d050e82d4b19aaa123611c961e50d
|
|
| MD5 |
ce631dbb06939ed637f2e5908aa14d75
|
|
| BLAKE2b-256 |
e3be015611fa5d9c35aae0b21234fac8540e594bf455ea5c663dc69e79ff7221
|
Provenance
The following attestation bundles were made for iqair-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on Omerhrr/iqair
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
iqair-1.0.0-py3-none-any.whl -
Subject digest:
b0ec8aebfd8b6a6b9880b1fe896786b6545d050e82d4b19aaa123611c961e50d - Sigstore transparency entry: 2341301728
- Sigstore integration time:
-
Permalink:
Omerhrr/iqair@65c1b86341eabb390ccbe7b72466dcf11d878640 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/Omerhrr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@65c1b86341eabb390ccbe7b72466dcf11d878640 -
Trigger Event:
release
-
Statement type: