Package: qtrader
QTrader: A Light Event-Driven Algorithmic Trading EngineLatest update on 2022-07-20QTrader 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 FeaturesCompletelysame codefor backtesting / simulation / live tradingSupport trading of various assets: equity, futuresResourceful functionalities to support live monitoring and analysisQuick InstallYou may run the folllowing command to install QTrader immediately:# Virtual environment is recommended (python 3.8 or above is supported)>>condacreate-nqtraderpython=3.8>>condaactivateqtrader# Install stable version from pip (currently version 0.0.2)>>pipinstallqtrader# Alternatively, install latest version from github>>pipinstallgit+https://github.com/josephchenhk/qtrader@masterPrepare the DataQTrader 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 of1 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):And you can prepare OHLCV data in CSV format, with dates as their file names,
e.g.,"yyyy-mm-dd.csv":Inside each csv file, the data columns should look like this:Now you can specify the path of data folder inqtrader/config/config.py. For
example, setDATA_PATH={"kline":"path_to_your_qtrader_folder/examples/data/k_line",}Implement a StrategyTo implement a strategy is simple in QTrader. A strategy needs to implementinit_strategyandon_barmethods inBaseStrategy. Here is a quick sample:fromqtrader.core.strategyimportBaseStrategyclassMyStrategy(BaseStrategy):definit_strategy(self):passdefon_bar(self,cur_data:Dict[str,Dict[Security,Bar]]):print(cur_data)Record VariablesQTrader provides a module namedBarEventEngineRecorderto record variables
during backtesting and/or trading. By default it savesdatetime,portfolio_valueandactionat every time step.If you want to record additional variables (let's say it is calledvar), you
need to write a method calledget_varin your strategy:fromqtrader.core.strategyimportBaseStrategyclassMyStrategy(BaseStrategy):defget_var(self):returnvarAnd initialize yourBarEventEngineRecorderwith the same vairablevar=[](if
you want to record every timestep) orvar=None(if you want to record only the
last updated value):recorder=BarEventEngineRecorder(var=[])Run a BacktestNow we are ready to run a backtest. Here is a sample of running a backtest in
QTrader:# Securitystock_list=[Stock(code="HK.01157",lot_size=100,security_name="中联重科",exchange=Exchange.SEHK),]# Gatewaygateway_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.0gateway.set_trade_mode(TradeMode.BACKTEST)# Core engineengine=Engine(gateways={gateway_name:gateway})# Strategy initializationinit_capital=100000strategy_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()# Recorderrecorder=BarEventEngineRecorder()# Event engineevent_engine=BarEventEngine({"demo":strategy},{"demo":recorder},engine)# Start event engineevent_engine.run()# Program terminates normallyengine.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:The result.csv file saves everything you want to record inBarEventEngineRecorder; while pnl.html is an interactive plot of the equity
curve of your running strategy:Simulation / Live tradingOk, 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 justtwolines (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 terminatesgateway=FutuGateway(securities=stock_list,end=datetime(2022,12,31,16,0,0,0),gateway_name=gateway_name,)# Choose either TradeMode.SIMULATE or TradeMode.LIVETRADEgateway.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 MonitoringWhen running the strategies, the trader typically needs to monitor the market
and see whether the signals are triggered as expected. QTrader provides with
suchdashboard(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 yourconfig.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:QTrader is also equipped with aTelegram Bot, which allows you get instant
information from your trading program. To enable this function, you can add your
telegram information inqtrader.config.config.py(you can refer to the
followinglinkfor detailed guidance):ACTIVATED_PLUGINS=[..,"telegram"]TELEGRAM_TOKEN="50XXXXXX16:AAGan6nFgmrSOx9vJipwmXXXXXXXXXXXM3E"TELEGRAM_CHAT_ID=21XXXXXX49In 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.ContributingFork it (https://github.com/josephchenhk/qtrader/fork)Study how it's implemented.Create your feature branch (git checkout -b my-new-feature).Useflake8to 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.