ig-trading 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ig_trading-0.1.0/PKG-INFO +136 -0
- ig_trading-0.1.0/README.md +119 -0
- ig_trading-0.1.0/pyproject.toml +112 -0
- ig_trading-0.1.0/pyproject.toml.orig +97 -0
- ig_trading-0.1.0/src/ig_trading/__init__.py +208 -0
- ig_trading-0.1.0/src/ig_trading/accounts/__init__.py +5 -0
- ig_trading-0.1.0/src/ig_trading/accounts/v1.py +17 -0
- ig_trading-0.1.0/src/ig_trading/application/__init__.py +5 -0
- ig_trading-0.1.0/src/ig_trading/application/v1.py +8 -0
- ig_trading-0.1.0/src/ig_trading/categories/__init__.py +5 -0
- ig_trading-0.1.0/src/ig_trading/categories/v1.py +17 -0
- ig_trading-0.1.0/src/ig_trading/client_sentiment/__init__.py +5 -0
- ig_trading-0.1.0/src/ig_trading/client_sentiment/v1.py +5 -0
- ig_trading-0.1.0/src/ig_trading/confirms/__init__.py +5 -0
- ig_trading-0.1.0/src/ig_trading/confirms/v1.py +19 -0
- ig_trading-0.1.0/src/ig_trading/env.py +9 -0
- ig_trading-0.1.0/src/ig_trading/history/__init__.py +5 -0
- ig_trading-0.1.0/src/ig_trading/history/v1.py +19 -0
- ig_trading-0.1.0/src/ig_trading/markets/__init__.py +12 -0
- ig_trading-0.1.0/src/ig_trading/markets/v1.py +41 -0
- ig_trading-0.1.0/src/ig_trading/markets/v4.py +23 -0
- ig_trading-0.1.0/src/ig_trading/positions/__init__.py +5 -0
- ig_trading-0.1.0/src/ig_trading/positions/v1.py +15 -0
- ig_trading-0.1.0/src/ig_trading/positions/v2.py +15 -0
- ig_trading-0.1.0/src/ig_trading/prices/__init__.py +10 -0
- ig_trading-0.1.0/src/ig_trading/prices/v1.py +17 -0
- ig_trading-0.1.0/src/ig_trading/prices/v3.py +18 -0
- ig_trading-0.1.0/src/ig_trading/py.typed +0 -0
- ig_trading-0.1.0/src/ig_trading/session/__init__.py +10 -0
- ig_trading-0.1.0/src/ig_trading/session/v1.py +19 -0
- ig_trading-0.1.0/src/ig_trading/session/v3.py +11 -0
- ig_trading-0.1.0/src/ig_trading/watchlists/__init__.py +5 -0
- ig_trading-0.1.0/src/ig_trading/watchlists/v1.py +19 -0
- ig_trading-0.1.0/src/ig_trading/working_orders/__init__.py +5 -0
- ig_trading-0.1.0/src/ig_trading/working_orders/v1.py +19 -0
- ig_trading-0.1.0/src/ig_trading/working_orders/v2.py +21 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: ig-trading
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: IG trading
|
|
5
|
+
Author: Nelson Yeung
|
|
6
|
+
Author-email: Nelson Yeung <nelsyeung@gmail.com>
|
|
7
|
+
Requires-Dist: aiohttp[speedups]>=3.14.3
|
|
8
|
+
Requires-Dist: pydantic>=2.13.5
|
|
9
|
+
Requires-Dist: python-dotenv>=1.2.3
|
|
10
|
+
Requires-Dist: typing-extensions>=4.16.0
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Project-URL: Changelog, https://github.com/nelsyeung/ig-trading/blob/main/CHANGELOG.md
|
|
13
|
+
Project-URL: Documentation, https://ig-trading.readthedocs.io
|
|
14
|
+
Project-URL: Issues, https://github.com/nelsyeung/ig-trading/issues
|
|
15
|
+
Project-URL: Repository, https://github.com/nelsyeung/ig-trading.git
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# 📈 IG trading
|
|
19
|
+
|
|
20
|
+
A fully-typed, async Python client for [IG](https://www.ig.com/)'s trading
|
|
21
|
+
REST API.
|
|
22
|
+
|
|
23
|
+
## 🚀 Usage
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
import asyncio
|
|
27
|
+
|
|
28
|
+
import ig_trading as ig
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
async def main() -> None:
|
|
32
|
+
async with ig.Client() as client:
|
|
33
|
+
# Credentials default to the IG_API_KEY, IG_IDENTIFIER and IG_PASSWORD
|
|
34
|
+
# environment variables if not passed explicitly.
|
|
35
|
+
positions = await client.positions.list()
|
|
36
|
+
for position in positions:
|
|
37
|
+
print(position.position.deal_id, position.market.epic)
|
|
38
|
+
|
|
39
|
+
deal_reference = await client.positions.otc.create(
|
|
40
|
+
currency_code="GBP",
|
|
41
|
+
direction="BUY",
|
|
42
|
+
epic="CS.D.EURGBP.CFD.IP",
|
|
43
|
+
expiry="-",
|
|
44
|
+
force_open=True,
|
|
45
|
+
guaranteed_stop=False,
|
|
46
|
+
order_type="MARKET",
|
|
47
|
+
size=1,
|
|
48
|
+
)
|
|
49
|
+
print((await client.confirms.get(deal_reference)).reason)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
asyncio.run(main())
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Each resource on `client` (`accounts`, `application`, `categories`,
|
|
56
|
+
`client_sentiment`, `confirms`, `history`, `markets`, `positions`, `prices`,
|
|
57
|
+
`session`, `watchlists`, `working_orders`) can also be used standalone with your
|
|
58
|
+
own `aiohttp.ClientSession`, e.g. for testing or for composing your own login
|
|
59
|
+
flow:
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
async with ig.ClientSession() as http_session:
|
|
63
|
+
requester = ig.APIRequester(http_session=http_session, key="...")
|
|
64
|
+
session = ig.SessionResource(requester)
|
|
65
|
+
account = await session.create(identifier="...", password="...")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 🔑 Environment variables
|
|
69
|
+
|
|
70
|
+
| Variable | Description |
|
|
71
|
+
| --------------- | ----------- |
|
|
72
|
+
| `IG_API_KEY` | API key |
|
|
73
|
+
| `IG_IDENTIFIER` | Username |
|
|
74
|
+
| `IG_PASSWORD` | Password |
|
|
75
|
+
|
|
76
|
+
These can be set directly or via a `.env` file in the working directory.
|
|
77
|
+
|
|
78
|
+
## 💡 Why
|
|
79
|
+
|
|
80
|
+
The existing IG API clients on PyPI/GitHub are, for the most part, sync (built
|
|
81
|
+
on [`requests`](https://requests.readthedocs.io/)), only partially typed, and
|
|
82
|
+
expose the API as a flat grab-bag of methods. This project exists because none
|
|
83
|
+
of the popular, actively-maintained alternatives (e.g.
|
|
84
|
+
[`trading-ig`](https://github.com/ig-python/trading-ig), the most widely used
|
|
85
|
+
one) offer all of the following together:
|
|
86
|
+
|
|
87
|
+
- **Fully typed.** Every request and response is a
|
|
88
|
+
[pydantic](https://docs.pydantic.dev/) model, so responses are validated at
|
|
89
|
+
the boundary and you get real autocomplete/type-checking instead of dicts of
|
|
90
|
+
`Any`.
|
|
91
|
+
- **Async.** Built on [`aiohttp`](https://docs.aiohttp.org/), with a background
|
|
92
|
+
task that automatically refreshes the OAuth token before it expires, so you
|
|
93
|
+
don't have to babysit sessions.
|
|
94
|
+
- **Clean, resource-oriented usage.** The client is organised as typed
|
|
95
|
+
sub-resources that mirror the shape of the API itself (`client.positions`,
|
|
96
|
+
`client.markets`, `client.working_orders`, ...) rather than one flat object
|
|
97
|
+
with dozens of loosely related methods bolted on.
|
|
98
|
+
|
|
99
|
+
A couple of other things fell out of that design along the way:
|
|
100
|
+
|
|
101
|
+
- The library mirrors IG's own API versioning (`v1`, `v2`, `v3`, ...) with a
|
|
102
|
+
matching submodule for each version, so it's clear exactly which version of an
|
|
103
|
+
endpoint/model you're using.
|
|
104
|
+
- Errors are typed too: IG's error codes are mapped to specific exception
|
|
105
|
+
classes (e.g. `ExceededAPIKeyAllowanceError`, `OAuthTokenInvalidError`)
|
|
106
|
+
instead of a single generic HTTP error.
|
|
107
|
+
|
|
108
|
+
## 🛠️ Development
|
|
109
|
+
|
|
110
|
+
The dev environment is a Docker container with everything needed (`uv`, Python,
|
|
111
|
+
Vim, Claude Code) pre-installed. Start it with:
|
|
112
|
+
|
|
113
|
+
```sh
|
|
114
|
+
docker compose run --build --interactive --remove-orphans --rm vim
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
This mounts the repo into the container and drops you into a shell with the
|
|
118
|
+
`.venv` already synced (`uv sync` has run as part of the image build).
|
|
119
|
+
|
|
120
|
+
From there:
|
|
121
|
+
|
|
122
|
+
```sh
|
|
123
|
+
# Run the test suite. Tests hit IG's real demo API (no mocking), so this
|
|
124
|
+
# needs IG_API_KEY, IG_IDENTIFIER and IG_PASSWORD set, e.g. via .env.
|
|
125
|
+
uv run pytest
|
|
126
|
+
|
|
127
|
+
# Lint and type-check.
|
|
128
|
+
uv run ruff check
|
|
129
|
+
uv run mypy .
|
|
130
|
+
|
|
131
|
+
# Build the docs; output goes to docs/_build/html.
|
|
132
|
+
uv run make -C docs html
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
If you don't want to use the container, the same commands work locally as
|
|
136
|
+
long as you have `uv` installed — just run `uv sync` first.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# 📈 IG trading
|
|
2
|
+
|
|
3
|
+
A fully-typed, async Python client for [IG](https://www.ig.com/)'s trading
|
|
4
|
+
REST API.
|
|
5
|
+
|
|
6
|
+
## 🚀 Usage
|
|
7
|
+
|
|
8
|
+
```python
|
|
9
|
+
import asyncio
|
|
10
|
+
|
|
11
|
+
import ig_trading as ig
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
async def main() -> None:
|
|
15
|
+
async with ig.Client() as client:
|
|
16
|
+
# Credentials default to the IG_API_KEY, IG_IDENTIFIER and IG_PASSWORD
|
|
17
|
+
# environment variables if not passed explicitly.
|
|
18
|
+
positions = await client.positions.list()
|
|
19
|
+
for position in positions:
|
|
20
|
+
print(position.position.deal_id, position.market.epic)
|
|
21
|
+
|
|
22
|
+
deal_reference = await client.positions.otc.create(
|
|
23
|
+
currency_code="GBP",
|
|
24
|
+
direction="BUY",
|
|
25
|
+
epic="CS.D.EURGBP.CFD.IP",
|
|
26
|
+
expiry="-",
|
|
27
|
+
force_open=True,
|
|
28
|
+
guaranteed_stop=False,
|
|
29
|
+
order_type="MARKET",
|
|
30
|
+
size=1,
|
|
31
|
+
)
|
|
32
|
+
print((await client.confirms.get(deal_reference)).reason)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
asyncio.run(main())
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Each resource on `client` (`accounts`, `application`, `categories`,
|
|
39
|
+
`client_sentiment`, `confirms`, `history`, `markets`, `positions`, `prices`,
|
|
40
|
+
`session`, `watchlists`, `working_orders`) can also be used standalone with your
|
|
41
|
+
own `aiohttp.ClientSession`, e.g. for testing or for composing your own login
|
|
42
|
+
flow:
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
async with ig.ClientSession() as http_session:
|
|
46
|
+
requester = ig.APIRequester(http_session=http_session, key="...")
|
|
47
|
+
session = ig.SessionResource(requester)
|
|
48
|
+
account = await session.create(identifier="...", password="...")
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 🔑 Environment variables
|
|
52
|
+
|
|
53
|
+
| Variable | Description |
|
|
54
|
+
| --------------- | ----------- |
|
|
55
|
+
| `IG_API_KEY` | API key |
|
|
56
|
+
| `IG_IDENTIFIER` | Username |
|
|
57
|
+
| `IG_PASSWORD` | Password |
|
|
58
|
+
|
|
59
|
+
These can be set directly or via a `.env` file in the working directory.
|
|
60
|
+
|
|
61
|
+
## 💡 Why
|
|
62
|
+
|
|
63
|
+
The existing IG API clients on PyPI/GitHub are, for the most part, sync (built
|
|
64
|
+
on [`requests`](https://requests.readthedocs.io/)), only partially typed, and
|
|
65
|
+
expose the API as a flat grab-bag of methods. This project exists because none
|
|
66
|
+
of the popular, actively-maintained alternatives (e.g.
|
|
67
|
+
[`trading-ig`](https://github.com/ig-python/trading-ig), the most widely used
|
|
68
|
+
one) offer all of the following together:
|
|
69
|
+
|
|
70
|
+
- **Fully typed.** Every request and response is a
|
|
71
|
+
[pydantic](https://docs.pydantic.dev/) model, so responses are validated at
|
|
72
|
+
the boundary and you get real autocomplete/type-checking instead of dicts of
|
|
73
|
+
`Any`.
|
|
74
|
+
- **Async.** Built on [`aiohttp`](https://docs.aiohttp.org/), with a background
|
|
75
|
+
task that automatically refreshes the OAuth token before it expires, so you
|
|
76
|
+
don't have to babysit sessions.
|
|
77
|
+
- **Clean, resource-oriented usage.** The client is organised as typed
|
|
78
|
+
sub-resources that mirror the shape of the API itself (`client.positions`,
|
|
79
|
+
`client.markets`, `client.working_orders`, ...) rather than one flat object
|
|
80
|
+
with dozens of loosely related methods bolted on.
|
|
81
|
+
|
|
82
|
+
A couple of other things fell out of that design along the way:
|
|
83
|
+
|
|
84
|
+
- The library mirrors IG's own API versioning (`v1`, `v2`, `v3`, ...) with a
|
|
85
|
+
matching submodule for each version, so it's clear exactly which version of an
|
|
86
|
+
endpoint/model you're using.
|
|
87
|
+
- Errors are typed too: IG's error codes are mapped to specific exception
|
|
88
|
+
classes (e.g. `ExceededAPIKeyAllowanceError`, `OAuthTokenInvalidError`)
|
|
89
|
+
instead of a single generic HTTP error.
|
|
90
|
+
|
|
91
|
+
## 🛠️ Development
|
|
92
|
+
|
|
93
|
+
The dev environment is a Docker container with everything needed (`uv`, Python,
|
|
94
|
+
Vim, Claude Code) pre-installed. Start it with:
|
|
95
|
+
|
|
96
|
+
```sh
|
|
97
|
+
docker compose run --build --interactive --remove-orphans --rm vim
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
This mounts the repo into the container and drops you into a shell with the
|
|
101
|
+
`.venv` already synced (`uv sync` has run as part of the image build).
|
|
102
|
+
|
|
103
|
+
From there:
|
|
104
|
+
|
|
105
|
+
```sh
|
|
106
|
+
# Run the test suite. Tests hit IG's real demo API (no mocking), so this
|
|
107
|
+
# needs IG_API_KEY, IG_IDENTIFIER and IG_PASSWORD set, e.g. via .env.
|
|
108
|
+
uv run pytest
|
|
109
|
+
|
|
110
|
+
# Lint and type-check.
|
|
111
|
+
uv run ruff check
|
|
112
|
+
uv run mypy .
|
|
113
|
+
|
|
114
|
+
# Build the docs; output goes to docs/_build/html.
|
|
115
|
+
uv run make -C docs html
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
If you don't want to use the container, the same commands work locally as
|
|
119
|
+
long as you have `uv` installed — just run `uv sync` first.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "ig-trading"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "IG trading"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"aiohttp[speedups]>=3.14.3",
|
|
9
|
+
"pydantic>=2.13.5",
|
|
10
|
+
"python-dotenv>=1.2.3",
|
|
11
|
+
"typing-extensions>=4.16.0",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[[project.authors]]
|
|
15
|
+
name = "Nelson Yeung"
|
|
16
|
+
email = "nelsyeung@gmail.com"
|
|
17
|
+
|
|
18
|
+
[project.urls]
|
|
19
|
+
Changelog = "https://github.com/nelsyeung/ig-trading/blob/main/CHANGELOG.md"
|
|
20
|
+
Documentation = "https://ig-trading.readthedocs.io"
|
|
21
|
+
Issues = "https://github.com/nelsyeung/ig-trading/issues"
|
|
22
|
+
Repository = "https://github.com/nelsyeung/ig-trading.git"
|
|
23
|
+
|
|
24
|
+
[build-system]
|
|
25
|
+
requires = ["uv_build>=0.11.3,<0.12.0"]
|
|
26
|
+
build-backend = "uv_build"
|
|
27
|
+
|
|
28
|
+
[dependency-groups]
|
|
29
|
+
dev = [
|
|
30
|
+
"coverage>=7.16.1",
|
|
31
|
+
"furo>=2025.12.19",
|
|
32
|
+
"mypy>=2.3.1",
|
|
33
|
+
"pytest-asyncio>=1.4.0",
|
|
34
|
+
"pytest-randomly>=5.0.0",
|
|
35
|
+
"pytest>=9.1.1",
|
|
36
|
+
"ruff>=0.16.8",
|
|
37
|
+
"sphinx-copybutton>=0.5.2",
|
|
38
|
+
"sphinx-inline-tabs>=2025.12.21.14",
|
|
39
|
+
"sphinx>=8.1.3",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[tool.coverage.report]
|
|
43
|
+
exclude_also = ["if t.TYPE_CHECKING:"]
|
|
44
|
+
fail_under = 95
|
|
45
|
+
show_missing = true
|
|
46
|
+
skip_covered = true
|
|
47
|
+
|
|
48
|
+
[tool.coverage.run]
|
|
49
|
+
source = ["src/_ig_trading"]
|
|
50
|
+
|
|
51
|
+
[tool.mypy]
|
|
52
|
+
show_error_codes = true
|
|
53
|
+
|
|
54
|
+
[tool.pytest.ini_options]
|
|
55
|
+
addopts = [
|
|
56
|
+
"--asyncio-mode=auto",
|
|
57
|
+
"--strict-markers",
|
|
58
|
+
"-ra",
|
|
59
|
+
]
|
|
60
|
+
asyncio_default_fixture_loop_scope = "session"
|
|
61
|
+
testpaths = ["tests"]
|
|
62
|
+
|
|
63
|
+
[tool.ruff]
|
|
64
|
+
line-length = 79
|
|
65
|
+
namespace-packages = ["scripts"]
|
|
66
|
+
|
|
67
|
+
[tool.ruff.lint]
|
|
68
|
+
ignore = [
|
|
69
|
+
"COM812",
|
|
70
|
+
"CPY001",
|
|
71
|
+
"D107",
|
|
72
|
+
"PLR0913",
|
|
73
|
+
"PLR0917",
|
|
74
|
+
]
|
|
75
|
+
select = ["ALL"]
|
|
76
|
+
|
|
77
|
+
[tool.ruff.lint.flake8-import-conventions.aliases]
|
|
78
|
+
asyncio = "aio"
|
|
79
|
+
datetime = "dt"
|
|
80
|
+
functools = "ft"
|
|
81
|
+
typing_extensions = "t"
|
|
82
|
+
|
|
83
|
+
[tool.ruff.lint.flake8-tidy-imports]
|
|
84
|
+
ban-relative-imports = "all"
|
|
85
|
+
|
|
86
|
+
[tool.ruff.lint.flake8-type-checking]
|
|
87
|
+
exempt-modules = [
|
|
88
|
+
"typing",
|
|
89
|
+
"typing_extensions",
|
|
90
|
+
]
|
|
91
|
+
runtime-evaluated-base-classes = [
|
|
92
|
+
"_ig_trading.model.Model",
|
|
93
|
+
"_ig_trading.positions.v1.Market",
|
|
94
|
+
"_ig_trading.prices.v1.Price",
|
|
95
|
+
"pydantic.BaseModel",
|
|
96
|
+
]
|
|
97
|
+
strict = true
|
|
98
|
+
|
|
99
|
+
[tool.ruff.lint.pydocstyle]
|
|
100
|
+
convention = "google"
|
|
101
|
+
|
|
102
|
+
[tool.ruff.lint.per-file-ignores]
|
|
103
|
+
"docs/conf.py" = [
|
|
104
|
+
"F403",
|
|
105
|
+
"F405",
|
|
106
|
+
"INP001",
|
|
107
|
+
]
|
|
108
|
+
"tests/**" = [
|
|
109
|
+
"D",
|
|
110
|
+
"S",
|
|
111
|
+
"SLF",
|
|
112
|
+
]
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
authors = [
|
|
3
|
+
{ name = "Nelson Yeung", email = "nelsyeung@gmail.com" },
|
|
4
|
+
]
|
|
5
|
+
name = "ig-trading"
|
|
6
|
+
version = "0.1.0"
|
|
7
|
+
description = "IG trading"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"aiohttp[speedups]>=3.14.3",
|
|
12
|
+
"pydantic>=2.13.5",
|
|
13
|
+
"python-dotenv>=1.2.3",
|
|
14
|
+
"typing-extensions>=4.16.0",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[project.urls]
|
|
18
|
+
Changelog = "https://github.com/nelsyeung/ig-trading/blob/main/CHANGELOG.md"
|
|
19
|
+
Documentation = "https://ig-trading.readthedocs.io"
|
|
20
|
+
Issues = "https://github.com/nelsyeung/ig-trading/issues"
|
|
21
|
+
Repository = "https://github.com/nelsyeung/ig-trading.git"
|
|
22
|
+
|
|
23
|
+
[build-system]
|
|
24
|
+
requires = ["uv_build>=0.11.3,<0.12.0"]
|
|
25
|
+
build-backend = "uv_build"
|
|
26
|
+
|
|
27
|
+
[dependency-groups]
|
|
28
|
+
dev = [
|
|
29
|
+
"coverage>=7.16.1",
|
|
30
|
+
"furo>=2025.12.19",
|
|
31
|
+
"mypy>=2.3.1",
|
|
32
|
+
"pytest-asyncio>=1.4.0",
|
|
33
|
+
"pytest-randomly>=5.0.0",
|
|
34
|
+
"pytest>=9.1.1",
|
|
35
|
+
"ruff>=0.16.8",
|
|
36
|
+
"sphinx-copybutton>=0.5.2",
|
|
37
|
+
"sphinx-inline-tabs>=2025.12.21.14",
|
|
38
|
+
"sphinx>=8.1.3",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[tool.coverage.report]
|
|
42
|
+
exclude_also = ["if t.TYPE_CHECKING:"]
|
|
43
|
+
fail_under = 95
|
|
44
|
+
show_missing = true
|
|
45
|
+
skip_covered = true
|
|
46
|
+
|
|
47
|
+
[tool.coverage.run]
|
|
48
|
+
source = ["src/_ig_trading"]
|
|
49
|
+
|
|
50
|
+
[tool.mypy]
|
|
51
|
+
show_error_codes = true
|
|
52
|
+
|
|
53
|
+
[tool.pytest.ini_options]
|
|
54
|
+
addopts = [
|
|
55
|
+
"--asyncio-mode=auto",
|
|
56
|
+
"--strict-markers",
|
|
57
|
+
"-ra",
|
|
58
|
+
]
|
|
59
|
+
asyncio_default_fixture_loop_scope = "session"
|
|
60
|
+
testpaths = ["tests"]
|
|
61
|
+
|
|
62
|
+
[tool.ruff]
|
|
63
|
+
line-length = 79
|
|
64
|
+
namespace-packages = ["scripts"]
|
|
65
|
+
|
|
66
|
+
[tool.ruff.lint]
|
|
67
|
+
ignore = ["COM812", "CPY001", "D107", "PLR0913", "PLR0917"]
|
|
68
|
+
select = ["ALL"]
|
|
69
|
+
|
|
70
|
+
[tool.ruff.lint.flake8-import-conventions.aliases]
|
|
71
|
+
asyncio = "aio"
|
|
72
|
+
datetime = "dt"
|
|
73
|
+
functools = "ft"
|
|
74
|
+
typing_extensions = "t"
|
|
75
|
+
|
|
76
|
+
[tool.ruff.lint.flake8-tidy-imports]
|
|
77
|
+
ban-relative-imports = "all"
|
|
78
|
+
|
|
79
|
+
[tool.ruff.lint.flake8-type-checking]
|
|
80
|
+
exempt-modules = [
|
|
81
|
+
"typing",
|
|
82
|
+
"typing_extensions",
|
|
83
|
+
]
|
|
84
|
+
runtime-evaluated-base-classes = [
|
|
85
|
+
"_ig_trading.model.Model",
|
|
86
|
+
"_ig_trading.positions.v1.Market",
|
|
87
|
+
"_ig_trading.prices.v1.Price",
|
|
88
|
+
"pydantic.BaseModel",
|
|
89
|
+
]
|
|
90
|
+
strict = true
|
|
91
|
+
|
|
92
|
+
[tool.ruff.lint.pydocstyle]
|
|
93
|
+
convention = "google"
|
|
94
|
+
|
|
95
|
+
[tool.ruff.lint.per-file-ignores]
|
|
96
|
+
"docs/conf.py" = ["F403", "F405", "INP001"]
|
|
97
|
+
"tests/**" = ["D", "S", "SLF"]
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"""IG trading."""
|
|
2
|
+
|
|
3
|
+
from _ig_trading.accounts.resource import (
|
|
4
|
+
AccountsPreferencesResource,
|
|
5
|
+
AccountsResource,
|
|
6
|
+
)
|
|
7
|
+
from _ig_trading.api_error import (
|
|
8
|
+
AccountAccessDeniedError,
|
|
9
|
+
AccountIDMustBeDifferentError,
|
|
10
|
+
AccountNotYetActivatedError,
|
|
11
|
+
AccountSuspendedError,
|
|
12
|
+
AccountTokenInvalidError,
|
|
13
|
+
AccountTokenMissingError,
|
|
14
|
+
APIError,
|
|
15
|
+
APIKeyDisabledError,
|
|
16
|
+
APIKeyInvalidError,
|
|
17
|
+
APIKeyMissingError,
|
|
18
|
+
APIKeyRestrictedError,
|
|
19
|
+
APIKeyRevokedError,
|
|
20
|
+
ClientSuspendedError,
|
|
21
|
+
ClientTokenInvalidError,
|
|
22
|
+
ClientTokenMissingError,
|
|
23
|
+
DealExecutionNotFoundError,
|
|
24
|
+
DealNotFoundError,
|
|
25
|
+
EndpointUnavailableForAPIKeyError,
|
|
26
|
+
ExceededAccountAllowanceError,
|
|
27
|
+
ExceededAccountHistoricalDataAllowanceError,
|
|
28
|
+
ExceededAccountTradingAllowanceError,
|
|
29
|
+
ExceededAPIKeyAllowanceError,
|
|
30
|
+
ExpiryNoneNotAllowedError,
|
|
31
|
+
ForceOpenNoneNotAllowedError,
|
|
32
|
+
GenericError,
|
|
33
|
+
GetSessionTimeoutError,
|
|
34
|
+
GuaranteedStopNoneNotAllowedError,
|
|
35
|
+
InvalidAccountIDError,
|
|
36
|
+
InvalidApplicationError,
|
|
37
|
+
InvalidCurrencyCodeError,
|
|
38
|
+
InvalidDateRangeError,
|
|
39
|
+
InvalidDetailsError,
|
|
40
|
+
InvalidDirectionError,
|
|
41
|
+
InvalidExpiryError,
|
|
42
|
+
InvalidInputError,
|
|
43
|
+
InvalidInstrumentError,
|
|
44
|
+
InvalidLevelError,
|
|
45
|
+
InvalidOrderTypeError,
|
|
46
|
+
InvalidRequestError,
|
|
47
|
+
InvalidSizeError,
|
|
48
|
+
InvalidWebsiteError,
|
|
49
|
+
KYCRequiredError,
|
|
50
|
+
MalformedDateError,
|
|
51
|
+
MissingCredentialsError,
|
|
52
|
+
MutualExclusiveValueError,
|
|
53
|
+
NoCompatiblePositionFoundError,
|
|
54
|
+
NoneConditionalSetValueRequestError,
|
|
55
|
+
NotNoneConditionalRequestError,
|
|
56
|
+
OAuthTokenInvalidError,
|
|
57
|
+
PendingAgreementsRequiredError,
|
|
58
|
+
PreferredAccountDisabledError,
|
|
59
|
+
PreferredAccountNotSetError,
|
|
60
|
+
StockbrokingNotSupportedError,
|
|
61
|
+
UnauthorisedAccessToEquityDataError,
|
|
62
|
+
UnknownAPIError,
|
|
63
|
+
)
|
|
64
|
+
from _ig_trading.api_requester import APIRequester, ClientSession
|
|
65
|
+
from _ig_trading.application.resource import (
|
|
66
|
+
ApplicationDisableResource,
|
|
67
|
+
ApplicationResource,
|
|
68
|
+
)
|
|
69
|
+
from _ig_trading.categories.resource import CategoriesResource
|
|
70
|
+
from _ig_trading.client import Client
|
|
71
|
+
from _ig_trading.client_sentiment.resource import (
|
|
72
|
+
ClientSentimentRelatedResource,
|
|
73
|
+
ClientSentimentResource,
|
|
74
|
+
)
|
|
75
|
+
from _ig_trading.confirms.resource import ConfirmsResource
|
|
76
|
+
from _ig_trading.history.resource import (
|
|
77
|
+
HistoryActivityResource,
|
|
78
|
+
HistoryResource,
|
|
79
|
+
HistoryTransactionsResource,
|
|
80
|
+
)
|
|
81
|
+
from _ig_trading.markets.resource import MarketsResource
|
|
82
|
+
from _ig_trading.model import Model
|
|
83
|
+
from _ig_trading.positions.resource import (
|
|
84
|
+
PositionsOTCResource,
|
|
85
|
+
PositionsResource,
|
|
86
|
+
)
|
|
87
|
+
from _ig_trading.prices.resource import PricesResource
|
|
88
|
+
from _ig_trading.session.resource import (
|
|
89
|
+
SessionEncryptionKeyResource,
|
|
90
|
+
SessionRefreshTokenResource,
|
|
91
|
+
SessionResource,
|
|
92
|
+
)
|
|
93
|
+
from _ig_trading.watchlists.resource import WatchlistsResource
|
|
94
|
+
from _ig_trading.working_orders.resource import (
|
|
95
|
+
WorkingOrdersOTCResource,
|
|
96
|
+
WorkingOrdersResource,
|
|
97
|
+
)
|
|
98
|
+
from ig_trading import (
|
|
99
|
+
accounts,
|
|
100
|
+
application,
|
|
101
|
+
categories,
|
|
102
|
+
client_sentiment,
|
|
103
|
+
confirms,
|
|
104
|
+
env,
|
|
105
|
+
history,
|
|
106
|
+
markets,
|
|
107
|
+
positions,
|
|
108
|
+
prices,
|
|
109
|
+
session,
|
|
110
|
+
watchlists,
|
|
111
|
+
working_orders,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
__all__ = (
|
|
115
|
+
"APIError",
|
|
116
|
+
"APIKeyDisabledError",
|
|
117
|
+
"APIKeyInvalidError",
|
|
118
|
+
"APIKeyMissingError",
|
|
119
|
+
"APIKeyRestrictedError",
|
|
120
|
+
"APIKeyRevokedError",
|
|
121
|
+
"APIRequester",
|
|
122
|
+
"AccountAccessDeniedError",
|
|
123
|
+
"AccountIDMustBeDifferentError",
|
|
124
|
+
"AccountNotYetActivatedError",
|
|
125
|
+
"AccountSuspendedError",
|
|
126
|
+
"AccountTokenInvalidError",
|
|
127
|
+
"AccountTokenMissingError",
|
|
128
|
+
"AccountsPreferencesResource",
|
|
129
|
+
"AccountsResource",
|
|
130
|
+
"ApplicationDisableResource",
|
|
131
|
+
"ApplicationResource",
|
|
132
|
+
"CategoriesResource",
|
|
133
|
+
"Client",
|
|
134
|
+
"ClientSentimentRelatedResource",
|
|
135
|
+
"ClientSentimentResource",
|
|
136
|
+
"ClientSession",
|
|
137
|
+
"ClientSuspendedError",
|
|
138
|
+
"ClientTokenInvalidError",
|
|
139
|
+
"ClientTokenMissingError",
|
|
140
|
+
"ConfirmsResource",
|
|
141
|
+
"DealExecutionNotFoundError",
|
|
142
|
+
"DealNotFoundError",
|
|
143
|
+
"EndpointUnavailableForAPIKeyError",
|
|
144
|
+
"ExceededAPIKeyAllowanceError",
|
|
145
|
+
"ExceededAccountAllowanceError",
|
|
146
|
+
"ExceededAccountHistoricalDataAllowanceError",
|
|
147
|
+
"ExceededAccountTradingAllowanceError",
|
|
148
|
+
"ExpiryNoneNotAllowedError",
|
|
149
|
+
"ForceOpenNoneNotAllowedError",
|
|
150
|
+
"GenericError",
|
|
151
|
+
"GetSessionTimeoutError",
|
|
152
|
+
"GuaranteedStopNoneNotAllowedError",
|
|
153
|
+
"HistoryActivityResource",
|
|
154
|
+
"HistoryResource",
|
|
155
|
+
"HistoryTransactionsResource",
|
|
156
|
+
"InvalidAccountIDError",
|
|
157
|
+
"InvalidApplicationError",
|
|
158
|
+
"InvalidCurrencyCodeError",
|
|
159
|
+
"InvalidDateRangeError",
|
|
160
|
+
"InvalidDetailsError",
|
|
161
|
+
"InvalidDirectionError",
|
|
162
|
+
"InvalidExpiryError",
|
|
163
|
+
"InvalidInputError",
|
|
164
|
+
"InvalidInstrumentError",
|
|
165
|
+
"InvalidLevelError",
|
|
166
|
+
"InvalidOrderTypeError",
|
|
167
|
+
"InvalidRequestError",
|
|
168
|
+
"InvalidSizeError",
|
|
169
|
+
"InvalidWebsiteError",
|
|
170
|
+
"KYCRequiredError",
|
|
171
|
+
"MalformedDateError",
|
|
172
|
+
"MarketsResource",
|
|
173
|
+
"MissingCredentialsError",
|
|
174
|
+
"Model",
|
|
175
|
+
"MutualExclusiveValueError",
|
|
176
|
+
"NoCompatiblePositionFoundError",
|
|
177
|
+
"NoneConditionalSetValueRequestError",
|
|
178
|
+
"NotNoneConditionalRequestError",
|
|
179
|
+
"OAuthTokenInvalidError",
|
|
180
|
+
"PendingAgreementsRequiredError",
|
|
181
|
+
"PositionsOTCResource",
|
|
182
|
+
"PositionsResource",
|
|
183
|
+
"PreferredAccountDisabledError",
|
|
184
|
+
"PreferredAccountNotSetError",
|
|
185
|
+
"PricesResource",
|
|
186
|
+
"SessionEncryptionKeyResource",
|
|
187
|
+
"SessionRefreshTokenResource",
|
|
188
|
+
"SessionResource",
|
|
189
|
+
"StockbrokingNotSupportedError",
|
|
190
|
+
"UnauthorisedAccessToEquityDataError",
|
|
191
|
+
"UnknownAPIError",
|
|
192
|
+
"WatchlistsResource",
|
|
193
|
+
"WorkingOrdersOTCResource",
|
|
194
|
+
"WorkingOrdersResource",
|
|
195
|
+
"accounts",
|
|
196
|
+
"application",
|
|
197
|
+
"categories",
|
|
198
|
+
"client_sentiment",
|
|
199
|
+
"confirms",
|
|
200
|
+
"env",
|
|
201
|
+
"history",
|
|
202
|
+
"markets",
|
|
203
|
+
"positions",
|
|
204
|
+
"prices",
|
|
205
|
+
"session",
|
|
206
|
+
"watchlists",
|
|
207
|
+
"working_orders",
|
|
208
|
+
)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""``/accounts`` v1 API models."""
|
|
2
|
+
|
|
3
|
+
from _ig_trading.accounts.v1 import (
|
|
4
|
+
Account,
|
|
5
|
+
AccountType,
|
|
6
|
+
Preferences,
|
|
7
|
+
Status,
|
|
8
|
+
UpdatePreferencesStatus,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
__all__ = (
|
|
12
|
+
"Account",
|
|
13
|
+
"AccountType",
|
|
14
|
+
"Preferences",
|
|
15
|
+
"Status",
|
|
16
|
+
"UpdatePreferencesStatus",
|
|
17
|
+
)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""``/categories`` resource models."""
|
|
2
|
+
|
|
3
|
+
from _ig_trading.categories.v1 import (
|
|
4
|
+
Categories,
|
|
5
|
+
Category,
|
|
6
|
+
Instrument,
|
|
7
|
+
Instruments,
|
|
8
|
+
InstrumentsMetaData,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
__all__ = (
|
|
12
|
+
"Categories",
|
|
13
|
+
"Category",
|
|
14
|
+
"Instrument",
|
|
15
|
+
"Instruments",
|
|
16
|
+
"InstrumentsMetaData",
|
|
17
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""``/positions`` resource models."""
|
|
2
|
+
|
|
3
|
+
from _ig_trading.confirms.v1 import (
|
|
4
|
+
AffectedDeal,
|
|
5
|
+
AffectedDealStatus,
|
|
6
|
+
DealConfirmation,
|
|
7
|
+
DealConfirmationReason,
|
|
8
|
+
DealStatus,
|
|
9
|
+
PositionStatus,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = (
|
|
13
|
+
"AffectedDeal",
|
|
14
|
+
"AffectedDealStatus",
|
|
15
|
+
"DealConfirmation",
|
|
16
|
+
"DealConfirmationReason",
|
|
17
|
+
"DealStatus",
|
|
18
|
+
"PositionStatus",
|
|
19
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""``/history`` resource models."""
|
|
2
|
+
|
|
3
|
+
from _ig_trading.history.v1 import (
|
|
4
|
+
ActionStatus,
|
|
5
|
+
Activities,
|
|
6
|
+
Activity,
|
|
7
|
+
Transaction,
|
|
8
|
+
Transactions,
|
|
9
|
+
TransactionType,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = (
|
|
13
|
+
"ActionStatus",
|
|
14
|
+
"Activities",
|
|
15
|
+
"Activity",
|
|
16
|
+
"Transaction",
|
|
17
|
+
"TransactionType",
|
|
18
|
+
"Transactions",
|
|
19
|
+
)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""``/markets`` v1 API models."""
|
|
2
|
+
|
|
3
|
+
from _ig_trading.markets.v1 import (
|
|
4
|
+
Currency,
|
|
5
|
+
DealingRule,
|
|
6
|
+
DealingRules,
|
|
7
|
+
ExpiryDetails,
|
|
8
|
+
Instrument,
|
|
9
|
+
MarginDepositBands,
|
|
10
|
+
Market,
|
|
11
|
+
MarketOrderPreference,
|
|
12
|
+
MarketOverview,
|
|
13
|
+
MarketTime,
|
|
14
|
+
OpeningHours,
|
|
15
|
+
RolloverDetails,
|
|
16
|
+
SizeOfTradeUnit,
|
|
17
|
+
SlippageFactor,
|
|
18
|
+
Snapshot,
|
|
19
|
+
TrailingStopsPreference,
|
|
20
|
+
Unit,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
__all__ = (
|
|
24
|
+
"Currency",
|
|
25
|
+
"DealingRule",
|
|
26
|
+
"DealingRules",
|
|
27
|
+
"ExpiryDetails",
|
|
28
|
+
"Instrument",
|
|
29
|
+
"MarginDepositBands",
|
|
30
|
+
"Market",
|
|
31
|
+
"MarketOrderPreference",
|
|
32
|
+
"MarketOverview",
|
|
33
|
+
"MarketTime",
|
|
34
|
+
"OpeningHours",
|
|
35
|
+
"RolloverDetails",
|
|
36
|
+
"SizeOfTradeUnit",
|
|
37
|
+
"SlippageFactor",
|
|
38
|
+
"Snapshot",
|
|
39
|
+
"TrailingStopsPreference",
|
|
40
|
+
"Unit",
|
|
41
|
+
)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""``/markets`` v4 API models."""
|
|
2
|
+
|
|
3
|
+
from _ig_trading.markets.v4 import (
|
|
4
|
+
Currency,
|
|
5
|
+
DealingRule,
|
|
6
|
+
DealingRules,
|
|
7
|
+
Instrument,
|
|
8
|
+
Market,
|
|
9
|
+
SizeOfTradeUnit,
|
|
10
|
+
Snapshot,
|
|
11
|
+
TrailingStopsPreference,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
__all__ = (
|
|
15
|
+
"Currency",
|
|
16
|
+
"DealingRule",
|
|
17
|
+
"DealingRules",
|
|
18
|
+
"Instrument",
|
|
19
|
+
"Market",
|
|
20
|
+
"SizeOfTradeUnit",
|
|
21
|
+
"Snapshot",
|
|
22
|
+
"TrailingStopsPreference",
|
|
23
|
+
)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""``/positions`` resource models."""
|
|
2
|
+
|
|
3
|
+
from _ig_trading.positions.v1 import DealDirection
|
|
4
|
+
from _ig_trading.positions.v2 import (
|
|
5
|
+
Market,
|
|
6
|
+
Position,
|
|
7
|
+
PositionData,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
__all__ = (
|
|
11
|
+
"DealDirection",
|
|
12
|
+
"Market",
|
|
13
|
+
"Position",
|
|
14
|
+
"PositionData",
|
|
15
|
+
)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""``/prices`` v3 API models."""
|
|
2
|
+
|
|
3
|
+
from _ig_trading.prices.v1 import (
|
|
4
|
+
Allowance,
|
|
5
|
+
PriceData,
|
|
6
|
+
PriceResolution,
|
|
7
|
+
)
|
|
8
|
+
from _ig_trading.prices.v3 import PageData, Price, Prices, PricesMetaData
|
|
9
|
+
|
|
10
|
+
__all__ = (
|
|
11
|
+
"Allowance",
|
|
12
|
+
"PageData",
|
|
13
|
+
"Price",
|
|
14
|
+
"PriceData",
|
|
15
|
+
"PriceResolution",
|
|
16
|
+
"Prices",
|
|
17
|
+
"PricesMetaData",
|
|
18
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""``/session`` v1 API models."""
|
|
2
|
+
|
|
3
|
+
from _ig_trading.session.v1 import (
|
|
4
|
+
Account,
|
|
5
|
+
AccountSummary,
|
|
6
|
+
EncryptionKey,
|
|
7
|
+
OAuthToken,
|
|
8
|
+
Session,
|
|
9
|
+
SwitchAccount,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = (
|
|
13
|
+
"Account",
|
|
14
|
+
"AccountSummary",
|
|
15
|
+
"EncryptionKey",
|
|
16
|
+
"OAuthToken",
|
|
17
|
+
"Session",
|
|
18
|
+
"SwitchAccount",
|
|
19
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""``/watchlists`` resource models."""
|
|
2
|
+
|
|
3
|
+
from _ig_trading.watchlists.v1 import (
|
|
4
|
+
CreateResult,
|
|
5
|
+
CreateStatus,
|
|
6
|
+
DeleteStatus,
|
|
7
|
+
UpdateStatus,
|
|
8
|
+
Watchlist,
|
|
9
|
+
Watchlists,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = (
|
|
13
|
+
"CreateResult",
|
|
14
|
+
"CreateStatus",
|
|
15
|
+
"DeleteStatus",
|
|
16
|
+
"UpdateStatus",
|
|
17
|
+
"Watchlist",
|
|
18
|
+
"Watchlists",
|
|
19
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""``/workingorders`` resource models."""
|
|
2
|
+
|
|
3
|
+
from _ig_trading.positions.v1 import DealDirection
|
|
4
|
+
from _ig_trading.working_orders.v1 import (
|
|
5
|
+
Market,
|
|
6
|
+
WorkingOrder,
|
|
7
|
+
WorkingOrderData,
|
|
8
|
+
WorkingOrderRequestType,
|
|
9
|
+
WorkingOrders,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = (
|
|
13
|
+
"DealDirection",
|
|
14
|
+
"Market",
|
|
15
|
+
"WorkingOrder",
|
|
16
|
+
"WorkingOrderData",
|
|
17
|
+
"WorkingOrderRequestType",
|
|
18
|
+
"WorkingOrders",
|
|
19
|
+
)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""``/workingorders`` resource models."""
|
|
2
|
+
|
|
3
|
+
from _ig_trading.positions.v1 import DealDirection
|
|
4
|
+
from _ig_trading.working_orders.v1 import Market
|
|
5
|
+
from _ig_trading.working_orders.v2 import (
|
|
6
|
+
TimeInForce,
|
|
7
|
+
WorkingOrder,
|
|
8
|
+
WorkingOrderData,
|
|
9
|
+
WorkingOrders,
|
|
10
|
+
WorkingOrderType,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__all__ = (
|
|
14
|
+
"DealDirection",
|
|
15
|
+
"Market",
|
|
16
|
+
"TimeInForce",
|
|
17
|
+
"WorkingOrder",
|
|
18
|
+
"WorkingOrderData",
|
|
19
|
+
"WorkingOrderType",
|
|
20
|
+
"WorkingOrders",
|
|
21
|
+
)
|