From e3965867658f18d96909298c66e4bbc83f1e2d7d Mon Sep 17 00:00:00 2001 From: Caleb Burke Date: Sat, 20 Jun 2026 02:06:20 -0700 Subject: [PATCH] Using docker file for ib gateway --- .env.template | 27 ++++++++++++++ .gitignore | 1 + .python-version | 1 + README.md | 12 ++++--- docker-compose.yml | 48 +++++++++++++++++++++++++ ibgw.sh | 23 ------------ main.py | 6 ++++ pyproject.toml | 9 +++++ start.sh | 3 ++ test-connection.py | 19 ++++++++++ uv.lock | 87 ++++++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 208 insertions(+), 28 deletions(-) create mode 100644 .env.template create mode 100644 .gitignore create mode 100644 .python-version create mode 100644 docker-compose.yml delete mode 100644 ibgw.sh create mode 100644 main.py create mode 100644 pyproject.toml create mode 100755 start.sh create mode 100644 test-connection.py create mode 100644 uv.lock diff --git a/.env.template b/.env.template new file mode 100644 index 0000000..84f120b --- /dev/null +++ b/.env.template @@ -0,0 +1,27 @@ +# Live account credentials +TWS_USERID= +TWS_PASSWORD= + +# Paper account credentials (required for TRADING_MODE=both) +TWS_USERID_PAPER= +TWS_PASSWORD_PAPER= + +TRADING_MODE=paper + +# VNC password (required to enable VNC on port 5900) +VNC_SERVER_PASSWORD=changeme + +# Restart gateway daily at this time instead of full logoff (avoids daily 2FA) +AUTO_RESTART_TIME=11:59 PM +TWOFA_TIMEOUT_ACTION=restart +RELOGIN_AFTER_TWOFA_TIMEOUT=yes + +READ_ONLY_API=no +ALLOW_BLIND_TRADING=no +EXISTING_SESSION_DETECTED_ACTION=primary +TIME_ZONE=America/Vancouver + +# SSH tunnel (leave blank if not using) +SSH_TUNNEL= +SSH_USER_TUNNEL= +SSH_PASSPHRASE= diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2eea525 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env \ No newline at end of file diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..6324d40 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.14 diff --git a/README.md b/README.md index 21bbd9c..52b69ae 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # ibgw -## Install +## Usage -Run the command below in the Proxmox VE Shell or a VM to install ibgw. +1. Copy `.env.template` to `.env` and fill out empty fields +2. Run `./start.sh` +3. VNC running on port 5900 for troubling shooting bugs -```bash -bash -c "$(curl -fsSL http://192.168.1.174:3000/alphane/ibgw/raw/branch/main/ibgw.sh)" -``` +## References + +- diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..016604e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,48 @@ +services: + ib-gateway: + restart: always + image: ghcr.io/gnzsnz/ib-gateway:stable + environment: + TWS_USERID: ${TWS_USERID} + TWS_PASSWORD: ${TWS_PASSWORD} + TWS_USERID_PAPER: ${TWS_USERID_PAPER} + TWS_PASSWORD_PAPER: ${TWS_PASSWORD_PAPER} + TRADING_MODE: ${TRADING_MODE:-both} + TWS_SETTINGS_PATH: ${TWS_SETTINGS_PATH:-} + TWS_ACCEPT_INCOMING: ${TWS_ACCEPT_INCOMING:-} + TWS_MASTER_CLIENT_ID: ${TWS_MASTER_CLIENT_ID:-} + READ_ONLY_API: ${READ_ONLY_API:-no} + VNC_SERVER_PASSWORD: ${VNC_SERVER_PASSWORD} + TWOFA_TIMEOUT_ACTION: ${TWOFA_TIMEOUT_ACTION:-restart} + TWOFA_DEVICE: ${TWOFA_DEVICE:-} + TWOFA_EXIT_INTERVAL: ${TWOFA_EXIT_INTERVAL:-60} + BYPASS_WARNING: ${BYPASS_WARNING:-} + AUTO_RESTART_TIME: ${AUTO_RESTART_TIME:-11:59 PM} + AUTO_LOGOFF_TIME: ${AUTO_LOGOFF_TIME:-} + TWS_COLD_RESTART: ${TWS_COLD_RESTART:-} + SAVE_TWS_SETTINGS: ${SAVE_TWS_SETTINGS:-} + RELOGIN_AFTER_TWOFA_TIMEOUT: ${RELOGIN_AFTER_TWOFA_TIMEOUT:-yes} + EXISTING_SESSION_DETECTED_ACTION: ${EXISTING_SESSION_DETECTED_ACTION:-primary} + ALLOW_BLIND_TRADING: ${ALLOW_BLIND_TRADING:-no} + TIME_ZONE: ${TIME_ZONE:-America/New_York} + TZ: ${TIME_ZONE:-America/New_York} + CUSTOM_CONFIG: ${CUSTOM_CONFIG:-NO} + JAVA_HEAP_SIZE: ${JAVA_HEAP_SIZE:-} + SSH_TUNNEL: ${SSH_TUNNEL:-} + SSH_USER_TUNNEL: ${SSH_USER_TUNNEL:-} + SSH_PASSPHRASE: ${SSH_PASSPHRASE:-} + SSH_REMOTE_PORT: ${SSH_REMOTE_PORT:-} + SSH_RESTART: ${SSH_RESTART:-} + SSH_VNC_PORT: ${SSH_VNC_PORT:-} + START_SCRIPTS: ${START_SCRIPTS:-} + X_SCRIPTS: ${X_SCRIPTS:-} + IBC_SCRIPTS: ${IBC_SCRIPTS:-} + volumes: + - tws_settings:/home/ibgateway/tws_settings + ports: + - "127.0.0.1:4001:4003" + - "127.0.0.1:4002:4004" + - "127.0.0.1:5900:5900" + +volumes: + tws_settings: diff --git a/ibgw.sh b/ibgw.sh deleted file mode 100644 index 8630d73..0000000 --- a/ibgw.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) - -APP="ibgw" -var_os="debian" -var_version="12" -var_cpu="2" -var_ram="4096" -var_disk="8" - -header_info - -base_settings - -update_script() { - header_info - msg_info "Installing Dependencies" - apt-get install -y git curl sudo - msg_ok "Installed Dependencies" -} - -build_container \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..b5b50ca --- /dev/null +++ b/main.py @@ -0,0 +1,6 @@ +def main(): + print("Hello from ibgw!") + + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..04f707b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,9 @@ +[project] +name = "ibgw" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.14" +dependencies = [ + "ib_async>=0.9.86", +] diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..1260734 --- /dev/null +++ b/start.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +docker compose -f docker-compose.yml up --remove-orphans \ No newline at end of file diff --git a/test-connection.py b/test-connection.py new file mode 100644 index 0000000..7becce6 --- /dev/null +++ b/test-connection.py @@ -0,0 +1,19 @@ +from ib_async import IB, Stock + +ib = IB() +ib.connect('127.0.0.1', port=4002, clientId=1) + +aapl = Stock('AAPL', 'SMART', 'USD') +ib.qualifyContracts(aapl) + +bars = ib.reqHistoricalData( + aapl, + endDateTime='', + durationStr='1 D', + barSizeSetting='1 day', + whatToShow='TRADES', + useRTH=True, +) +print(f'AAPL close: {bars[-1].close}') + +ib.disconnect() diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..b8d19ce --- /dev/null +++ b/uv.lock @@ -0,0 +1,87 @@ +version = 1 +revision = 3 +requires-python = ">=3.14" + +[[package]] +name = "aeventkit" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/8c/c08db1a1910f8d04ec6a524de522edd0bac181bdf94dbb01183f7685cd77/aeventkit-2.1.0.tar.gz", hash = "sha256:4e7d81bb0a67227121da50a23e19e5bbf13eded541a9f4857eeb6b7b857b738a", size = 24703, upload-time = "2025-06-22T15:54:03.961Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/8c/2a4b912b1afa201b25bdd0f5bccf96d5a8b5dccb6131316a8dd2d9cabcc1/aeventkit-2.1.0-py3-none-any.whl", hash = "sha256:962d43f79e731ac43527f2d0defeed118e6dbaa85f1487f5667540ebb8f00729", size = 26678, upload-time = "2025-06-22T15:54:02.141Z" }, +] + +[[package]] +name = "ib-async" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aeventkit" }, + { name = "nest-asyncio" }, + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/30/4d/dfc1da8224c3ffcdcd668da7283c4e5f14239a07f83ea66af99700296fc3/ib_async-2.1.0.tar.gz", hash = "sha256:6a03a87d6c06acacb0217a5bea60a8a168ecd5b5a7e86e1c73678d5b48cbc796", size = 87678, upload-time = "2025-12-08T01:42:32.004Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/80/e7/8f33801788c66f15e9250957ff7f53a8000843f79af1a3ed7a96def0e96b/ib_async-2.1.0-py3-none-any.whl", hash = "sha256:f6d8b991bdbd6dd38e700c61b3dced06ebe0f14be4e5263e2ef10ba10b88d434", size = 88876, upload-time = "2025-12-08T01:42:30.883Z" }, +] + +[[package]] +name = "ibgw" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "ib-async" }, +] + +[package.metadata] +requires-dist = [{ name = "ib-async", specifier = ">=0.9.86" }] + +[[package]] +name = "nest-asyncio" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418, upload-time = "2024-01-21T14:25:19.227Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" }, +] + +[[package]] +name = "numpy" +version = "2.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/ad/fed0499ce6a338d2a03ebae59cd15093910c8875328855781952abf6c2fe/numpy-2.4.6.tar.gz", hash = "sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda", size = 20735807, upload-time = "2026-05-18T23:37:14.07Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/91/3ab2044d05fd16d343c5ac2e69b127f1b2854040dd20b193257c78028bd3/numpy-2.4.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06ca2f61ec4385a07a6977c55ba998a4466c123642b4a32694d3128fce18c079", size = 16683458, upload-time = "2026-05-18T23:35:38.353Z" }, + { url = "https://files.pythonhosted.org/packages/8e/62/764ce66fa4147ae6d73071a3abf804ffe606f174618697c571acdf26a7c9/numpy-2.4.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:38efbc8de75c7a0fc1ac190162d892787f3f47b57cc291231aafee36b80982b7", size = 14704559, upload-time = "2026-05-18T23:35:42.14Z" }, + { url = "https://files.pythonhosted.org/packages/60/61/23f27c172f022e04025b7dc2367f4d63c1a398120607ec896228649a6f48/numpy-2.4.6-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:d581b735e177fdcdce6fed8e7e8880a3fb6ee4e3653a3ac6af01c6f4c03effc5", size = 5209716, upload-time = "2026-05-18T23:35:45.377Z" }, + { url = "https://files.pythonhosted.org/packages/03/71/21cf70dc6ea3e3acb95fc53a265b2fc248b981f0194ceb5b475271b8809d/numpy-2.4.6-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:0a041d3d761dc3c35cc56ce0351506a02bcbc25f7b169f652435141a17db9096", size = 6543947, upload-time = "2026-05-18T23:35:47.926Z" }, + { url = "https://files.pythonhosted.org/packages/d5/91/64288395ee1799bd2e0b04a305dce9666da90c961e1f3fe982a05ee1c036/numpy-2.4.6-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40fdc1ae7125e518ea98e53e69a4ebc27e1fd50510c47b7ea130cf21e5e1d42b", size = 15685197, upload-time = "2026-05-18T23:35:50.863Z" }, + { url = "https://files.pythonhosted.org/packages/f3/eb/ebffaa97dc55502df69584a8f0dcf07f69a3e0b3e2323670a2722db9aa39/numpy-2.4.6-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a2c306dea656c12c68f51f4cea133cbe78ca7435eb28c735eac1d3ebe73be6e8", size = 16638245, upload-time = "2026-05-18T23:35:54.752Z" }, + { url = "https://files.pythonhosted.org/packages/b8/0b/54f9da33128d7e350fab89c7455902eeae70349ee52bddb448dc4a576f45/numpy-2.4.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:33111801a01c12a8a1e3721f0a9232f8cfc8ae2c6b7098167e6f623c6073f402", size = 17036587, upload-time = "2026-05-18T23:35:58.355Z" }, + { url = "https://files.pythonhosted.org/packages/b6/f0/fdebc1052db1cc37c64beb22072d67cd6d1c71adca1299f53dec2b5e20d3/numpy-2.4.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ae506e6902902557576a26ff33eda8695e7ecb3cb36c3b573a0765dee114ebdb", size = 18363226, upload-time = "2026-05-18T23:36:02.845Z" }, + { url = "https://files.pythonhosted.org/packages/aa/b4/298628d98c72b57e57f7165ae6a481a1deaf6f3c28262a6e4c739c275930/numpy-2.4.6-cp314-cp314-win32.whl", hash = "sha256:aaf159caa35993cb1f56fb9b8e4610d35758e7ca005412eb1daa856a78c9c4b1", size = 6010196, upload-time = "2026-05-18T23:36:05.92Z" }, + { url = "https://files.pythonhosted.org/packages/df/ac/46de6dda46478f7942f839e094970be2d4a861e005c4b3bf07c92e291a09/numpy-2.4.6-cp314-cp314-win_amd64.whl", hash = "sha256:b507f5c4c1d508876d1819b6bf9a49d365b96320b5d4993426b33a23ca4b8261", size = 12450334, upload-time = "2026-05-18T23:36:09.107Z" }, + { url = "https://files.pythonhosted.org/packages/78/92/b8b798ac784102c0da830d2257d59358e3d3d90d1e2b3f2575dad976c5cf/numpy-2.4.6-cp314-cp314-win_arm64.whl", hash = "sha256:6f41ae150c4e32db4f3310cdaf64b1593a03dbabe29eec77fc9b50fe64061df6", size = 10495678, upload-time = "2026-05-18T23:36:12.766Z" }, + { url = "https://files.pythonhosted.org/packages/30/34/ec28d1aa8115971537c01469ab2011ee96827930f0a124de1000cc2a7ed7/numpy-2.4.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ece3d2cfe132e7d51f44a832b303895e6f2d499c5e74dfbdb06ee246147a304a", size = 14823672, upload-time = "2026-05-18T23:36:16.473Z" }, + { url = "https://files.pythonhosted.org/packages/16/bd/f6d1fede4e54e8042a7ff97bb495510f3c220f94bcd9e8b228e87c92cc0d/numpy-2.4.6-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:e3e5193ef5a3dc73bceee50f7fdc2c90dbb76c42df8d8fae3d1067a583df579e", size = 5328731, upload-time = "2026-05-18T23:36:19.767Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f0/e105b9e2fd728a9910103884decd6951d9dd73896b914a98d9a231de02ee/numpy-2.4.6-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:17f9ade344e7d9b464a084d69bcf18fc691cb1db67c62ed80820bf4926d78f0e", size = 6649805, upload-time = "2026-05-18T23:36:22.266Z" }, + { url = "https://files.pythonhosted.org/packages/82/dd/1206a7ca6ab15e3f02069707ca96222e202af681bb73756da7527f3cb837/numpy-2.4.6-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cd5ffd25db4e7ba6a375693b3fc0fc1791ec636c17db3720da19bde7180ec43", size = 15730496, upload-time = "2026-05-18T23:36:25.713Z" }, + { url = "https://files.pythonhosted.org/packages/51/e7/38d3ea825dcab85a591734decb2f6c67caa7c8367d374df1a1c3842f9b07/numpy-2.4.6-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d92c3819208a60205a12a245c91ad70cb0a85336659b19b834205573ac8456e", size = 16679616, upload-time = "2026-05-18T23:36:29.652Z" }, + { url = "https://files.pythonhosted.org/packages/93/b7/caabfdf53edf663e0b4eb74d7d405d83baef09eb5e83bcd32d601d72b93e/numpy-2.4.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e85b752a1e912b70eaad4fafbd4d1238007ab221de2009b9a2f5ae7461239895", size = 17085145, upload-time = "2026-05-18T23:36:33.449Z" }, + { url = "https://files.pythonhosted.org/packages/f9/45/68d7c33a6bcf3e5aa3bdbd57a367e6f615286dfd6482f97e8ffeb734306e/numpy-2.4.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:29cb7f67d10b479ff07c17d33e39f78c07f71c40ef30d63c153d340e96cd3fb4", size = 18403813, upload-time = "2026-05-18T23:36:37.369Z" }, + { url = "https://files.pythonhosted.org/packages/9c/50/0753655aa844c99cd9e018aacf76f130f1bd81d881bb74bc0aef5d73a8ba/numpy-2.4.6-cp314-cp314t-win32.whl", hash = "sha256:260a5d70215b61ab4fadf5c7baacd64821842975eea312125ed3c39a6391b063", size = 6156982, upload-time = "2026-05-18T23:36:40.817Z" }, + { url = "https://files.pythonhosted.org/packages/b2/d4/7c67becf668f973cb490cec3e98dfd799d866f9c989a54d355672cfa0db6/numpy-2.4.6-cp314-cp314t-win_amd64.whl", hash = "sha256:81a1cca95ed5bb92aa8b10dd2cdc9a0d3853a50fad926c28b5d7e8ea54389627", size = 12638908, upload-time = "2026-05-18T23:36:43.996Z" }, + { url = "https://files.pythonhosted.org/packages/43/bb/e1c71a4295b1b1d1393d50dbb4f2a36283c6859d9d3892e84f00ec5a91d5/numpy-2.4.6-cp314-cp314t-win_arm64.whl", hash = "sha256:0c9136e14ed34a9e343a31c533d78a9813a69a3148332bce5e9821cb2f996e66", size = 10565867, upload-time = "2026-05-18T23:36:47.114Z" }, +] + +[[package]] +name = "tzdata" +version = "2025.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, +]