Skip to main content

QTrader: A Light Event-Driven Algorithmic Trading Engine

Latest update on 2022-07-20

QTrader is a light and flexible event-driven algorithmic trading engine that can be used to backtest strategies, and seamlessly switch to live trading without any pain.

Key Features

  • Completely same code for backtesting / simulation / live trading

  • Support trading of various assets: equity, futures

  • Resourceful functionalities to support live monitoring and analysis

Quick Install

You may run the folllowing command to install QTrader immediately:

# Virtual environment is recommended (python 3.8 or above is supported)
>> conda create -n qtrader python=3.8
>> conda activate qtrader

# Install stable version from pip (currently version 0.0.2)
>> pip install qtrader

# Alternatively, install latest version from github 
>> pip install git+https://github.com/josephchenhk/qtrader@master

Prepare the Data

QTrader supports bar data at the moment. What you need to do is creating a folder with the name of the security you are interested in. Let's say you want to backtest or trade HK equity "HK.01157" in frequency of 1 minute, your data folder should be like this (where "K_1M" stands for 1 minute; you can also find a sample from the qtrader/examples/data):

alt text

And you can prepare OHLCV data in CSV format, with dates as their file names, e.g., "yyyy-mm-dd.csv":

alt text

Inside each csv file, the data columns should look like this:

alt text

Now you can specify the path of data folder in qtrader/config/config.py. For example, set

DATA_PATH = {
    "kline": "path_to_your_qtrader_folder/examples/data/k_line",
}

Implement a Strategy

To implement a strategy is simple in QTrader. A strategy needs to implement init_strategy and on_bar methods in BaseStrategy. Here is a quick sample:

from qtrader.core.strategy import BaseStrategy

class MyStrategy(BaseStrategy):

    def init_strategy(self):
        pass

    def on_bar(self, cur_data:Dict[str, Dict[Security, Bar]]):
        print(cur_data)

Record Variables

QTrader provides a module named BarEventEngineRecorder to record variables during backtesting and/or trading. By default it saves datetime, portfolio_value and action at every time step.

