Skip to content

whtis/ibkr-mobile

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

3 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

ibkr-mobile

A personal Android trading client for Interactive Brokers, with UI inspired by Longbridge / ้•ฟๆกฅ่ฏๅˆธ.

License: MIT Kotlin Compose FastAPI ib_async

Built because the official IBKR mobile app is slow, ugly, and missing the things a Longbridge user takes for granted: snappy K-lines with crosshair, intraday session classification (็›˜ๅ‰ / ็›˜ไธญ / ็›˜ๅŽ / ๅคœ็›˜), red-up / green-down (็บขๆถจ็ปฟ่ทŒ), aggregated positions PnL, one-tap quick-actions on long-press, and a UI that doesn't look like it was designed in 2008.

โš ๏ธ Disclaimer This is a personal project for educational purposes. It is not financial advice, not affiliated with Interactive Brokers or Longbridge, and is provided as-is with no warranty. Trading involves substantial risk of loss. Use a paper account first. You are solely responsible for any orders submitted through this software.


Screenshots

Positions K-line chart with MA + MACD + cost basis Intraday with VWAP and 4-channel session colors Market overview

From left: Positions with aggregated PnL ยท K-line with MA/MACD/cost basis ยท Intraday with VWAP and pre/regular/post/overnight session coloring ยท Market overview with movers

More screenshots

Long-press quick actions Company info Financials Watchlist empty state

Long-press quick actions ยท Company panorama ยท Financials ยท Watchlist empty state

All screenshots are from the bundled mock mode running against a freshly-built emulator โ€” no real account is needed to see the app like this. See Quickstart below.


Try it in 60 seconds (mock mode)

Don't have an IBKR or LongPort account and just want to look around?

git clone https://github.com/whtis/ibkr-mobile.git
cd ibkr-mobile/backend
cp .env.example .env
echo "MOCK_MODE=yes" >> .env          # one line is the only required change
echo "API_TOKEN=anything-you-want" >> .env
uv sync
uv run uvicorn app.main:app --host 0.0.0.0 --port 8000

Then in another shell:

cd ibkr-mobile/android
./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk

Open the app โ†’ Settings โ†’ backend URL http://10.0.2.2:8000 (emulator) or http://<your-LAN-ip>:8000 (real device), token = whatever you put in .env โ†’ save. Done. Mock mode serves a synthesized portfolio of AAPL, TSLA, NVDA, MSFT, GOOGL, BABA, SPY with realistic K-lines, intraday charts, and option chains.


Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Android App (Kotlin + Jetpack Compose) โ”‚
โ”‚  - Material 3, Canvas charts            โ”‚
โ”‚  - WebSocket realtime quotes            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚  HTTPS + Bearer token
                   โ”‚  (LAN Wi-Fi, Tailscale, or public TLS)
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  FastAPI + ib_async                     โ”‚
โ”‚  - REST + WebSocket                     โ”‚
โ”‚  - SQLite (execution history)           โ”‚
โ”‚  - LongPort SDK (free L1 quotes)        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚  TWS binary socket :4002 (paper) / :4001 (live)
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  IB Gateway in Docker (gnzsnz image)    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
              IBKR servers

The backend is the only place that holds IBKR credentials. The Android app authenticates via a bearer token, configurable in Settings. No credentials, accounts, or executions ever live on the phone outside of an OS-protected DataStore.


Features

๐Ÿ“ˆ Market

  • Watchlist with auto-refresh and pull-to-update
  • Search by symbol with debounced lookup
  • Stock detail page with three sub-tabs (่กŒๆƒ… / ๅ…จๆ™ฏ / ่ดขๅŠก):
    • Native Canvas K-line chart (1m / 5m / 15m / 30m / 60m / 1d / 1w / 1mo) with crosshair, zoom, pan
    • Intraday chart with 4-channel session classification (pre-market / regular / after-hours / overnight)
    • MACD sub-chart with linked crosshair
    • Company info + key metrics (P/E TTM, P/B, EPS, BPS, dividend yield)
  • Fullscreen chart mode (landscape lock + larger viewport)
  • Option chain browser with strike grid and side/expiry selector

๐Ÿ’ผ Positions

  • Aggregated PnL across positions (more accurate than IBKR per-account summary)
  • Four sort modes: market value / unrealized PnL / daily PnL / symbol
  • Long-press quick actions: ๅŠ ไป“ / ๅ‡ไป“ / ๆŸฅ็œ‹่ฏฆๆƒ… / ๅคๅˆถไปฃ็ 
  • Active orders panel with one-tap cancel

