Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [ "3.10", "3.11", "3.12" ]
python-version: [ "3.10", "3.11", "3.12", "3.13" ]

steps:

Expand All @@ -39,4 +39,4 @@ jobs:

- name: Unit tests with pytest
run: |
uv run pytest --ignore=tests/test_integration.py
uv run pytest -m "not integration"
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,6 @@ trading_ig_config.py

.vscode

# poetry
# build system
poetry.lock
uv.lock
11 changes: 9 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[build-system]
requires = ["uv_build>=0.11.6,<0.12.0"]
requires = ["uv_build>=0.11.6,<0.13.0"]
build-backend = "uv_build"

[project]
Expand Down Expand Up @@ -33,18 +33,19 @@ classifiers = [
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Scientific/Engineering",
"Topic :: Software Development :: Libraries",
]
dependencies = [
"requests>=2.24,<3",
"pycryptodome>=3.9,<4",
"requests-cache>1,<2",
"six>=1.15,<2",
"lightstreamer-client-lib==1.0.3",
]

[project.optional-dependencies]
requests-cache = ["requests-cache>1,<2"]
pandas = [
"pandas>=2,<3",
]
Expand All @@ -69,6 +70,12 @@ dev = [
"ruff==0.16.1",
]

[tool.pytest.ini_options]
testpaths = ["tests"]
markers = [
"integration: Integration tests (requires API credentials)",
]

[tool.uv.build-backend]
module-name = "trading_ig"
module-root = ""
Expand Down
103 changes: 25 additions & 78 deletions sample/all_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,45 +8,31 @@
)


def display_top_level_nodes():
def display_categories():
ig_service = get_session()

response = ig_service.fetch_top_level_navigation_nodes()
df = response["nodes"]
for record in df.to_dict("records"):
print(f"{record['name']} [{record['id']}]")
response = ig_service.fetch_categories()
df = response["categories"]
for row in df.itertuples(index=False):
print(f"{row.code}, nonTradeable={row.nonTradeable}")


def display_all_epics():
ig_service = get_session()
response = ig_service.fetch_top_level_navigation_nodes()
df = response["nodes"]
for record in df.to_dict("records"):
print(f"{record['name']} [{record['id']}]")
display_epics_for_node(record["id"], space=" ", ig_service=ig_service)
response = ig_service.fetch_categories()
df = response["categories"]
for row in df.itertuples(index=False):
print(f"{row.code}, nonTradeable={row.nonTradeable}")
display_epics_for_category(row.code, space=" ", ig_service=ig_service)


def display_epics_for_node(node_id=0, space="", ig_service=None):
def display_epics_for_category(category: str, space="", ig_service=None):
if ig_service is None:
ig_service = get_session()

sub_nodes = ig_service.fetch_sub_nodes_by_node(node_id)

if sub_nodes["nodes"].shape[0] != 0:
rows = sub_nodes["nodes"].to_dict("records")
for record in rows:
print(f"{space}{record['name']} [{record['id']}]")
display_epics_for_node(
record["id"], space=space + " ", ig_service=ig_service
)

if sub_nodes["markets"].shape[0] != 0:
cols = sub_nodes["markets"].to_dict("records")
for record in cols:
print(
f"{space}{record['instrumentName']} ({record['expiry']}): "
f"{record['epic']}"
)
response = ig_service.fetch_category_instruments(category)
for row in response["instruments"].itertuples(index=False):
print(f"{space}{row.instrumentName} ({row.expiry.strip()}): {row.epic}")


def get_session():
Expand All @@ -63,58 +49,19 @@ def get_session():


if __name__ == "__main__":
display_top_level_nodes()
display_categories()
# display_all_epics()

"""
Weekend Markets [191926749]
Indices [97601]
Forex [195235]
Commodities Metals Energies [101515]
Cryptocurrency [668394]
Bonds and Moneymarket [108092]
ETFs, ETCs & Trackers [184730]
Shares - UK [180500]
Shares - UK International (IOB) [97695]
Shares - US (All Sessions) [298158]
Shares - US [97477]
Shares - Austria [114058]
Shares - Belgium [114036]
Shares - Canada [103185]
Shares - Denmark [419769]
Shares - Finland [99514]
Shares - France [113659]
Shares - LSE (UK) [172904]
Shares - Germany [97466]
Shares - Greece [100437]
Shares - Hong Kong [105775]
Shares - Ireland (LSE) [421257]
Shares - Ireland (Euronext Dublin) [99578822]
Shares - Netherlands [105509]
Shares - New Zealand [127489792]
Shares - Norway [99808]
Shares - Portugal [99787]
Shares - Singapore [105781]
Shares - South Africa [100066]
Shares - Sweden [113681]
Shares - Switzerland [99814]
IPOs [324080]
Options (Australia 200) [77976799]
Options (Eu Stocks 50) [245938]
Options (France 40) [188760]
Options (FTSE) [122250]
Options (Germany) [97612]
Options (HS 50) [92462573]
Options (Japan 225) [111915265]
Options (Netherlands 25) [236490]
Options (Sweden 30) [319963]
Options (Taiwan Index) [157168018]
Options (US 500) [267039]
Options (US Tech 100) [89291253]
Options (Wall St) [122505]
Options on FX Majors [255072]
Options (Volatility Index) [56719751]
Options on Metals, Energies [195913]
INDICES
FX
CRYPTOCURRENCY
EQUITIES
COMMODITIES
BONDS_RATES
ETF
OPTIONS
IPOS
"""

# display_epics_for_node(195913)
# display_epics_for_category("INDICES")
18 changes: 17 additions & 1 deletion sample/rest_ig.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"""

import logging
import sys

# if you need to cache to DB your requests
from datetime import timedelta
Expand All @@ -18,7 +19,12 @@


def main():
logging.basicConfig(level=logging.DEBUG)
logging.basicConfig(
format="%(asctime)s %(levelname)s %(name)s.%(funcName)s: %(message)s",
level=logging.DEBUG,
stream=sys.stdout,
)
logging.captureWarnings(True)

expire_after = timedelta(hours=1)
session = requests_cache.CachedSession(
Expand Down Expand Up @@ -63,6 +69,16 @@ def main():

print()

# categories = ig_service.fetch_categories()
# print(f"categories: {categories}")

print()

# instruments = ig_service.fetch_category_instruments("INDICES")
# print(f"category instruments: {instruments}")

print()

# epic = 'CS.D.EURUSD.MINI.IP'
epic = "IX.D.ASX.IFM.IP" # US (SPY) - mini
# epic = "CS.D.GBPUSD.CFD.IP" # sample CFD epic
Expand Down
Loading