If you want to record additional variables (let's say it is called var), you need to write a method called get_var in your strategy:

from qtrader.core.strategy import BaseStrategy

class MyStrategy(BaseStrategy):

    def get_var(self):
        return var

And initialize your BarEventEngineRecorder with the same vairable var=[](if you want to record every timestep) or var=None(if you want to record only the last updated value):

recorder = BarEventEngineRecorder(var=[])

Run a Backtest

Now we are ready to run a backtest. Here is a sample of running a backtest in QTrader:

# Security 
stock_list = [
    Stock(code="HK.01157", lot_size=100, security_name="中联重科", exchange=Exchange.SEHK),
]

# Gateway
gateway_name = "Backtest"
gateway = BacktestGateway(
    securities=stock_list,
    start=datetime(2021, 3, 15, 9, 30, 0, 0),
    end=datetime(2021, 3, 17, 16, 0, 0, 0),
    gateway_name=gateway_name,
)
gateway.SHORT_INTEREST_RATE = 0.0
gateway.set_trade_mode(TradeMode.BACKTEST)

# Core engine
engine = Engine(gateways={gateway_name: gateway})

# Strategy initialization
init_capital = 100000
strategy_account = "DemoStrategy"
strategy_version = "1.0"
strategy = DemoStrategy(
    securities={gateway_name: stock_list},
    strategy_account=strategy_account,
    strategy_version=strategy_version,
    init_strategy_cash={gateway_name: init_capital},
    engine=engine,
    strategy_trading_sessions={
        "HK.01157": [
            [datetime(1970, 1, 1, 9, 30, 0), datetime(1970, 1, 1, 12, 0, 0)],
            [datetime(1970, 1, 1, 13, 0, 0), datetime(1970, 1, 1, 16, 0, 0)],
        ],
)
strategy.init_strategy()

# Recorder
recorder = BarEventEngineRecorder()

# Event engine
event_engine = BarEventEngine(
    {"demo": strategy},
    {"demo": recorder},
    engine
)

# Start event engine
event_engine.run()

# Program terminates normally
engine.log.info("Program shutdown normally.")

After shutdown, you will be able to find the results in qtrader/results, with the folder name of latest time stamp:

alt text

The result.csv file saves everything you want to record in BarEventEngineRecorder; while pnl.html is an interactive plot of the equity curve of your running strategy:

alt text

Simulation / Live trading

Ok, your strategy looks good now. How can you put it to paper trading and/or live trading? In QTrader it is extremely easy to switch from backtest mode to simulation or live trading mode. What you need to modify is just two lines (replace a backtest gateway with a live trading gateway!):

# Currently you can use "Futu", "Ib", and "Cqg" 
gateway_name = "Futu"  

# Use FutuGateway, IbGateway, or CqgGateway accordingly
# End time should be set to a future time stamp when you expect the program terminates
gateway = FutuGateway(
    securities=stock_list,
    end=datetime(2022, 12, 31, 16, 0, 0, 0),  
    gateway_name=gateway_name,
)

# Choose either TradeMode.SIMULATE or TradeMode.LIVETRADE
gateway.set_trade_mode(TradeMode.LIVETRADE)

That's it! You switch from backtest to simulation / live trading mode now.

Important Notice: In the demo sample, the live trading mode will keep on sending orders, please be aware of the risk when running it.

Live Monitoring

When running the strategies, the trader typically needs to monitor the market and see whether the signals are triggered as expected. QTrader provides with such dashboard(visualization panel) which can dynamically update the market data and gives out entry and exit signals in line with the strategies.

You can activate this function in your config.py:

ACTIVATED_PLUGINS = [.., "monitor"]

After running the main script, you will be able to open a web-based monitor in the browser: 127.0.0.1:8050:

alt text

QTrader is also equipped with a Telegram Bot, which allows you get instant information from your trading program. To enable this function, you can add your telegram information in qtrader.config.config.py(you can refer to the following link for detailed guidance):

ACTIVATED_PLUGINS = [.., "telegram"]

TELEGRAM_TOKEN = "50XXXXXX16:AAGan6nFgmrSOx9vJipwmXXXXXXXXXXXM3E"
TELEGRAM_CHAT_ID = 21XXXXXX49

In this way, your mobile phone with telegram will automatically receive a documenting message:

You can use your mobile phone to monitor and control your strategy now.

Contributing

  • Fork it (https://github.com/josephchenhk/qtrader/fork)
  • Study how it's implemented.
  • Create your feature branch (git checkout -b my-new-feature).
  • Use flake8 to ensure your code format complies with PEP8.
  • Commit your changes (git commit -am 'Add some feature').
  • Push to the branch (git push origin my-new-feature).
  • Create a new Pull Request.

Metadata

Release files for qtrader 0.0.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for qtrader 0.0.4
File Size Uploaded Provenance Actions
qtrader-0.0.4.tar.gz 4.0 MB Without provenance Details for qtrader-0.0.4.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for qtrader 0.0.4
File Interpreter ABI Platform Actions
qtrader-0.0.4-py3-none-any.whl Python 3 none any Details for qtrader-0.0.4-py3-none-any.whl

Total release size: 6.2 MB

Release files / qtrader-0.0.4.tar.gz

Download URL qtrader-0.0.4.tar.gz
Size 4.0 MB
Tags Source
SHA-256 checksum
How to use checksums
a7baa5893eadf103a9db23cdf5ff6a187c3abb2ee663f8ce5de2288b490464f6
BLAKE2b-256 checksum
How to use checksums
bffe55460c95f902c5d4d4580879ad4ec9774725dca1b9855c586822d4d61c58
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.2.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.6.3 requests-toolbelt/0.9.1 tqdm/4.48.2 CPython/3.7.1

Release files / qtrader-0.0.4-py3-none-any.whl

Download URL qtrader-0.0.4-py3-none-any.whl
Size 2.2 MB
Tags Python 3
SHA-256 checksum
How to use checksums
c3950ead0f5fbb067cb41ebd2db1ee067bfbe0207b33da87f19da440279e92c3
BLAKE2b-256 checksum
How to use checksums
e81c5c097f99c060ce5adeb492d51fe67db04242145e592676cba29e6c99d2f0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.2.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.6.3 requests-toolbelt/0.9.1 tqdm/4.48.2 CPython/3.7.1

Security for qtrader 0.0.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page