From 31b76cf645ac5c2ea2317d9f19bafa4f59ed2890 Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Mon, 22 Jan 2024 12:51:11 +0000 Subject: [PATCH 1/8] adding a sample jupyter notebook --- sample/rest.ipynb | 142 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 sample/rest.ipynb diff --git a/sample/rest.ipynb b/sample/rest.ipynb new file mode 100644 index 0000000..939c100 --- /dev/null +++ b/sample/rest.ipynb @@ -0,0 +1,142 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "ec8c83b74991ebc7", + "metadata": { + "collapsed": false + }, + "source": [ + "# Imports, objects, and starting a session\n", + "\n", + "Using v2 sessions by default" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6236766fd0340597", + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from trading_ig.rest import IGService\n", + "from trading_ig.config import config\n", + "\n", + "service = IGService(\n", + " config.username,\n", + " config.password,\n", + " config.api_key,\n", + " config.acc_type,\n", + " acc_number=config.acc_number,\n", + ")\n", + "# creating a v2 session\n", + "service.create_session()\n", + "\n", + "# creating a v3 session\n", + "#service.create_session(version=\"3\")" + ] + }, + { + "cell_type": "markdown", + "id": "aa41443cec0fb2d2", + "metadata": { + "collapsed": false + }, + "source": [ + "# Fetching account information" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19f74547fb3174e1", + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "service.fetch_accounts()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Fetching historic prices" + ], + "metadata": { + "collapsed": false + }, + "id": "f3e01ba486501770" + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "data = service.fetch_historical_prices_by_epic(\n", + " epic=\"IX.D.FTSE.DAILY.IP\",\n", + " resolution=\"D\",\n", + " start_date=\"2024-01-01\",\n", + " end_date=\"2024-01-22\",\n", + " format=service.flat_prices\n", + ")\n", + "\n", + "data[\"prices\"]" + ], + "metadata": { + "collapsed": false + }, + "id": "3b72874aaba7a665" + }, + { + "cell_type": "markdown", + "source": [ + "# Save prices to file" + ], + "metadata": { + "collapsed": false + }, + "id": "e34db8ecfc649f6e" + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "from pathlib import Path\n", + "\n", + "save_path = Path('~').expanduser() / \"prices.csv\"\n", + "print(f\"saving historic prices to {save_path}\")\n", + "\n", + "data[\"prices\"].to_csv(save_path, date_format=\"%Y-%m-%dT%H:%M:%S%z\")\n" + ], + "metadata": { + "collapsed": false + }, + "id": "f9cd0c0854f0a17c" + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.16" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 6bd5b3f06cc628e436c9e8196480097ea3cb787b Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Tue, 6 Feb 2024 09:15:55 +0000 Subject: [PATCH 2/8] rest sample notebook updated with history and activity --- sample/rest.ipynb | 98 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 21 deletions(-) diff --git a/sample/rest.ipynb b/sample/rest.ipynb index 939c100..6783168 100644 --- a/sample/rest.ipynb +++ b/sample/rest.ipynb @@ -16,9 +16,7 @@ "cell_type": "code", "execution_count": null, "id": "6236766fd0340597", - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "from trading_ig.rest import IGService\n", @@ -52,9 +50,7 @@ "cell_type": "code", "execution_count": null, "id": "19f74547fb3174e1", - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "service.fetch_accounts()" @@ -62,17 +58,19 @@ }, { "cell_type": "markdown", - "source": [ - "# Fetching historic prices" - ], + "id": "f3e01ba486501770", "metadata": { "collapsed": false }, - "id": "f3e01ba486501770" + "source": [ + "# Fetching historic prices" + ] }, { "cell_type": "code", "execution_count": null, + "id": "3b72874aaba7a665", + "metadata": {}, "outputs": [], "source": [ "data = service.fetch_historical_prices_by_epic(\n", @@ -84,25 +82,23 @@ ")\n", "\n", "data[\"prices\"]" - ], - "metadata": { - "collapsed": false - }, - "id": "3b72874aaba7a665" + ] }, { "cell_type": "markdown", - "source": [ - "# Save prices to file" - ], + "id": "e34db8ecfc649f6e", "metadata": { "collapsed": false }, - "id": "e34db8ecfc649f6e" + "source": [ + "# Save prices to file" + ] }, { "cell_type": "code", "execution_count": null, + "id": "f9cd0c0854f0a17c", + "metadata": {}, "outputs": [], "source": [ "from pathlib import Path\n", @@ -111,11 +107,71 @@ "print(f\"saving historic prices to {save_path}\")\n", "\n", "data[\"prices\"].to_csv(save_path, date_format=\"%Y-%m-%dT%H:%M:%S%z\")\n" - ], + ] + }, + { + "cell_type": "markdown", + "id": "d5ecd4aa7bc33dea", + "metadata": { + "collapsed": false + }, + "source": [ + "# Fetch history" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79c0c6ed2ca08a1c", + "metadata": {}, + "outputs": [], + "source": [ + "from datetime import datetime, timedelta\n", + "to_date = datetime.now()\n", + "from_date = to_date - timedelta(days=7)\n", + "\n", + "service.fetch_transaction_history(from_date=from_date, to_date=to_date)" + ] + }, + { + "cell_type": "markdown", + "id": "52e40ae5ef37d3eb", + "metadata": { + "collapsed": false + }, + "source": [ + "# Fetch activity (simple)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a089d1babd98781", + "metadata": {}, + "outputs": [], + "source": [ + "service.fetch_account_activity(from_date=from_date, to_date=to_date)" + ] + }, + { + "cell_type": "markdown", + "id": "5411321a662441be", "metadata": { "collapsed": false }, - "id": "f9cd0c0854f0a17c" + "source": [ + "# Fetch activity (detailed)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c31119d129505286", + "metadata": {}, + "outputs": [], + "source": [ + "service.fetch_account_activity(from_date=from_date, to_date=to_date, detailed=True)" + ] } ], "metadata": { From 3af5eccdba9251127f67d35628d03dd95e25b350 Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 8 Jan 2025 13:46:46 +0000 Subject: [PATCH 3/8] min Python 3.9, min pandas 2 --- pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b86d7a0..12cb1ed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,15 +28,15 @@ classifiers = [ ] [tool.poetry.dependencies] -python = ">=3.7,<4.0" +python = ">=3.9,<4.0" requests = "^2.24" pycryptodome = "^3.9" requests-cache = "^0.5" six = "^1.15" lightstreamer-client-lib = "^1.0.3" -pandas = { version = "^1", optional = true } -munch = { version = "^2.5", optional = true } +pandas = {version = "^2", optional = true} +munch = {version = "^2.5", optional = true} tenacity = {version = "^8", optional = true} [tool.poetry.extras] From caafd0ce293c31ac3c78679c21db11b72126e111 Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 8 Jan 2025 13:47:12 +0000 Subject: [PATCH 4/8] drop 3.8, add 3.11 for unit tests --- .github/workflows/unit-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 0150753..2a724fc 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [ "3.8", "3.9", "3.10" ] + python-version: [ "3.9", "3.10", "3.11" ] steps: From 333b484c4d1953254fc0a682551616f4595bfb81 Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 8 Jan 2025 13:47:29 +0000 Subject: [PATCH 5/8] run integration tests against 3.10 --- .github/workflows/integration-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index a64f450..8455dfd 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -15,10 +15,10 @@ jobs: - uses: actions/checkout@v4 - - name: Set up Python 3.8 + - name: Set up Python 3.10 uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: 3.10 - name: Install Poetry uses: abatilo/actions-poetry@v2 From 6a2b1cb1eb3340354c167119a7676b49b3ab8dbe Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 8 Jan 2025 13:48:33 +0000 Subject: [PATCH 6/8] fix pandas 2 datetime changes. suppress pandas 2 future warnings --- trading_ig/rest.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/trading_ig/rest.py b/trading_ig/rest.py index 33cc63e..c9e2758 100644 --- a/trading_ig/rest.py +++ b/trading_ig/rest.py @@ -33,7 +33,7 @@ from .utils import munchify if _HAS_PANDAS: - from .utils import pd, np + from .utils import pd from pandas import json_normalize from threading import Thread @@ -1613,6 +1613,11 @@ def cols(typ): keys.append("last") df2 = pd.concat(data, axis=1, keys=keys) + + # force all object columns to be numeric, NaN if error + for col in df2.select_dtypes(include=["object"]).columns: + df2[col] = pd.to_numeric(df2[col], errors="coerce") + return df2 def flat_prices(self, prices, version): @@ -1637,9 +1642,11 @@ def flat_prices(self, prices, version): if version == "3": df = df.set_index("snapshotTimeUTC") df = df.drop(columns=["snapshotTime"]) + date_format = "%Y-%m-%dT%H:%M:%S" else: df = df.set_index("snapshotTime") - df.index = pd.to_datetime(df.index, format=DATE_FORMATS[int(version)]) + date_format = DATE_FORMATS[int(version)] + df.index = pd.to_datetime(df.index, format=date_format) df.index.name = "DateTime" df = df.drop( columns=[ @@ -1798,7 +1805,6 @@ def fetch_historical_prices_by_epic( format = self.format_prices if self.return_dataframe: data["prices"] = format(data["prices"], version) - data["prices"] = data["prices"].fillna(value=np.nan) self.log_allowance(data["metadata"]) return data @@ -1820,7 +1826,6 @@ def fetch_historical_prices_by_epic_and_num_points( format = self.format_prices if self.return_dataframe: data["prices"] = format(data["prices"], version) - data["prices"] = data["prices"].fillna(value=np.nan) return data def fetch_historical_prices_by_epic_and_date_range( @@ -1884,7 +1889,6 @@ def fetch_historical_prices_by_epic_and_date_range( format = self.format_prices if self.return_dataframe: data["prices"] = format(data["prices"], version) - data["prices"] = data["prices"].fillna(value=np.nan) return data def log_allowance(self, data): From b05f4650e9a142801e3c66edc8c700ee5301a9d6 Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 8 Jan 2025 13:48:43 +0000 Subject: [PATCH 7/8] suppress pandas 2 future warnings --- trading_ig/utils.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/trading_ig/utils.py b/trading_ig/utils.py index f006aaa..5cc25e2 100644 --- a/trading_ig/utils.py +++ b/trading_ig/utils.py @@ -46,13 +46,13 @@ def conv_resol(resolution): to_offset("10Min"): "MINUTE_10", to_offset("15Min"): "MINUTE_15", to_offset("30Min"): "MINUTE_30", - to_offset("1H"): "HOUR", - to_offset("2H"): "HOUR_2", - to_offset("3H"): "HOUR_3", - to_offset("4H"): "HOUR_4", + to_offset("1h"): "HOUR", + to_offset("2h"): "HOUR_2", + to_offset("3h"): "HOUR_3", + to_offset("4h"): "HOUR_4", to_offset("D"): "DAY", to_offset("W"): "WEEK", - to_offset("M"): "MONTH", + to_offset("ME"): "MONTH", } offset = to_offset(resolution) if offset in d: From 88431c763108aac6399c8ccf11b444cdde17a42c Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 8 Jan 2025 13:53:38 +0000 Subject: [PATCH 8/8] drop 3.7, 3.8, add 3.11 --- pyproject.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 12cb1ed..f8cc48a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,10 +18,9 @@ classifiers = [ "Operating System :: OS Independent", "Programming Language :: Cython", "Programming Language :: Python", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Topic :: Scientific/Engineering", "Topic :: Software Development :: Libraries", "License :: OSI Approved :: BSD License",