futu_algo: a Hong Kong equities backtester and paper trader on Futu OpenAPI
Futu Algorithmic Trading Solution (Python) 基於富途OpenAPI所開發量化交易程序
At a glance
- What is it?
- futu_algo caches Futu K-lines locally, runs TDX-style strategies through a cost-accurate backtester and then trades the same signals on a paper account, with a web console served by one Python process.
- Who is it for?
- Adopt futu_algo if you trade Hong Kong equities through Futu OpenAPI and want one codebase for backtest, paper trading and a browser console, and try the demo mode before touching a live account. Do not expect a strategy edge out of the box, since the built-in signals are standard TDX indicators, and check the OpenD quote rights and the web token settings before exposing the console.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One codebase covers cache, backtest and paper account
The project targets one market and one broker API: Hong Kong equities on Futu OpenAPI. Everything else follows from that. There is a local Parquet cache of Futu K-lines, a set of strategies written in the TDX style, a backtester that prices Hong Kong transaction costs, a server-side screener, and a paper trading engine, all reachable from a web console or from the command line. The claim that ties it together is that the live engine and the backtester share the same strategy code and entry rules, and that the test suite replays real one-minute bars through both and requires every fill, fee and the final equity to match exactly. That is the design decision worth evaluating. A strategy that behaves differently once it goes live is the classic failure of home-grown trading code, and the answer here is that the same code path computes the signal in both places. The package version in pyproject.toml is 2.1.0, requires Python 3.11 or newer, and depends on futu-api, pandas, numpy, pyarrow, pydantic, pyyaml, fastapi and uvicorn.
Bars are assembled session by session, not across the lunch break
The data layer has more care in it than a typical downloader. The README says K-lines are downloaded into a Parquet cache, paging past the 1,000-bar page limit, while staying within Futu's rate limits and history quota. The detail that matters for Hong Kong equities is that any minute multiple, 10M, 2H or 4H for instance, is built session by session and never across the lunch break. Aggregating a full day into bars without splitting the session produces artefacts, and this design avoids them. History quota is also a hard constraint rather than a soft one, which is why the screener is designed to run filters on Futu's servers over the whole Hong Kong market without using that quota, with a strategy optionally confirming the result. In other words the system splits its work: cached bars for backtesting and chart work, server-side queries for discovery, so a market-wide scan does not eat the same budget as a backtest run.
TDX-exact indicators, with a check for future functions
The bundled strategies are named in the README: macd, kdj, rsi, ma_cross, ema_ribbon, boll and donchian, all implemented on TDX-exact indicators, meaning the formulas match the TDX style trading terminal common in Chinese markets rather than approximating them. The README also states that writing your own takes a few lines and that every backtest checks it for future functions. That check is the important part for anyone extending the set. A signal that reads a bar before it closes is the single most common way a backtest manufactures returns that cannot be reproduced live, and an automatic check turns that from a review item into a build failure. The strategy surface is deliberately modest. These are well known oscillators and channel rules with no claims attached, so the value of the framework is in the execution and accounting layer, not in the signals themselves.
Stamp duty, levies and the tick table decide the backtest
The backtester fills at the next open, in whole board lots, and it applies the costs that make Hong Kong results differ from other markets: HK stamp duty and levies on the schedule in force each day, and slippage from the HKEX tick table. Costs are dated rather than fixed, so a schedule change is a configuration fact rather than a code change. Stops and targets are supported, the run works in either portfolio mode or per-symbol mode, and the Hang Seng Index can be used as a benchmark. The report view is a tear sheet with headline metrics, equity against the benchmark and against buy and hold, drawdown, monthly returns, the distribution of trade returns, drawdown periods and every individual trade. None of that is exotic, but each item is the difference between a backtest that reflects the market and one that flatters itself. On fees alone, a strategy that clears a small gross spread can still lose money once duty and tick-sized slippage are applied.
Paper trading re-prices and reconciles, and survives restarts
The paper engine runs on live bars pushed by OpenD at one-minute resolution or any other, sends tick-rounded limit orders to your Futu paper account, re-prices unfilled orders, reconciles fills, enforces risk limits and survives restarts. Tick rounding is the detail that connects this engine to the backtester, because a limit price that is not on the tick grid is not a price the exchange will accept. The risk limits are enforced in the engine rather than left to the strategy, which is the correct place for them, since a strategy bug should not be able to exceed an account limit. Restart survival matters for an intraday system, where a laptop sleep or a broker reconnect should not leave orphaned orders. The engine also exposes controls in the console header, namely start, halt entries, cancel all, flatten and stop, so an operator can act without editing the configuration.
The console is one process with its own fonts and chart library
The web console is a single-page app served by the same process as the engine, with no build step and nothing loaded from the internet. Fonts and the chart library ship inside the package, and a strict Content-Security-Policy allows only same-origin scripts. That constraint is unusual in a trading tool and it matters operationally, since a console that can serve remote scripts is a console that can be tampered with on a machine holding live credentials. The pages cover a live dashboard with equity, allocation, positions, working intents, open orders, fills and an event timeline, a watchlist quote board with session change and per-symbol strategy state, charts with indicator lines and fill markers, a stepped backtest builder, a screener, an order blotter, the bar cache with history quota, a YAML config editor with validation and the event log. The top bar shows the Hong Kong session as a timeline covering the auction, morning, lunch, afternoon and closing auction, with a count to the close.
Demo mode and a container for running without a broker session
Two entry points lower the barrier to trying it. The quick start clones the repository, creates a virtual environment, installs the package in editable mode and then launches the demo:
git clone https://github.com/billpwchan/futu_algo.git
cd futu_algo
python -m venv .venv && source .venv/bin/activate
pip install -e .
futu-algo web --demo --speed 30Demo mode runs on a simulated OpenD with a synthetic market and a virtual clock inside the Hong Kong session, and the engine starts automatically and trades six made-up stocks on one-minute bars, which needs no account at all. With a real OpenD session the flow is a sequence of commands:
futu-algo init config.yaml
futu-algo check -c config.yaml
futu-algo backtest -c config.yaml
futu-algo web -c config.yamlinit writes a commented starter config and an .env.example, check validates the config, OpenD, the quota and the paper account, backtest downloads data once and prints a summary, and web opens the console. A Dockerfile is also provided, and it makes the deployment constraints explicit:
FROM python:3.12-slim
ENTRYPOINT ["futu-algo"]
CMD ["web", "-c", "/work/config.yaml", "--engine"]The container runs the console on port 8765, OpenD runs on the host or in another container and is reached through futu.host, and if OpenD is not on the same host it needs an RSA key for trading. Exposing the console beyond localhost means setting web.host to 0.0.0.0, providing FUTU_ALGO_WEB_TOKEN and listing the browser hostnames in web.allowed_hosts.
Apache-2.0 code, but the release tags stopped in 2021
The licence is Apache-2.0, which covers both the source and, per the pyproject metadata, the packaged project, and it lets you modify and redistribute the code while keeping the notice. The maintenance story needs a second look. The repository is not archived and the last push was on 2026-10-22, so the code is being worked on. The GitHub release list, however, stops much earlier: version 0.1 for Futu Algo Trade (Alpha) on 2020-12-24 and version 0.2 for HFT Support on 2021-01-10, while the version in pyproject.toml is 2.1.0. The tags therefore do not describe the current code, and there is no tagged release to pin against. A CHANGELOG.md is present, so the change history lives in the repository rather than in releases. The project also carries a Dockerfile, a deploy directory and a CI workflow, so there is a container and test story, but your upgrade path is the main branch rather than a versioned artefact, and the dependency floor of futu-api 10.4 with Python 3.11 or newer is worth checking against the OpenD build you already run.
Editorial conclusion
Adopt futu_algo if you trade Hong Kong equities through Futu OpenAPI and want one codebase for backtest, paper trading and a browser console, and try the demo mode before touching a live account. Do not expect a strategy edge out of the box, since the built-in signals are standard TDX indicators, and check the OpenD quote rights and the web token settings before exposing the console.
Frequently asked questions
How do I try futu_algo without a Futu account?
Run futu-algo web --demo --speed 30, which starts the console on a simulated OpenD with a synthetic market and a virtual clock inside the Hong Kong session, trading six made-up stocks on one-minute bars. Open http://127.0.0.1:8765/ afterwards.
What does futu_algo check before a backtest runs?
The check command validates the config, the OpenD connection, the history quota and the paper account. The backtest command then downloads the data once, prints a summary and saves a report.
Does the futu_algo backtest include Hong Kong trading costs?
Yes. Fills are at the next open in whole board lots, with HK stamp duty and levies applied on the schedule in force each day and slippage taken from the HKEX tick table. The Hang Seng Index can be used as a benchmark.
How do I run futu_algo in Docker?
The image is built on python:3.12-slim, exposes port 8765 and runs futu-algo web -c /work/config.yaml --engine by default. OpenD runs on the host or in another container and is reached through futu.host, and a config.yaml with its .env should be mounted at /work.
Which strategies ship with futu_algo?
The bundled set is macd, kdj, rsi, ma_cross, ema_ribbon, boll and donchian, implemented on TDX-exact indicators. You can add your own in a few lines, and every backtest checks a strategy for future functions.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/billpwchan-futu-algo)Was this useful?