๐Ÿ›’ Orders

  • Market / Limit / Stop / Stop-Limit
  • TIF: DAY / GTC / IOC / FOK
  • RTH-only toggle
  • Stocks + Options (with expiry / strike / right pre-filled from option chain)
  • Live preview of margin impact

โšก Realtime

  • Single WebSocket multiplex with ref-counted subscriptions
  • Auto-reconnect with exponential backoff
  • LongPort L1 stream (free, real-time) + IBKR fallback

๐ŸŽจ Polish

  • ็บขๆถจ็ปฟ่ทŒ (Chinese convention: red = up, green = down)
  • Material 3 dark theme tuned to Longbridge palette
  • Adaptive icon (animated C pulse)
  • Bottom-bar navigation, 4 tabs (่‡ช้€‰ / ่กŒๆƒ… / ๆŒไป“ / ่ฎพ็ฝฎ)

Tech stack

Backend (backend/)

  • FastAPI, Uvicorn, Pydantic v2
  • ib_async 2.1.0 โ€” modern async IBKR API client
  • longport Python SDK 3.0.23 โ€” free L1 quotes + K-lines
  • SQLite for execution history persistence
  • uv for dependency management
  • Docker Compose + gnzsnz/ib-gateway

Android (android/)

  • Kotlin 2.1.20, Jetpack Compose BOM 2026.05.01
  • Material 3
  • Navigation Compose 2.9.8
  • Ktor + OkHttp engine (HTTP + WebSocket)
  • DataStore (settings persistence)
  • kotlinx.serialization (JSON)
  • Compose Canvas (native charts โ€” no WebView)
  • AGP 8.10.1 / Gradle 8.13 / minSdk 26 / compileSdk 36

Quickstart

1. Backend

cd backend
cp .env.example .env

# edit .env โ€” at minimum:
#   TWS_USERID=<your IBKR paper-trading username>
#   TWS_PASSWORD=<your IBKR paper-trading password>
#   API_TOKEN=$(openssl rand -hex 32)
#   LONGPORT_APP_KEY / SECRET / ACCESS_TOKEN โ€” optional, but recommended for free quotes
#     (get at https://open.longportapp.com โ†’ Developer Center โ†’ Create App)
#
# OR: skip the IBKR + LongPort fields entirely and set MOCK_MODE=yes for synthetic data.
# See "Try it in 60 seconds" above.

# pull and start IB Gateway (Docker)
docker compose pull
docker compose up -d

# wait ~30s, watch Gateway login
docker compose logs -f ibgateway     # look for "API server listening on port 4002"

# install Python deps (first time only)
uv sync

# run FastAPI
uv run uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload

Verify:

TOKEN=$(grep ^API_TOKEN .env | cut -d= -f2)
curl -s http://localhost:8000/health | jq                  # ib_connected: true
curl -s -H "Authorization: Bearer $TOKEN" \
  http://localhost:8000/account/positions | jq

See backend/README.md for the full smoke-test set and troubleshooting.

2. Android

cd android
./gradlew assembleDebug
# APK at: app/build/outputs/apk/debug/app-debug.apk

Install on device:

adb install -r app/build/outputs/apk/debug/app-debug.apk

Open the app โ†’ Settings tab โ†’ fill in:

  • Backend URL: http://<Mac LAN IP>:8000 (or https://your.domain if cloud-hosted)
  • API Token: same value as API_TOKEN in backend .env
  • Tap ๆต‹่ฏ•่ฟžๆŽฅ โ†’ should turn green
  • Tap ไฟๅญ˜

Now the Positions / Market / Watchlist tabs will populate from your paper account.

3. (Optional) Cloud deployment

Quote-only deployments (LongPort quotes without IBKR trading) can run on any small VPS โ€” no Mac required for the Gateway:

# on your server
git clone <this repo>
cd ibkr-mobile/backend
cp .env.example .env
# fill LONGPORT_* keys, leave TWS_* blank or set READ_ONLY_API=yes
uv sync
# put behind nginx + Let's Encrypt + systemd, point your domain at it

Full IBKR trading needs IB Gateway, which has stricter networking + 2FA requirements. The Mac-as-gateway model is recommended for the trading path; the VPS can serve as a public quote endpoint.


Project layout

ibkr-mobile/
โ”œโ”€โ”€ android/                   Kotlin + Compose app
โ”‚   โ”œโ”€โ”€ app/src/main/
โ”‚   โ”‚   โ”œโ”€โ”€ java/com/tis/ibkr/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ data/          API client, DataStore, models
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ ui/screens/    Watchlist, Market, Positions, StockDetail, ...
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ ui/components/ Charts, sub-bars, quick-action sheet
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ ui/theme/      Longbridge-inspired Material 3 theme
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ viewmodel/     One ViewModel per screen
โ”‚   โ”‚   โ””โ”€โ”€ res/               icons (adaptive), strings
โ”‚   โ””โ”€โ”€ gradle/libs.versions.toml
โ”œโ”€โ”€ backend/                   FastAPI + ib_async
โ”‚   โ”œโ”€โ”€ app/
โ”‚   โ”‚   โ”œโ”€โ”€ main.py            FastAPI app, lifespan, CORS
โ”‚   โ”‚   โ”œโ”€โ”€ ibkr.py            IB Gateway connector
โ”‚   โ”‚   โ”œโ”€โ”€ longbridge.py      LongPort SDK wrapper
โ”‚   โ”‚   โ”œโ”€โ”€ db.py              SQLite executions store
โ”‚   โ”‚   โ”œโ”€โ”€ auth.py            Bearer auth dependency
โ”‚   โ”‚   โ””โ”€โ”€ routes/
โ”‚   โ”‚       โ”œโ”€โ”€ account.py     summary, positions
โ”‚   โ”‚       โ”œโ”€โ”€ orders.py      place, cancel, list active
โ”‚   โ”‚       โ”œโ”€โ”€ executions.py  history (SQLite + ib_async)
โ”‚   โ”‚       โ”œโ”€โ”€ options.py     option chain, contract lookup
โ”‚   โ”‚       โ”œโ”€โ”€ quote.py       quote, intraday, bars (K-line)
โ”‚   โ”‚       โ””โ”€โ”€ ws_quotes.py   WebSocket realtime stream
โ”‚   โ”œโ”€โ”€ docker-compose.yml     IB Gateway container
โ”‚   โ””โ”€โ”€ pyproject.toml
โ”œโ”€โ”€ BUILD.md                   Architecture decisions
โ”œโ”€โ”€ DESIGN_NOTES.md            UI/UX spec referencing Longbridge
โ”œโ”€โ”€ ONBOARDING.md              Setup gotchas (IBKR auth quirks, etc.)
โ””โ”€โ”€ README.md                  โ† you are here

Why these choices

Decision Reason
Compose Canvas charts (not WebView) First paint ~50 ms vs ~800 ms for a WebView+JS chart lib. Memory ~5 MB vs ~50 MB.
LongPort SDK + IBKR fallback LongPort gives free real-time L1 + K-lines for US + HK + CN; IBKR market data is paid. Trading still goes through IBKR.
ib_async over ibapi/ib-insync ib-insync is no longer maintained; ib_async is its modern fork, native async, type-hinted.
gnzsnz/ib-gateway in Docker Headless IB Gateway with IBC auto-login, VNC for debugging, daily restart. Avoids manual Gateway baby-sitting.
One Mac as the gateway host Gateway needs persistent network identity + 2FA approval. A always-on Mac is simpler than fighting Docker NAT + cloud IP rotation.
WebSocket subscription multiplex with refcounts Multiple Compose screens can subscribe to the same symbol cheaply; cleanup is automatic when the last subscriber leaves.
SQLite execution history IBKR reqExecutions only returns 7 days. Local persistence preserves full history.
uv over pip ~10ร— faster install, lockfile, pyproject-native.

Documentation


Status

  • v1: shipped, in personal daily use. Single-user, paper account.
  • v2: design complete, implementation pending โ€” see ROADMAP.md. Adds per-device multi-user, moves Longbridge SDK in-app, makes the backend credential-free.

Active development. APIs and screens may change without notice.

Tested with: Pixel-class Android devices and emulators, IBKR paper account, LongPort developer account.


Contributing

PRs are welcome, especially ones aligned with ROADMAP.md. For anything non-trivial, please open an issue first so we can discuss direction before you write the code.

See CONTRIBUTING.md for dev setup, code style, what kinds of PRs are most likely to land, and what to avoid. Note that mock mode (described in Quickstart above) lets you contribute without any brokerage credentials โ€” start there.

Looking for somewhere to start? Check the good first issue and help wanted labels.

This project follows a Code of Conduct.


License

MIT. See LICENSE.

The MIT license grants you broad rights, but it does not grant you a right to safety. Read the disclaimer above. Trade with money you can afford to lose.


Built by @whtis. Contributions from anyone who finds it useful.

About

Personal Android trading client for Interactive Brokers, UI inspired by Longbridge. FastAPI + ib_async backend, Kotlin + Compose app with native Canvas charts.

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors