AlgoTrader Reference Documentation
AlgoTrader Reference Documentation
AlgoTrader
Version 6.1.0
CONFIDENTIAL
Table of Contents
Preface .............................................................................................................................................. xvi
1. Document Conventions .......................................................................................................... xvi
1.1. Typographic Conventions ............................................................................................. xvi
1.2. Pull-quote Conventions ............................................................................................... xvii
1.3. Notes and Warnings .................................................................................................. xviii
1. Introduction .................................................................................................................................... 1
2. Installation and Deployment ........................................................................................................... 2
2.1. Windows Installer .................................................................................................................. 2
2.2. Development Environment Installation .................................................................................... 4
2.2.1. Prerequisites ............................................................................................................... 4
2.2.2. AlgoTrader Server Code Installation ........................................................................... 10
2.2.3. Python installation ..................................................................................................... 13
2.2.4. Next Steps ............................................................................................................... 13
2.3. Server Environment Installation ............................................................................................ 13
2.3.1. Docker based Installation .......................................................................................... 14
2.3.2. Docker Containers .................................................................................................... 15
2.3.3. Docker Compose ...................................................................................................... 20
2.3.4. Docker Management ................................................................................................. 25
2.4. VM Options ......................................................................................................................... 27
3. Starting AlgoTrader ...................................................................................................................... 28
3.1. Simulation Mode .................................................................................................................. 29
3.2. Live Trading Mode ............................................................................................................... 30
3.2.1. Embedded Mode ....................................................................................................... 30
3.2.2. Distributed Mode ....................................................................................................... 31
3.3. Server Environment ............................................................................................................. 32
3.3.1. Embedded Mode ....................................................................................................... 32
3.3.2. Distributed Mode ....................................................................................................... 34
4. Strategy Development .................................................................................................................. 36
4.1. Creating a Trading Strategy ................................................................................................. 36
4.1.1. AlgoTrader Strategy Wizard ....................................................................................... 36
4.1.2. AlgoTrader Maven Archetype ..................................................................................... 39
4.1.3. Generated Artifacts Java Archetype ........................................................................... 40
4.1.4. Generated Artifacts Simple Java Archetype ................................................................ 42
4.1.5. Generated Artifacts Esper Archetype .......................................................................... 45
4.2. Building a Trading Strategy .................................................................................................. 50
4.3. Hints for Strategy Development ............................................................................................ 51
4.3.1. Java based Strategies ............................................................................................... 51
4.3.2. Esper based Strategies ............................................................................................. 56
4.4. Strategy life-cycle events ..................................................................................................... 64
4.5. Strategy Development in Python ........................................................................................... 65
4.5.1. Python Strategy Performance .................................................................................... 68
5. Strategy Backtesting .................................................................................................................... 69
ii
CONFIDENTIAL
iii
CONFIDENTIAL
iv
CONFIDENTIAL
v
CONFIDENTIAL
vi
CONFIDENTIAL
vii
CONFIDENTIAL
viii
CONFIDENTIAL
ix
CONFIDENTIAL
x
CONFIDENTIAL
xi
CONFIDENTIAL
List of Figures
3.1. IntelliJ Run Configurations ............................................................................................................ 28
3.2. Run Configurations ...................................................................................................................... 29
4.1. Strategy Development Process ..................................................................................................... 36
5.1. Back Test Report ......................................................................................................................... 75
6.1. Architecture ................................................................................................................................. 79
7.1. Entities Overview ......................................................................................................................... 80
7.2. Strategy ...................................................................................................................................... 82
7.3. Securities .................................................................................................................................... 84
7.4. Orders ......................................................................................................................................... 88
7.5. Account ....................................................................................................................................... 89
7.6. Transaction ................................................................................................................................. 91
7.7. Position ....................................................................................................................................... 92
7.8. Subscription ................................................................................................................................. 93
7.9. Exchange .................................................................................................................................... 94
7.10. Order Preference ....................................................................................................................... 95
11.1. AlgoTrader UI Header .............................................................................................................. 134
11.2. AlgoTrader UI Toolbar .............................................................................................................. 134
11.3. AlgoTrader UI Settings ............................................................................................................. 136
11.4. AlgoTrader UI Notification ......................................................................................................... 137
11.5. AlgoTrader UI Alert List ............................................................................................................ 137
11.6. AlgoTrader UI Order Table ....................................................................................................... 138
11.7. AlgoTrader UI Manual Order Entry ............................................................................................ 138
11.8. AlgoTrader UI Manual Order Modification .................................................................................. 138
11.9. AlgoTrader UI Advanced Order Form ........................................................................................ 139
11.10. AlgoTrader UI Advanced Order Form - Routing section, Smart Routing switched off .................... 140
11.11. AlgoTrader UI Advanced Order Form - Routing section, Smart Routing switched on .................... 140
11.12. AlgoTrader UI Advanced Order Form - Routing section, Smart Routing disabled ......................... 141
11.13. AlgoTrader UI Advanced Order Form - Routing section, Smart Routing equivalent of Simple Order
Type ................................................................................................................................................ 141
11.14. Execution Algo details icon visible in action column in the Orders table ...................................... 142
11.15. Execution Algo details modal window with a grid listing all children of a given Execution Algo ....... 142
11.16. RFQ Button displayed in the Order section .............................................................................. 142
11.17. RFQ Entry Form filled with example data ................................................................................ 143
11.18. RFQ Responses Window ........................................................................................................ 144
11.19. RFQ Retry ............................................................................................................................. 145
11.20. AlgoTrader UI Transaction Table ............................................................................................. 145
11.21. AlgoTrader UI Transaction Entry ............................................................................................. 146
11.22. AlgoTrader UI Transaction Entry and Fees Entry ..................................................................... 146
11.23. AlgoTrader UI Position Table .................................................................................................. 147
11.24. AlgoTrader UI Market Data Table ............................................................................................ 147
11.25. AlgoTrader UI Market Data Subscribe ..................................................................................... 148
11.26. AlgoTrader UI Market Data Unsubscribe .................................................................................. 148
xii
CONFIDENTIAL
xiii
CONFIDENTIAL
List of Tables
4.1. Strategy life-cycle phase .............................................................................................................. 64
7.1. Entities ........................................................................................................................................ 80
7.2. Strategy Classes ......................................................................................................................... 83
7.3. Portfolio Value Details .................................................................................................................. 83
7.4. Security Types ............................................................................................................................. 84
7.5. Market Data Types ...................................................................................................................... 86
7.6. Order Classes ............................................................................................................................. 88
7.7. Position Valuation Details ............................................................................................................. 93
7.8. Exchange .................................................................................................................................... 94
7.9. Order Preference ......................................................................................................................... 95
7.10. Quote Request and Quote ......................................................................................................... 96
7.11. Main Services ............................................................................................................................ 97
7.12. Client Services ........................................................................................................................... 98
8.1. AlgoTrader Server modules ........................................................................................................ 118
8.2. Esper tags ................................................................................................................................. 119
9.1. Cache configuration ................................................................................................................... 129
14.1. Position Currency Attribution ..................................................................................................... 189
14.2. Transaction Currency Attribution ............................................................................................... 190
15.1. Bar Data Format ...................................................................................................................... 192
19.1. Tick Data Format ..................................................................................................................... 230
19.2. Bar Data Format ...................................................................................................................... 231
22.1. Event topics ............................................................................................................................. 243
22.2. Logon ...................................................................................................................................... 252
22.3. Logout ..................................................................................................................................... 252
22.4. Test Request ........................................................................................................................... 252
22.5. Heartbeat ................................................................................................................................. 253
22.6. Resend Request ...................................................................................................................... 253
22.7. New Order Single .................................................................................................................... 253
22.8. Order Cancel Request .............................................................................................................. 254
22.9. Execution Report ..................................................................................................................... 255
23.1. Tradable security types ............................................................................................................ 264
23.2. Order type constraints .............................................................................................................. 265
23.3. Account Adapter Functionality Support ...................................................................................... 266
23.4. B2C2 constraints ...................................................................................................................... 287
23.5. Binance constraints .................................................................................................................. 288
23.6. Supported Functionality ............................................................................................................ 289
23.7. Bitfinex constraints ................................................................................................................... 290
23.8. Supported Functionality ............................................................................................................ 290
23.9. BitFlyer constraints ................................................................................................................... 292
23.10. Supported Functionality .......................................................................................................... 293
23.11. Supported Functionality .......................................................................................................... 295
23.12. Supported Instruments ............................................................................................................ 296
xiv
CONFIDENTIAL
xv
CONFIDENTIAL
Preface
1. Document Conventions
This manual uses several conventions to highlight certain words and phrases and draw attention to specific
pieces of information.
1
In PDF and paper editions, this manual uses typefaces drawn from the Liberation Fonts set. The Liberation
Fonts set is also used in HTML editions. If not, alternative but equivalent typefaces are displayed.
System input, including shell commands, file names and paths, and key caps and key-combinations are
presented as follows.
To see the contents of the file my_next_bestselling_novel in the current working directory,
enter the cat my_next_bestselling_novel command at the shell prompt and press Enter
to execute the command.
The above includes a file name, a shell command and a key cap, all distinguishable thanks to context.
Key-combinations can be distinguished from key caps by the symbol connecting each part of a key-
combination. For example:
Press Ctrl-Alt-F1 to switch to the first virtual terminal. Press Ctrl-Alt-F7 to return to the X-
Windows session.
The first sentence highlights the particular key cap to press. The second highlights two sets of three key caps,
each set pressed simultaneously.
If source code is discussed, class names, methods, functions, variable names and returned values mentioned
within a paragraph are presented as follows.
File-related classes include filesystem for file systems, file for files, and dir for directories.
Each class has its own associated set of permissions.
Words or phrases encountered on a system, including application names; dialog box text; labeled buttons;
check-box and radio button labels; menu titles and sub-menu titles are presented as follows.
Choose System → Preferences → Mouse from the main menu bar to launch Mouse
Preferences. In the Buttons tab, click the Left-handed mouse check box and click Close
to switch the primary mouse button from the left to the right (making the mouse suitable for
use in the left hand).
1
https://pagure.io/liberation-fonts
xvi
CONFIDENTIAL Pull-quote Conventions
The above text includes application names; system-wide menu names and items; application-specific menu
names; and buttons and text found within a GUI interface, all distinguishable by context.
Note the shorthand used to indicate traversal through a menu and its sub-menus. This is to avoid the difficult-
to-follow 'Select Mouse from the Preferences sub-menu in the System menu of the main menu bar' approach.
Italics denotes text that does not need to be imputed literally or displayed text that changes depending on
circumstance. Replaceable or variable text is presented as follows.
The mount -o remount file-system command remounts the named file system. For
example, to remount the home file system, the command is mount -o remount /home.
To see the version of a currently installed package, use the rpm -q package command. It
will return a result as follows: package-version-release .
Note the words in italics above — username, domain.name, file-system, package, version and release. Each
word is a placeholder, either for text entered when issuing a command or for text displayed by the system.
package org.jboss.book.jca.ex1;
import javax.naming.InitialContext;
xvii
CONFIDENTIAL Notes and Warnings
System.out.println("Created Echo");
Warning
A Warning should not be ignored. Ignoring warnings will most likely cause data loss.
Important
Important boxes detail things that are easily missed: configuration changes that only apply to the
current session, or services that need restarting before an update will apply. Ignoring Important
boxes won't cause data loss but may cause irritation and frustration.
Note
A note is a tip or shortcut or alternative approach to the task at hand. Ignoring a note should
have no negative consequences, but might lead to a missed out on a trick that makes life easier.
xviii
Chapter 1. CONFIDENTIAL
Introduction
AlgoTrader is a comprehensive algorithmic trading platform that enables both buy side and sell side trading
firms to rapidly develop, simulate, backtest and deploy automated quantitative trading strategies on a single
platform. Designed by industry experts, it gives users maximum control over their trading experience. Initially
designed for global equities, futures, forex and options, AlgoTrader now fully supports automated trading of
Cryptocurrencies. AlgoTrader is an extremely reliable and robust system built on a multi-threaded, memory
efficient, highly concurrent architecture. It is optimized for high availability and performance to support
uninterrupted trading.
1
https://www.algotrader.com/product/overview/
2
https://www.algotrader.com/product/demo-system/
3
https://www.algotrader.com/product/demo-system/
4
https://www.algotrader.com/product/video/
5
https://www.algotrader.com/product/architecture/
6
https://www.algotrader.com/product/screenshots/
7
https://www.algotrader.com/features/
8
http://doc.algotrader.com/AlgoTraderFactsheet.pdf
9
https://www.algotrader.com/product/3rd-party-libraries/
1
Chapter 2. CONFIDENTIAL
• IntelliJ IDEA
• PyCharm CE IDE
• MySQL Database
• InfluxDB Database
• Notepad++
You can opt out of some of these at installation time and the installed software should be sandboxed and will
not interfere with other installations of the same software you might have on your machine.
In addition you will need a modern browser to display the AlgoTrader UI and if you want to visualise backtest
results, also MS Excel.
Note
With the installer, automatic updates are disabled for IngelliJ IDEA, PyCharm CE IDE, dbForge
Studio Express and Interactive Brokers Trader Workstation. You should change the update
settings on these applications if you intend to use the system for a longer period of time.
2
CONFIDENTIAL Windows Installer
Note
The installer configures trial user Maven credentials if you do not yet have a Maven configuration
on your PC. You should change the credentials to your personal login in the Maven settings file
(.m2/settings.xml under your Windows user).
After the installation, start the IntelliJ IDEA using the Idea for Algotrader dektop icon and wait for the
examples project to be read.
To be able to run AlgoTrader, you first need to run a Maven install: at the bottom right of the screen, press
Enable auto-import, then install the Maven project Bootstrap in the Maven menu on the right, then repeat
with the AlgoTrader Example Strategies.
3
CONFIDENTIAL Development Environment Installation
Once that has completed (you should see the log BUILD SUCCESS), you are ready to use AlgoTrader on your
machine.
2.2.1. Prerequisites
Note
It is generally recommended not to use paths with spaces for any of the components used by
AlgoTrader (e.g. C:\Program Files).
Java JDK
1 2
Install the latest Java JDK 1.8 from Oracle or OpenJDK 1.8 from Red Hat .
Important
It is necessary to have a Java JDK (Java Development Environment), a Java JRE (Java
Runtime Environment) will not be sufficient.
Please set the JAVA_HOME environment variable to point at the directory where the Java
JDK is installed. You also need to add JAVA_HOME\bin to your PATH variable. Setup java
3
environment variables:
1
https://www.oracle.com/java/technologies/javase-jdk8-downloads.html
2
https://developers.redhat.com/products/openjdk/download
3
https://docs.oracle.com/javase/tutorial/essential/environment/paths.html
4
CONFIDENTIAL Prerequisites
Maven
AlgoTrader uses Apache Maven for handling of dependencies. The IntelliJ IDEA from the Algotrader
installer already has an embedded Maven installation integrated. In case you want to use Maven from the
command line, it is necessary to download and install the latest version of Maven and setup it`s environment
4
variables according to the link Maven setup .
In particular, please set the MAVEN_HOME environment variable to point at the directory where Maven is
installed. You also need to add MAVEN_HOME\bin to your PATH variable.
All AlgoTrader artifacts are located on our Nexus server which is password protected:
https://repo.algotrader.com/nexus/
It is necessary the create the following file <user-home>\.m2\settings.xml below content there, to make
sure Maven can access our Nexus server. Folder .m2 should have been automatically created while
running maven for the first time.
<profiles>
<profile>
<id>algotrader</id>
<repositories>
<repository>
<id>algotraderrepo</id>
<url>https://repo.algotrader.com/nexus/repository/general/</url>
</repository>
<repository>
<id>archetype</id>
<url>https://repo.algotrader.com/nexus/repository/general/</url>
</repository>
4
http://maven.apache.org/install.html
5
CONFIDENTIAL Prerequisites
</repositories>
<pluginRepositories>
<pluginRepository>
<id>algotraderrepo</id>
<url>https://repo.algotrader.com/nexus/repository/general/</url>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>algotrader</activeProfile>
</activeProfiles>
</settings>
Note
Please replace myusername and mypassword (both appear twice!) with the username and
password provided when licensing AlgoTrader.
MySQL
5
Download and install MySQL Community Server .
Important
The minimum required MySQL version is 5.7.8
Per default the system uses the user name root and password password. To change username and/or
password the following properties need to be updated inside conf-core.properties. Alternatively the
properties can be changed via Section 2.4, “VM Options”:
# database password
#{"type":"String","label":"Data Source Password"}
dataSource.password = password
You can create the root user/set the DB password using the following command:
5
https://dev.mysql.com/downloads/
6
CONFIDENTIAL Prerequisites
To work with MySQL it is recommended to install a MySQL client. There are many different MySQL clients
available to choose from:
6
• devart dbForge Studio Express (free)
7
• MySQL Workbench (free)
8
• SQLyog MySQL (commercial)
Note
The Java MySQL JDBC driver sometimes has issues connecting to the MySQL database
depending on the MySQL time zone setting. Java Exceptions like the following are an
indication for this issue:
To fix the issue it is recommended to change the MySQL time zone setting by executing
the following MySQL statement
This means that your MySQL database does not know the UTC time zone yet. Follow the
9
instructions under My SQL Time Zone Issues to install them. For Windows this means to
download the 5.7 .sql file with the posix time zone definitions and manually loading them
into your local DB instance. For Linux this can be easily fixed by running following command:
To be sure you do not lose this information, e.g. on reboot, you can set a time zone in the
MYSQL my.cnf or my.ini file
6
https://www.devart.com/dbforge/mysql/studio/download.html
7
https://www.mysql.com/products/workbench/
8
https://www.webyog.com/
9
https://dev.mysql.com/downloads/timezones.html
7
CONFIDENTIAL Prerequisites
[mysqld]
default-time-zone=+00:00
explicit_defaults_for_timestamp=1
InfluxDB
Note
InfluxDB is an optional component that is used to store historical data. In back testing it is
possible to use CSV files to provide historical data as an alternative to using InfluxDB
10
Linux/MacOS: Download the latest version of InfluxDB and install it according to the InfluxDB installation
11
instructions (Install it in a directory/tree without spaces in the names).
12
Windows: Download version 1.5.2 of InfluxDB and unpack the file in a directory/tree without spaces in
the names.
Important
On Windows AlgoTrader requires InfluxDB 1.5.2. Do not use InfluxDB 1.6.0 or greater.
13
• download nssm
• unpack nssm
• update the following sections inside influxdb.conf by replacing <username> with the username that
will run InfluxDB
[meta]
# Where the metadata/raft database is stored
dir = "C:\\Users\\<username>\\.influxdb\\meta"
[data]
# The directory where the TSM storage engine stores TSM files.
dir = "C:\\Users\\<username>\\.influxdb\data"
# The directory where the TSM storage engine stores WAL files.
10
https://portal.influxdata.com/downloads/
11
https://docs.influxdata.com/influxdb/v1.5/introduction/installation//
12
https://dl.influxdata.com/influxdb/releases/influxdb-1.5.2_windows_amd64.zip
13
https://nssm.cc/download
8
CONFIDENTIAL Prerequisites
wal-dir = "C:\\Users\\<username>\\.influxdb\\wal"
• Go to nssm installed folder, choose win64 or win32 folder, start a command prompt and type:
• Add an environment variable named HOME pointing to the directory where InfluxDB is installed
All InfluxDB related settings are available within the file conf-influxdb.properties
Connection settings
#{"type":"String","label":"Host"}
influxDB.host = localhost
#{"type":"Integer","label":"Port"}
influxDB.port = 8086
#{"type":"String","label":"Database Name"}
influxDB.dBName = algotrader
#{"type":"String","label":"Username","required":"false"}
influxDB.username =
#{"type":"String","label":"Password","required":"false"}
influxDB.password =
#{"type":"String","label":"Retention Policy"}
influxDB.retentionPolicy = autogen
#{"type":"Integer","label":"Ping interval"}
influxDB.pingMs = 10000
Depending on machine performance and dataset size it may be needed to adjust InfluxDB timeout periods
(especially influxDB.readTimeoutMs property) to bigger values.
9
CONFIDENTIAL AlgoTrader Server Code Installation
#{"type":"Integer","label":"Connect timeout"}
influxDB.connectTimeoutMs = 10000
#{"type":"Integer","label":"Read timeout"}
influxDB.readTimeoutMs = 10000
#{"type":"Integer","label":"Write timeout"}
influxDB.writeTimeoutMs = 10000
Per default username/password authentication is disabled. To set username and password based
14
authentication please visit the InfluxDB Authentication and Authorization guide .
You can manage your InfluxDB data using AlgoTrader's Historical Data Manager Section 11.3, “Historical
Data Manager”
There are several 3rd party client options available to access InfluxDB:
15
• InfluxDB Chronograf
16
• Grafana
The AlgoTrader server code can be installed either via command line or via IDE
To install the AlgoTrader server code via command line please perform the following steps.
Download the Bootstrap project zip file and unpack it in a directory of your choosing: https://
www.algotrader.com/downloads/latest-bootstrap
Note
user name and password will be provided when signing up for an AlgoTrader license
If you need an older AlgoTrader version, login to our maven repository (https://repo.algotrader.com/nexus) and
click on Browse on the left and select code-general.
14
https://docs.influxdata.com/influxdb/v1.5/query_language/authentication_and_authorization/
15
https://docs.influxdata.com/chronograf/v1.5/
16
https://grafana.com/docs/features/datasources/influxdb/
10
CONFIDENTIAL AlgoTrader Server Code Installation
Note
Please make sure the Maven settings file is updated according to Section 2.2.1, “Prerequisites”.
Note
When running the build process for the first time, this will take a few minutes since all maven
dependencies have to be downloaded.
11
CONFIDENTIAL AlgoTrader Server Code Installation
To build AlgoTrader from within IntelliJ IDEA please follow this process.
• Download and unpack the code as per Section 2.2.2.1.1, “Code Installation”
• On the main menu, select File / Open and navigate to the Bootstrap directory and press OK
• Click on Project on the top of the sidebar on the left and you will see the Bootstrap project in the package
explorer, with the sub-projects conf and launch.
To generate the code click on Maven on the top of the sidebar on the right to get the Maven menu, then press
the Execute Maven Goal button at the top right and select (double-click) Maven install. This will download
the missing libraries and compile AltoTrader
12
CONFIDENTIAL Python installation
Python packages can be downloaded as a source distribution via our secured Nexus repository and can be
installed via pip:
for the latest version or if you're looking for a specific version (e.g. 6.0.2)
Required dependencies are installed automatically. The interface is not distributed via the public PyPI
repository. The package functionality has been tested with Python 2.7 and Python 3.7.
The AlgoTrader Python Interface package name is algotrader_com to prevent collisions with a non-affiliated
library with name algotrader that is present on PyPI.
Docker allows packaging of applications with all of its dependencies into a standardized unit for software
development.
At the core of the Docker platform is Docker Engine, a lightweight runtime and robust tooling that builds and
runs Docker containers.
18
For an in-depth description of Docker please visit the What is Docker page.
19
To get started with Docker please visit the Docker Engine Documentation page.
17
https://www.docker.com/
18
https://www.docker.com/why-docker
19
https://docs.docker.com/engine/
13
CONFIDENTIAL Docker based Installation
Note
On Mac and Windows please install Docker Toolbox that contains the Docker Engine
Note
On Mac and Windows please install the Docker Toolbox that contains Docker Compose
Login to Nexus
Login to the Docker Repository with the username and password provided when licensing AlgoTrader.
docker-compose up -d
http://localhost:9090
The above process will setup an AlgoTrader based system made up of the following Docker containers:
20
https://docs.docker.com/engine/installation/
21
https://docs.docker.com/compose/install/
14
CONFIDENTIAL Docker Containers
• AlgoTrader server
To startup AlgoTrader with different startup options please visit this chapter on starting AlgoTrader in a
Section 3.3, “Server Environment”
To startup one of the AlgoTrader example strategies please visit the appendix of this documentation.
The following Docker environment variables are relevant for the AlgoTrader container:
• ALGOTRADER_HOST (default: algotrader). This variable is used by strategies to reference the AlgoTrader
Docker container.
• IB_GATEWAY_ACCOUNT optional, only needs to be specified if the IB login has multiple accounts associated
• SPRING_PROFILES (default:
live,pooledDataSource,iBMarketData,iBNative,iBHistoricalData,embeddedBroker,html5) Spring
profiles to be used (comma separated list)
In addition the command line switch -i can be used to load the MySQL sample data file (samples/db/mysql/
mysql-data.sql) on first start up. The sample data will only be loaded if the security table contains no data.
To use the -i switch please use the following directive inside docker-compose.yml:
15
CONFIDENTIAL Docker Containers
command: -i
The AlgoTrader Docker container will run through the following process on startup:
1. Wait for MySQL to be available. When starting up MySQL and AlgoTrader at the same time (using docker
compose) it will take the database a few seconds to become available.
3. Load MySQL sample data if the -i command line switch is used (see above).
The strategy code is located in the directory /usr/local/strategy inside the Docker container.
All strategy Docker containers are based on the AlgoTrader Docker container, so environment variables from
the AlgoTrader docker container can be reused inside strategy containers.
To build a strategy Docker container the following Dockerfile has to be added to the root of the project:
FROM docker.algotrader.com/algotrader/algotrader:latest
ENV STRATEGY_NAME=XYZ
WORKDIR /usr/local/strategy
ADD target/*.jar lib/
ENTRYPOINT ["/usr/local/algotrader/bin/docker-strategy-run.sh"]
CMD ["-e"]
The startup script supports both embedded and distributed mode, see: Section 3.2, “Live Trading Mode”
To start the strategy Docker container in embedded mode please use the -e command line switch inside the
docker-compose.yml file of your strategy:
command: -e
This will cause the system to run through the following process:
16
CONFIDENTIAL Docker Containers
1. Wait for MySQL to be available. When starting up MySQL and AlgoTrader at the same time (using docker
compose) it will take the database a few seconds to become available.
3. Load MySQL data from db/mysql/mysql-data.sql. MySQL is only loaded if the entry in the strategy table
for STRATEGY_NAME is missing
To start the strategy Docker container in distributed mode please use the -d command line switch inside the
docker-compose.yml file of your strategy:
command: -d
This will cause the system to run through the following process:
When running the system in distributed mode the AlgoTrader server needs to be run in a separate Docker
container. Since trading strategies do not have access to the database directly MySQL data needs to be loaded
manually by connecting to the database with a MySQL client. It is therefore suggested to follow this process
when starting up the system in distributed mode:
Note
Please see the following chapter about changing IB API settings (Read-Only API)
2. Load MySQL data by connecting a MySQL client to port 3306 of the Docker Engine
3. Start strategies
docker-compose up -d XYZ
17
CONFIDENTIAL Docker Containers
22
• Interactive Brokers IB Gateway
23
• IB Controller which allows running IB Gateway in an automated fashion
The following environment variables are relevant for the IB Controller container:
Unfortunately only few settings of the IB Gateway can be managed via the IB Controller. All other settings have
to be managed via the IB Gateway UI itself which is not visible on the Docker container.
This is especially cumbersome for the Read-Only API trading mode that the is set by default. If this mode is
active, placement of orders is not allowed.
To change any of the IB Gateway settings (e.g. Read-Only API trading mode) please execute the following
steps:
25
1. The IB Gateway container stores IB settings inside a Docker Volume . This volume can be mapped to a
local directory as follows.
volumes:
- /var/lib/tws:/var/lib/tws
This will make IB Gateway settings available in the local directory /var/lib/tws
On Windows
volumes:
- c:/Users/Administrator/Documents/tws:/var/lib/tws
This will make IB Gateway settings available in the local directory c:\Users\Administrator\Documents
\tws
22
https://www.interactivebrokers.com/en/index.php?f=5041
23
https://github.com/ib-controller/ib-controller
24
https://en.wikipedia.org/wiki/Xvfb
25
https://docs.docker.com/storage/volumes/
18
CONFIDENTIAL Docker Containers
4. Make necessary changes (e.g. deselect the Read-Only API check box) and click OK
6. Inside the IB Gateway installation folder there will be one or multiple sub-directories starting which have a
name made up of 8-9 characters starting with a the letter d. Please select the directory with the latest time-
stamp and makes sure it contains a file named ibg.xml
7. Copy this directory (e.g. darykqwzr) into the IB Gateway settings directory linked above:
8. Copy the jts.ini file into the IB Gateway settings directory linked above:
Note
The above steps will not work for the public pmdemo account which gets reset upon each startup.
2.3.2.4. MySQL
26
MySQL provides a fully configured Docker container. For further details please visit MySQL on Docker Hub
The following environment variables are relevant for the MySQL container:
volumes:
- /var/lib/mysql:/var/lib/mysql
This will make MySQL data available in the local directory /var/lib/mysql
On Windows
volumes:
26
https://hub.docker.com/_/mysql/
27
https://docs.docker.com/storage/volumes/
19
CONFIDENTIAL Docker Compose
- c:/Users/Administrator/Documents/mysql:/var/lib/mysql
This will make MySQL data available in the local directory c:\Users\Administrator\Documents\mysql
2.3.2.5. InfluxDB
28
InfluxDB provides a fully configured Docker container. For further details please visit InfluxDB on Docker Hub
29
InfluxDB data is stored inside a Docker Volume . This volume can be mapped to a local directory as follows.
volumes:
- /var/lib/influxdb:/var/lib/influxdb
This will make MySQL data available in the local directory /var/lib/mysql
On Windows
volumes:
- c:/Users/Administrator/Documents/influxdb:/var/lib/influxdb
This will make MySQL data available in the local directory c:\Users\Administrator\Documents\influxdb
Docker Compose uses docker-compose.yml files to configure multi-container applications. AlgoTrader ships
with a default docker-compose.yml file located inside the top-level AlgoTrader project directory:
algotrader:
image: docker.algotrader.com/algotrader/algotrader
command: -i
28
https://hub.docker.com/_/influxdb/
29
https://docs.docker.com/storage/volumes/
30
https://docs.docker.com/compose/
20
CONFIDENTIAL Docker Compose
environment:
- VM_ARGUMENTS=-Dkeygen.id=...
links:
- mysql
- ibgateway
- influxdb
ports:
- 9090:9090
- 61614:61614
ibgateway:
image: docker.algotrader.com/interactivebrokers/ibgateway
environment:
TWS_USERNAME: pmdemo
TWS_PASSWORD: demouser
volumes:
- /var/lib/tws
mysql:
image: mysql:5.7.22
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: algotrader
ports:
- 3306:3306
volumes:
- /var/lib/mysql
influxdb:
image: influxdb:1.5.2
ports:
- 8086:8086
volumes:
- /var/lib/influxdb
Using this docker-compose.yml file will create Docker containers for AlgoTrader, IB Gateway, MySQL and
InfluxDB. The following items are present in the file:
• image: the name of the image to use in the format namespace/repository:version (e.g.
docker.algotrader.com/algotrader/algotrader:latest)
• command: command line argument to pass to the Docker container (e.g. -i). See Section 2.3.2, “Docker
Containers” for supported command line arguments
• links: services to link to this container (e.g. MySQL & ibgateway). Adding a link will make the target container
accessible with the correct IP by its link name
21
CONFIDENTIAL Docker Compose
• ports: ports to map on the host machine. E.g. 3306:3306 will map port 3306 of the MySQL container to
3306 of the host machine
• environment: environment variables to use. See Section 2.3.2, “Docker Containers” for supported
environment variables
• volumes: Docker Data volumes to create. E.g. c:/Users/mysql:/var/lib/mysql will map the directory /
var/lib/mysql inside the container to c:\mysql on the host machine
2.3.3.1. Passwords
The example docker-compose.yml file specifies multiple passwords directly. For security purposes this often
31
not advisable. As an alternative passwords can be stored using Docker secrets
If a large number of properties need to be changed or if other config files need to be changed (e.g. fix.cfg)
it is recommended to follow this process:
4. Commit the change to the modified AlgoTrader container using the following command
volumes:
- ./conf:/usr/local/algotrader/bootstrap/conf/
31
https://docs.docker.com/engine/swarm/secrets/
32
https://docs.docker.com/storage/volumes/
22
CONFIDENTIAL Docker Compose
And copying all necessary config files (fix.cfg included) to the created ./conf folder on local machine.
To store config values as docker secrets one needs to follow these steps:
bmx.apiKey=revdPMrxxxxxxxxxfdsPo
bmx.apiSecret=fFzYObWcVlyyyyyyyyyFmgXk
version: '3.1'
services:
algotrader:
image: docker.algotrader.com/algotrader/algotrader
command: -i
environment:
SPRING_PROFILES:
live,pooledDataSource,bMX,bMXMarketData,bMXAccount,embeddedBroker,html5
SECRET_FILE: /run/secrets/api_keys
secrets:
- api_keys
deploy:
restart_policy:
condition: none
ports:
- 9090:9090
33
https://docs.docker.com/engine/swarm/secrets/
23
CONFIDENTIAL Docker Compose
- 61614:61614
ibgateway:
image: docker.algotrader.com/interactivebrokers/ibgateway
environment:
TWS_USERNAME: pmdemo
TWS_PASSWORD: demouser
volumes:
- /var/lib/tws
depends_on:
- algotrader
mysql:
image: mysql:5.7.22
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: algotrader
ports:
- 3306:3306
volumes:
- /var/lib/mysql
depends_on:
- algotrader
influxdb:
image: influxdb:1.5.2
ports:
- 8086:8086
volumes:
- /var/lib/influxdb
depends_on:
- algotrader
secrets:
api_keys:
external: true
Note
Docker secrets as shown above are only available to swarm services, not to standalone
containers. To use this feature, algotrader must run as a service with a scale of 1, on a single
node cluster.
Prior to creating and using secrets initialize machine as swarm manager using following
command:
24
CONFIDENTIAL Docker Management
Operating in Swarm mode means using different docker commands, see examples below.
To look at logs:
Otherwise the docker swarm will not be able to use it and the algotrader image will not start. To
create Docker secret from e.g. myKeys.txt file use:
It is a Docker best-practice to have only one running process per Docker container. Typically application output
is logged directly to the console where it can be viewed using the command docker logs according to the
34
Docker documentation
Sometimes this is not enough and one wishes to write additional information (e.g. fix messages) to a separate
log file. To get access to this log file from outside the container it is advised to create an additional volume:
volumes:
- ~/fix.log:/usr/local/algotrader/logs/fix.log
In addition to using the Docker command line, several options exist for management of docker based
installations
2.3.4.1. Portainer
34
https://docs.docker.com/engine/reference/commandline/logs/
25
CONFIDENTIAL Docker Management
docker-ui:
image: portainer/portainer
command: -H unix:///var/run/docker.sock
ports:
- 9000:9000
volumes:
- /var/run/docker.sock:/var/run/docker.sock
35 36
For further details please visit Docker UI on Docker Hub and Docker UI on GitHub .
2.3.4.2. Kitematic
37
When running Docker on Windows or Mac Docker Kitematic provides a UI for management of the Docker
engine.
35
https://hub.docker.com/r/dockerui/dockerui/
36
https://github.com/kevana/ui-for-docker
37
https://kitematic.com/
26
CONFIDENTIAL VM Options
2.4. VM Options
Many characteristics of the system can be customized with VM Options, the following list provides an overview
of commonly used VM Options.
-DlogLevel
log4j log level (ERROR, WARN, INFO or DEBUG)
-Dspring.profiles.active
list of Spring Profiles to activate (see Section 26.2, “Spring Profiles”)
-Xmx
increase the Java Heap Size to specified amount (e.g. 2048M)
AlgoTrader specific configuration parameters can be changed inside the .properties files. As an alternative
configuration parameters can also be provided as VM Options in which case they will overwrite existing
parameters inside *.properties files.
-Dstatement.closePosition=false
27
Chapter 3. CONFIDENTIAL
Starting AlgoTrader
As a first step you to make sure that your AlgoTrader license key is properly configured. The license key was
provided in the Email after signing up for the AlgoTrader free 30-day trial or when purchasing an AlgoTrader
license. The license key needs to be configured inside the file /algotrader-conf/src/main/resources/
conf.properties as follows.
The screenshot below shows where to find this file in the AlgoTrader IntelliJ IDE, for which you have a desktop
shortcut if you used the AlgoTrader installer process:
Now AlgoTrader can be started through various Run Configurations which are available to launch the various
operation modes of AlgoTrader. To access the available Run Configurations in the AlgoTrader IntelliJ IDEA,
follow screenshots below.
28
CONFIDENTIAL Simulation Mode
Update program and VM options if necessary. You can expand them by pressing the 2 facing arrows on the
right.
The run configurations of the AlgoTrader installer have been configured to run with the TWS demo account
and have IB delayed market data enabled. If you've got a proper IB account, simply remove the setting that
enables delayed market data -Dib.pricefeed.allowDelayedMarketData=true from the argument list of
the starter by editing the relevant run configuration, expanding the VM options and removing that entry:
In IntelliJ Run Configurations named SimulationStarter-simulate-xxx are provided which contain the
following items:
Main-Tab
simulateWithCurrentParams
29
CONFIDENTIAL Live Trading Mode
Arguments-Tab / VM Options
-Dsimulation=true
-DstrategyName=XXX
-DdataSource.0.dataSetType=TICK
-DdataSource.dataSetName=yyy
-Dspring.profiles.active=simulation,pooledDataSource
Note
To run the strategy in simulation mode a dependency to algotrader-core has to be added to
the maven dependencies of the trading strategy. Alternatively one can create a separate maven
module containing dependencies to the strategy project as well as algotrader-core.
If using InteractiveBrokers the Trader Workstation or the IB Gateway have to be running with the following
configurations under API/Settings:
When running AlgoTrader in Live Trading Mode the AlgoTrader Server and the Strategies can either be run in
separate JVMs (distributed mode) or the entire system can be run within one single JVM (embedded mode).
Before starting AlgoTrader check the database table strategy. The column AUTO_ACTIVATE should be set to
true for records corresponding to the AlgoTrader Server and the trading strategy one wants to trade.
Note
Only one Strategy can be run at once in Embedded Mode
In IntelliJ Run Configurations named EmbeddedStrategyStarter-xxx are provided which contain the following
items:
30
CONFIDENTIAL Distributed Mode
Main-Tab
Configuration-Tab / VM Options
-DstrategyName=TEST
-
Dspring.profiles.active=live,<dataSource>,<marketDataProfile>,<brokerProfile>,embeddedBroker,ht
• marketDataProfile: the SpringProfile corresponding to the market data interface in use (e.g.
iBMarketData or bBMarketData)
• tradingProfile: the SpringProfile corresponding to the adapter in use (e.g. iBNative or iBFix)
Note
To run the strategy in embedded mode a dependency to algotrader-core has to be added to
the maven dependencies of the trading strategy. Alternatively one can create a separate maven
module containing dependencies to the strategy project as well as algotrader-core.
To Start the AlgoTrader Server in distributed mode the IntelliJ run configurations ServerStarterXX is provided
which contain the following items:
Main-Tab
• Project: algotrader-core
Configuration-Tab / VM Options
-
Dspring.profiles.active=live,<dataSource>,<marketDataProfile>,<brokerProfile>,embeddedBroker,ht
• marketDataProfile: the SpringProfile corresponding to the market data interface in use (e.g.
iBMarketData or bBMarketData)
31
CONFIDENTIAL Server Environment
• tradingProfile: the SpringProfile corresponding to the adapter in use (e.g. iBNative or iBFix)
To start a Strategy IntelliJ Run Configurations StrategyStarter-xxx are provided which contain the following
items:
Main-Tab
Configuration-Tab / VM Options
-DstrategyName=TEST
-Dspring.profiles.active=live
xyz:
image: xyz
command: -d
environment:
- VM_ARGUMENTS=-Dkeygen.id=...
algotrader:
image: docker.algotrader.com/algotrader/algotrader
container_name: algotrader
environment:
- VM_ARGUMENTS=-Dkeygen.id=...
Note
Only one Strategy can be run at once in Embedded Mode
To run the system in embedded mode create a docker-compose.yml file similar to the following:
32
CONFIDENTIAL Embedded Mode
xyz:
image: xyz
command: -e
environment:
- VM_ARGUMENTS=-Dkeygen.id=...
links:
- mysql
- ibgateway
- influxdb
ports:
- 9090:9090
- 61614:61614
environment:
STRATEGY_NAME: XYZ
ibgateway:
image: docker.algotrader.com/interactivebrokers/ibgateway
environment:
TWS_USERNAME: pmdemo
TWS_PASSWORD: demouser
volumes:
- /var/lib/tws
mysql:
image: mysql:5.7.22
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: algotrader
ports:
- 3306:3306
volumes:
- /var/lib/mysql
influxdb:
image: influxdb:1.5.2
ports:
- 8086:8086
volumes:
- /var/lib/influxdb
Please replace xyz / XYZ with the name of the trading strategy. Please refer to Chapter 4, Strategy Development
on how to create a new trading strategy.
To start the system in embedded mode please run the following command from the directory where the docker-
compose.yml file is located:
docker-compose up -d
33
CONFIDENTIAL Distributed Mode
This will create the following docker containers: strategy (xyz), ibgateway & mysql
To run the system in distributed mode create a docker-compose.yml file similar to the following:
xyz:
image: xyz
command: -d
environment:
- VM_ARGUMENTS=-Dkeygen.id=...
links:
- algotrader
environment:
STRATEGY_NAME: XYZ
algotrader:
image: docker.algotrader.com/algotrader/algotrader
container_name: algotrader
environment:
- VM_ARGUMENTS=-Dkeygen.id=...
links:
- mysql
- ibgateway
- influxdb
ports:
- 9090:9090
- 61614:61614
ibgateway:
image: docker.algotrader.com/interactivebrokers/ibgateway
container_name: ibgateway
environment:
TWS_USERNAME: pmdemo
TWS_PASSWORD: demouser
volumes:
- /var/lib/tws
mysql:
image: mysql:5.7.22
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: algotrader
34
CONFIDENTIAL Distributed Mode
ports:
- 3306:3306
volumes:
- /var/lib/mysql
influxdb:
image: influxdb:1.5.2
ports:
- 8086:8086
volumes:
- /var/lib/influxdb
Please replace xyz / XYZ with the name of the trading strategy.
To start the system in distributed mode please run the following command from the directory where the docker-
compose.yml file is located:
docker-compose up -d
This will create the following docker containers: strategy (xyz), algotrader, ibgateway & mysql
Important
In the Distributed Mode the strategies communicate with the server via messaging provided
by ActiveMQ. Every message has a default TTL (time-to-live) set to 60s configurable via the
configuration property activeMQ.message.ttl (in ms). This is to prevent the messages from
piling up and consuming a lot of memory in case the strategy isn't able to process them in time.
35
Chapter 4. CONFIDENTIAL
Strategy Development
Warning
It is recommended to perform thorough Simulation / Back Testing of newly developed strategies.
After that the strategy should be tested with a Paper Trading Account. At the end of a thorough
test procedure, the new strategy can be put into production. At the beginning of live trading it
is recommended to use a small trading amount only.
The following diagram shows the general procedure for developing new strategies:
The following 2 options can assist in creating a new trading strategy, the AlgoTrader Strategy Wizard and the
AlgoTrader Maven Archetype.
In addition to this setup, you will need to create a database entry for your strategy. Please refer to the strategy
table definition.
36
CONFIDENTIAL AlgoTrader Strategy Wizard
Section 4.1, “Creating a Trading Strategy ”. The Strategy Wizard provides options for three different types of
Trading Strategies:
The AlgoTrader IntelliJ IDEA from the Section 2.1, “Windows Installer” already has these archetypes
configured. To add them to your own IDEA installation, simply create new archetypes with group id algotrader,
artifact id algotrader-archetype-esper, algotrader-archetype-java or algotrader-archetype-simple
and set the version to your AlgoTrader version.
Inside Intellij IDEA, the Strategy Wizard can be started via File / New / Module which will bring up the following
screen where you should select Maven on the left, check the Create from archetype box and select your
desired archetype, e.g. algotrader-archetype-simple, then press Next.
Configure the next screen by setting the parent project (e.g. AlgoTrader Example Strategies , the strategy
name (e.g. ema), set the group id to ch.algotrader.strategy and press Next.
37
CONFIDENTIAL AlgoTrader Strategy Wizard
Important
On the following page, add 2 additional name/value pairs using the + button:
• name: your strategy name (e.g. ema), all lower-case, no periods, no dashes
• serviceNamne: the name of the strategy service (e.g. EMA), first letter upper-case or all upper-case, do not
include Service at the end (e.g. do not specify EMAService)
When clicking Finish the Strategy Wizard will create a new project named like your strategy.
38
CONFIDENTIAL AlgoTrader Maven Archetype
The AlgoTrader Maven Archetype is a project template that can be used to create a new AlgoTrader trading
Strategy. To use the Maven Archetype execute the following command from the command line in a new empty
directory.
To create Esper bases strategies execute (replace <version> with the corresponding AlgoTrader version):
To create Java strategies execute (replace <version> with the corresponding AlgoTrader version):
To create simple strategies consisting of only one single java file execute (replace <version> with the
corresponding AlgoTrader version):
The Maven Archetype will ask for the following input parameters:
groupId
The maven group id (e.g. algotrader), all lower-case, can contain periods
artifactId
The maven artifact id (e.g. algotrader-ema), all lower-case, can contain dashes
version
The maven version (e.g. 1.0.0-SNAPSHOT), x.y.z, plus optionally -SNAPSHOT
packageName
The java package name (ch.algotrader.strategy), all lower-case, can contain periods.
name
The name of the strategy (e.g. ema), all lower-case, no periods, no dashes
serviceName
The name of the strategy service (e.g. EMA), first letter upper-case or all upper-case, do not include Service
at the end (e.g. do not specify EMAService)
39
CONFIDENTIAL Generated Artifacts Java Archetype
Important
/src/main/java/ch/algotrader/strategy/EMAService.java
The strategy service class
/src/main/java/ch/algotrader/strategy/EMAConfig.java
The strategy configuration class
/src/main/java/ch/algotrader/strategy/Metrics.java
A sample class that can be used within the strategy
/src/main/java/ch/algotrader/strategy/State.java
A sample enum that can be used within the strategy
/runConfigurations/*.xml
IntelliJ IDEA (v.2020.1 or greater) Run Configurations to start the Strategy in embedded mode and
simulation mode.
/pom.xml
The Maven project object model file containing general information about the Trading Strategy
/Dockerfile
The Docker file
4.1.3.1. EMAService.java
The references to the Services provided by the AlgoTrader Server (e.g. OrderService, PositionService,
etc.) will be injected on startup by the Spring Framework
@Override
public void onStart(final LifecycleEventVO event) {
getSubscriptionService().subscribeMarketDataEvent(getStrategyName(), getConfig().getSecurityId()
40
CONFIDENTIAL Generated Artifacts Java Archetype
@Override
public void onBar(BarVO bar) {
getOrderService().sendOrder(order);
}
Once the strategy has reached the START live cycle phase subscribe to the security needed for this strategy
Construct an Order Value Object using the MarketOrderVOBuilder. The OrderVO contains a reference
to the strategy, the security, the account as well as the quantity and the order side.
Send the Order to the market via the OrderService
4.1.3.2. pom.xml
The Maven pom.xml file contains the Maven project definition as well as Maven dependencies:
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
41
CONFIDENTIAL Generated Artifacts Simple Java Archetype
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>algotrader</groupId>
<artifactId>algotrader-core</artifactId>
<version>...</version>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
</project>
4.1.3.3. Dockerfile
FROM docker.algotrader.com/algotrader/algotrader:latest
ENV STRATEGY_NAME=EMA
WORKDIR /usr/local/strategy
ADD target/*.jar lib/
ENTRYPOINT ["/usr/local/algotrader/bin/docker-strategy-run.sh"]
CMD ["-e"]
/src/main/java/ch/algotrader/strategy/EMAService.java
The strategy service class
/runConfigurations/*.xml
IntelliJ IDEA (v.2020.1 or greater) Run Configurations to start the Strategy in embedded mode and
simulation mode.
/pom.xml
The Maven project object model file containing general information about the Trading Strategy
42
CONFIDENTIAL Generated Artifacts Simple Java Archetype
/Dockerfile
The Docker file
4.1.4.1. EMAService.java
This is the main Java-class containing the Business Logic.
The references to the Services provided by the AlgoTrader Server (e.g. OrderService, PositionService,
etc.) will be injected on startup by the Spring Framework
@Override
public void onStart(final LifecycleEventVO event) {
getSubscriptionService().subscribeMarketDataEvent(getStrategyName(), getConfig().getSecurity
}
@Override
public void onBar(BarVO bar) {
getOrderService().sendOrder(order);
}
Once the strategy has reached the START live cycle phase subscribe to the security needed for this strategy
Construct an Order Value Object using the MarketOrderVOBuilder. The OrderVO contains a reference
to the strategy, the security, the account as well as the quantity and the order side.
Send the Order to the market via the OrderService
4.1.4.2. pom.xml
The Maven pom.xml file contains the Maven project definition as well as Maven dependencies:
43
CONFIDENTIAL Generated Artifacts Simple Java Archetype
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>algotrader</groupId>
<artifactId>algotrader-core</artifactId>
<version>...</version>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
</project>
4.1.4.3. Dockerfile
FROM docker.algotrader.com/algotrader/algotrader:latest
ENV STRATEGY_NAME=EMA
WORKDIR /usr/local/strategy
ADD target/*.jar lib/
ENTRYPOINT ["/usr/local/algotrader/bin/docker-strategy-run.sh"]
44
CONFIDENTIAL Generated Artifacts Esper Archetype
CMD ["-e"]
/src/main/java/ch/algotrader/strategy/EMAService.java
The strategy service class
/src/main/resources/module-ema.epl
Esper Module containing statements related to signal generation
/src/main/resources/conf-ema.properties
Contains parameters used by the strategy (e.g. Moving average durations etc.)
/src/main/resources/META-INF/esper-ema.cfg.xml
Contains event-types, imports, variables and general Esper settings
/src/main/resources/META-INF/applicationContext-client-ema.xml
Spring Application Context File for the strategy
/src/main/resources/db/mysql/mysql-ema.sql
MySQL data file containing db data needed for this trading strategy in live trading mode
/runConfigurations/*.xml
IntelliJ IDEA (v.2020.1 or greater) Run Configurations to start the Strategy in embedded mode and
simulation mode.
/pom.xml
The Maven project object model file containing general information about the Trading Strategy
/Dockerfile
The Docker file
4.1.5.1. EMAService.java
The references to the Services provided by the AlgoTrader Server (e.g. OrderService, PositionService,
etc.) will be auto injected on startup by the Spring Framework
45
CONFIDENTIAL Generated Artifacts Esper Archetype
@Override
public void onStart(final LifecycleEventVO event) {
getSubscriptionService().subscribeMarketDataEvent(getStrategyName(), this.securityId, AdapterTyp
}
getOrderService().sendOrder(order);
}
4.1.5.2. module-ema.epl
This Esper module contains the Esper statements for signal generation
The statement MOVING_AVERAGE generate signals by using the moving average function.
the statement SEND_ORDER calls the EMAService.sendOrder() whenever there is a moving average crossover
on the indicators. The Tag @Subscriber is used to instruct the EsperEngine to attach the Subscriber to this
statement. This way the sendOrder method is called whenever there is a signal.
@Name('MOVING_AVERAGE')
insert into
Indicator
select
ema(currentValue, movingAveragePeriodShort) -
ema(currentValue, movingAveragePeriodLong) as value
from
46
CONFIDENTIAL Generated Artifacts Esper Archetype
TickVO;
@Name('SEND_ORDER')
@Subscriber(className='emaService#sendOrder')
select
case when indicator.value > 0 then Side.BUY else Side.SELL end as side
from
pattern [every indicator=Indicator]
where
(indicator.value > 0 and prior(1, indicator.value) <= 0)
or
(indicator.value < 0 and prior(1, indicator.value) >= 0)
4.1.5.3. conf-ema.properties
#{"type":"Integer","label":"Account ID"}
accountId = 1
#{"type":"Integer","label":"Security ID"}
securityId = 1
4.1.5.4. esper-ema.cfg.xml
</esper-configuration>
47
CONFIDENTIAL Generated Artifacts Esper Archetype
The above file configures the required variables along with their type. The actual values for the variables are
taken from conf-ema.properties.
4.1.5.5. applicationContext-client-ema.xml
<bean id="emaConfigParams"
class="ch.algotrader.config.spring.CustomConfigParamsFactoryBean" >
<property name="global" ref="configParams"/>
<property name="resource">
<value>classpath:/conf-ema.properties</value>
</property>
</bean>
<bean id="emaEngine"
class="ch.algotrader.esper.EngineFactoryBean">
<property name="strategyName" value="EMA"/>
<property name="configResource" value="esper-ema.cfg.xml"/>
<property name="configParams" ref="emaConfigParams"/>
<property name="initModules" value="test"/>
</bean>
<bean id="emaService"
class="ch.algotrader.EMAService" autowire="byName">
<property name="strategyName" value="EMA"/>
<property name="engine" ref="emaEngine"/>
</bean>
</beans>
48
CONFIDENTIAL Generated Artifacts Esper Archetype
4.1.5.6. mysql-ema.sql
The MySQL database script contains the following items:
The file contains an entry in the table strategy. The column AUTO_ACTIVATE means that the strategy will be
automatically run in simulation mode.
4.1.5.7. pom.xml
The Maven pom.xml file contains the Maven project definition as well as Maven dependencies:
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>algotrader</groupId>
<artifactId>algotrader-core</artifactId>
<version>...</version>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
49
CONFIDENTIAL Building a Trading Strategy
</project>
4.1.5.8. Dockerfile
The Dockerfile contains all relevant information to build a Docker container:
FROM docker.algotrader.com/algotrader/algotrader:latest
ENV STRATEGY_NAME=EMA
WORKDIR /usr/local/strategy
ADD target/*.jar lib/
ENTRYPOINT ["/usr/local/algotrader/bin/docker-strategy-run.sh"]
CMD ["-e"]
mvn install
The Maven modules can now be deployed to a Maven repository (e.g. Sonatype Nexus) using:
mvn deploy
1
For further details regarding a maven deploy please visit the Maven deploy plug-in page
Execute the following Docker command to create a Docker image of the trading strategy that can be used for
productive deployments:
The Docker image can now be pushed to a Docker repository (e.g. Docker Hub, Sonatype Nexus or Amazon
ECR). For further details on pushing to a Docker repository please visit:
2
• Docker Hub
3
• Sonatype Nexus 3.0
1
https://maven.apache.org/plugins/maven-deploy-plugin/
2
https://docs.docker.com/docker-hub/repos/#pushing-a-repository-image-to-docker-hub
3
https://support.sonatype.com/hc/en-us/articles/360000761828
50
CONFIDENTIAL Hints for Strategy Development
4
• Amazon ECR
Java bases Strategies typically consist of a single Java class where all logic is implemented inside event
handler methods (e.g. onInit, onBar, onTick, onOrderStatus, etc.)
The following two Starters are available to start a trading strategy in embedded and in distributed mode.
StrategyStarter
StrategyStarter starts a strategy in stand-alone mode running in a separate JVM process. The strategy
will use ActiveMQ message broker to receive market data and other events from the server JVM process.
The server JVM process is expected to be running before the strategy JVM is started.
EmbeddedStrategyStarter
EmbeddedStrategyStarter starts a strategy in single JVM (embedded) mode, when server and strategy
run in the same process. Market data and other events are delivered directly to the strategy instances by
a single event dispatcher.
AlgoTrader is an event-based system. All strategy related events are propagated to strategies as event objects
(e.g. Order, OrderStatus, Tick, Bar, etc.). Inside strategies these events are made available through event
handler methods, e.g.:
@Override
public void onBar(BarVO bar) {
// do something
}
Strategy classes can provide listeners for life-cycle events in order to receive notifications about strategy life-
cycle phase transitions and execute custom life-cycle dependent logic
4
https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-push-ecr-image.html
51
CONFIDENTIAL Java based Strategies
@Override
public void onInit(final LifecycleEventVO event) {
// do something
}
@Override
public void onPrefeed(final LifecycleEventVO event) {
// do something
}
For further information on life-cycle events please visit Section 23.4, “Session life-cycle events”
Often a strategy has several states that it runs through during execution (e.g. FLAT, PENDING_LONG,
PENDING_SHORT, LONG, SHORT, etc.). For these situations it is advisable to use a Java Enum, e.g.:
package ch.algotrader.strategy;
In case a strategy trades multiple instruments and each instrument has its own state it is suggested to create a
Metrics object for each instrument. The Metrics object is a simple Java POJO that holds the state per instrument
and potential other information regarding the instrument (e.g. values of technical indicators):
52
CONFIDENTIAL Java based Strategies
Often a Java Action is triggered multiple times by a certain situation, because the underlying cause takes a
finite amount of time to be resolved.
Example: The current market level exceeds a defined stop, which triggers a closing order. However during
the time the order is being executed at the market, additional market data events are received. Because the
position is not yet closed by that time, another undesired closing order might get placed.
To prevent actions from happening multiple times a state object mentioned in the previous section is again
very helpful.
Whenever the predefined signal condition is met the state will be set to PENDING.
@Component
public class ABCService extends StrategyService {
@Override
public void onInit(final LifecycleEventVO event) {
@Override
public void onTick(TickVO tick) {
53
CONFIDENTIAL Java based Strategies
@Override
public void onOrderStatus(OrderStatusVO orderStatus) {
if (Status.EXECUTED == orderStatus.getStatus()) {
Strategies that trade multiple securities at the same time often have the requirement to associate a particular
order with a certain strategy. It is therefore often necessary to "tag" an order with additional meta data. This can
be accomplished using order properties, see Section 17.2.3, “Order Properties”. In tagging orders using order
properties it is also possible to distinguish automatically placed orders from manually placed orders (through
AlgoTrader client or external broker GUI).
Typically a strategy running corresponds to one entry in the database table strategy. In certain situations it
may be necessary for a running strategy to place orders into separate entries in the database table strategy.
Reasons for this might be:
• A strategy wants to have of multiple positions on the same instrument (i.e. long and short positions at the
same time)
Example:
54
CONFIDENTIAL Java based Strategies
A strategy named EXAMPLE would like to interact with the two separate entries in the database named LONG
and SHORT. For this purpose the strategy needs to be started with the strategyName set to EXAMPLE inside the
fileconf.properties . Alternatively the properties can be changed via Section 2.4, “VM Options”:
strategyName = EXAMPLE
In addition one needs to create the two entries EXAMPLE|LONG and EXAMPLE|SHORT in the database table
strategy. the | separator causes strategy events like OrderStatusVO, FillVO and TransactionVO are
propagated to the running strategy EXAMPLE.
Note
Using other characters than | will not work and will cause strategy events not to arrive in the
EXAMPLE strategy.
4. On First Tick (see Section 8.4.8.1, “First tick callback”) open a new Position
When dealing with futures one has to decide on when to roll from the Front-Month future into the Back-Month
future. For this different philosophies exist:
• Roll on a fixed day prior to the expiration date or the first notice date
• Roll when the Back-Month future starts having a higher traded volume than the Front-Month future
Since Futures have an expiration date and are therefore not continuous, it is often not possible to base
indicators on them. There are several methods for dealing with this situation:
• use the raw data and ignore the fact that price time series will have jumps
• On the rollover day, add the difference between yesterday's closing price of the Back-Month future and
yesterday's closing price of the Front-Month future to the combined time series. Alternatively one can use
the difference between today's opening price of the Back-Month future and yesterday's closing price of the
Front-Month future if only the time series for the generic 1st future is available. This method can be used for
P&L calculation it might however lead to negative prices on long time series.
55
CONFIDENTIAL Esper based Strategies
• Instead of using addition as mentioned in the previous item use multiplication. This method however cannot
be used for P&L calculations. Depending on the indicator in use either addition or multiplication will be
adequate.
Please see Section 5.6, “Subscribing/Unsubscribing securities during a simulation” for options on how to back
test futures and options based strategies that require multiple securities to be subscribed and unsubscribed
during the back test.
Many strategies require that the local system clock is in sync with the remote server clock. Unfortunately it is
not possible to directly sync the local time with the remote server clock. However most servers are using NTP
or some other time sync mechanism to make sure there local clock is in sync with the official time defined by
NTP servers. As a result local system clock should also be synchronized with NTP servers. In most cases this
can be done directly through the operating system (e.g. Windows Time Service). For Windows Servers there
5
is also the time sync tool available which tends to be more precise than the Windows Time Service.
Strategy code running runs outside of Hibernate Sessions. Traversal along the Object Tree beyond what is
already loaded into the Hibernate session will throw a LazyInitializationException. All n-to-1 associations
(e.g. Position.getStrategy) will be fetched eagerly so no LazyInitializationException will be throws.
Traverse of an uninitialized relation from Position to Security in strategy code would look like this:
5
http://www.timesynctool.com/
56
CONFIDENTIAL Esper based Strategies
By means of the TestSubscriber, selected values of a Statement can be printed to the Console.
@Name('TEST')
@Subscriber(className='ch.algotrader.esper.subscriber.TestSubscriber')
@SimulationOnly
select
valueA,
valueB,
valueC
from
TestEvent;
Often strategies are based on a technical indicator. During simulation it is often desirable to log the values of
such an indicator to a log file. This can be done with the following statement:
@Name('INSERT_INTO_INDICATOR')
@Listeners(classNames={'ch.algotrader.esper.listener.IndicatorListener'})
select
dateTime.toDate() as dateTime,
valueA,
valueB
valueC
from
Indicator;
Above statement will log dateTime, valueA, valueB and valueC to the file files/report/
IndicatorReport.csv
Esper has a sophisticated variable management functionality. It is possible to access those variables from Java
through the following methods:
57
CONFIDENTIAL Esper based Strategies
6
For further details on Esper Variables please visit the Esper Documentation
Complex computations should be handled outside Esper. For this purpose, it is often easier to create a small
Utility class and use its methods inside the statement. Example:
package ch.algotrader.strategy;
<auto-import import-name="ch.algotrader.strategy.MyUtil"/>
Now, the Utility class can be used in an Esper Statement like this to adjust a trailing stop loss:
select
tick.last,
value
from
TickVO as tick,
method:MyUtil.calculate(tick.last) as value
7
For further details on using static methods please visit the Esper documentation
If two statements are based on the same Event, it is necessary to set a priority for each statement to make
sure, the system behaves deterministically:
@Name('STATEMENT_1')
@Priority(2)
select * from A;
6
http://esper.espertech.com/release-7.0.0/esper-reference/html/epl_clauses.html#variables_overview
7
http://esper.espertech.com/release-7.0.0/esper-reference/html/epl_clauses.html#joining_method_syntax
58
CONFIDENTIAL Esper based Strategies
@Name('STATEMENT_2')
@Priority(1)
select * from A;
8
For further details on statement priorities please visit the Esper documentation
@Override
protected void onPrefeed(final LifecycleEventVO event) {
switch (event.getOperationMode()) {
case REAL_TIME:
feedMarketData();
break;
}
}
This method will load all ticks for the security (defined by securityId) for the last hour. It will then feed all of
them sequentially to the local EsperEngine. Make sure collection you are providing to feedEventsToEngine
method is sorted in ascending order by dateTime. In the example above getTicksByMinDate returns ticks in
the correct order.
Note
Feeding of live market data only starts in the START live cycle phase. This prevents mix-up of
historical pre-feed data and live market data.
8
http://esper.espertech.com/release-7.0.0/esper-reference/html/epl_clauses.html#epl-syntax-annotation
59
CONFIDENTIAL Esper based Strategies
package ch.algotrader.strategy;
If the variable needs to have an initial value, the variable has to be declared with a statement.
@Name('CREATE_VAR_STATE')
create variable ch.algotrader.enumeration.State state = State.FLAT;
It is now possible to query current state inside Esper statements like this:
9
In case a strategy trades multiple instruments and each instrument has its own state an Esper Named Window
can be used instead of an Esper Variable.
@Name('METRICS_WINDOW')
create window
MetricsWindow.std:lastevent()
as
Metrics;
@Name('INSERT_INTO_METRICS_WINDOW')
insert into
MetricsWindow
select
*
from
Metrics;
The first statement creates the Named Window and the second statements inserts all Metrics events into the
Named Window.
9
http://esper.espertech.com/release-7.0.0/esper-reference/html/nwtable.html
60
CONFIDENTIAL Esper based Strategies
The Metrics object is a simple Java POJO that holds the state per instrument (and potential other information
regarding the instrument):
To initialize the Named Window one Metrics event per instrument has to be sent into the Esper Engine upon
startup of the strategy
It is now possible to query current state inside Esper statements like this:
Often a Java Action is triggered multiple times by a certain situation, because the underlying cause takes a
finite amount of time to be resolved.
Example: The current market level exceeds a defined stop, which triggers a closing order. However during
the time the order is being executed at the market, additional market data events are received. Because the
position is not yet closed by that time, another undesired closing order might get placed.
To prevent actions from happening multiple times a state object mentioned in the previous section is again
very helpful.
Whenever the predefined signal condition is met the state will be set to PENDING
61
CONFIDENTIAL Esper based Strategies
@Name('LONG_TRIGGER')
on
//trigger event (can also be the MetricsWindow itself)
update
MetricsWindow as metricsWindow
set
state = State.PENDING_LONG
where
// condition
and
metricsWindow.state = State.SHORT or metricsWindow.state = State.FLAT
@Name('SEND_ORDER')
@Subscriber(className='xyzService#sendOrder')
select
state
from
MetricsWindow
where
state = State.PENDING_LONG
or
state = State.PENDING_SHORT;
Once the state has been changed to PENDING_LONG the statement SEND_ORDER will trigger an order to be sent.
Since the LONG_TRIGGER statement only triggers if the state is either SHORT or FLAT it will not trigger again once
the state has been set to PENDING_LONG.
Once the order has been fully executed (potentially using a Section 8.4.8.2, “Trade callback”) the state needs
to be changed to LONG
Often strategies rely on indicators that are based on OHLC Bars. Since Live Market Data (i.e. Ticks) are not
delivered in the format of Bars, it is often necessary to create Bars from arriving Ticks. Section 18.1, “Creation
of Bars based on Ticks” explains how to do this.
Especially for Option and Future based strategies it is often not possible to subscribe to the entire Option
or Futures Chain in advance. Therefore the actual Security the strategy is interested in, is evaluated and
subscribed to at runtime. There are often steps that should take place immediately after the first market data
event has arrived for such a security.
62
CONFIDENTIAL Esper based Strategies
Section 8.4.8.1, “First tick callback” explains how to use a FirstTickCallback for this purpose
A common use case is to wait for the full execution or cancellation of an order and then take some additional
action.
Section 8.4.8.2, “Trade callback” explains how to use a TradeCallback for this purpose.
In this context it is also important to remember that when trying to close a position there might still be open
orders associated with the corresponding security and strategy. It is suggested to cancel all corresponding
orders, attach a TradeCallback to the cancellation and only close the position once all cancels have been
confirmed.
Also keep in mind that an order might receive multiple fills in live trading. For example if one wants to send a
Stop Order for each executed Order it is important to use the filled quantity and not on the original order quantity.
In handling partial fills the TargetPositionOrder can be useful, please see: Chapter 24, Execution Algos
Upon system startup strategies run through the life cycle phases as defined in Section 3.2, “Live Trading
Mode”. At the same time market data connections are established. Due to the asynchronous nature of these
two processes it is not predetermined which one will complete first. Typically within the START life cycle phase
market data is subscribed. This however will fail if the market data adapter has not reached its SUBSCRIBED
state by that time. To circumvent this issue the following Esper patter can be used, which waits for both the
first LifecyclePhaseVO and SessionEventVO to arrive before it fires:
select *
from pattern[LifecycleEventVO(phase=LifecyclePhase.`START`)
and SessionEventVO(state=ConnectionState.SUBSCRIBED)];
@Subscriber(className='OrderService#cancelAllOrders')
select
null
from
pattern [every (timer:at(0, 18, *, *, 1:5)];
The above statement will cancel all open orders at 18:00:00 Mo-Fri.
63
CONFIDENTIAL Strategy life-cycle events
All trading strategies allocate a certain amount of memory to objects. If however those object allocations are
never released the corresponding memory will not get freed which will lead to a memory leak. This is especially
a concern for strategies that are kept running for an extended period of time.
In addition one has to be careful with Esper statements not to introduce memory leaks. For example the
following statement is potentially dangerous since it just keeps all Tick Events it receives:
In addition the AlgoTrader life cycle manager supports two modes of operation: REAL_TIME and SIMULATION.
In both modes all strategies transition through the same life-cycle phases. Depending on the operation mode
not all phases may be relevant.
Phase Description
INIT Called after deploying all modules of the Server Engine but before deploying the init
modules of the Strategy Engines.
PREFEED Called after deploying the init modules with Engine#deployInitModules() of Strategy
Engines but before deploying their run modules and before feeding any market data events.
START Called after deploying the run modules of all Engines. At this time Market data events start
feeding into strategy engines.
RUNNING Called after the START phase to inform subscribers that all components have properly started
and the system is fully up and ready to use.
EXIT In SIMULATION mode this event occurs after finishing the simulation and before sending an
EndOfSimulationVO event and before publishing simulation results. In REAL_TIME operation
mode an EXIT life cycle event occurs when the virtual machine begins its shutdown.
Strategies can subscribe to these life-cycle events by overwriting the corresponding live-cycle method of the
StrategyService:
@Override
public void onInit(final LifecycleEventVO event) {
...
}
@Override
64
CONFIDENTIAL Strategy Development in Python
@Override
public void onStart(final LifecycleEventVO event) {
...
}
@Override
public void onRunning(final LifecycleEventVO event) {
...
}
@Override
public void onExit(final LifecycleEventVO event) {
...
}
Additionally, the user has the availability to subscribe to all incoming Life cycle events at once by overriding the
onLifecycleEvent method instead. This is especially useful in Distributed mode, when there are two types
of life-cycle: STRATEGY and SERVER.
@Override
public void onLifecycleEvent(final LifecycleEventVO event) {
...
}
Important
For an example of a strategy written in Python see Appendix N, Example strategy "EMA" in Python and
Appendix O, Example strategy "BreakOut" in Python
65
CONFIDENTIAL Strategy Development in Python
In order to test or run a Python based strategy, the strategy is implemented using AlgoTrader Python Interface
classes and functions and runs in the Python interpreter. AlgoTrader is based on Java and needs to be run
separately. Communication between Python and Java is implemented using the Py4J framework.
AlgoTrader (running in Java) can be started using the EmbeddedStrategyStarter (for live trading, or
live trading against an exchange simulator,Section 5.1, “Exchange Simulator”), StrategyStarter (for the
same purposes but in distributed mode,Section 3.2.2, “Distributed Mode”) or using the SimulationStarter
for strategy backtesting on historical data (see Section 3.1, “Simulation Mode”). The Spring profile
pythonIntegration needs to be activated with those.
In order to implement a strategy in Python, the main step is the same as in Java, extending the
StrategyService class. It is found in the algotrader_com.services.strategy package.
The strategy implementation overrides event handler methods to receive data or events it needs from
AlgoTrader. Method names mirror Java names in the Python code-style in lower case with underscores, e.g.
on_bar is the equivalent of onBar in Java. Method parameters are identical.
Domain classes in Python mirror domain classes in Java, e.g. MarketOrder in Python is identical to
MarketOrder in Java, except for names of fields changed to follow Python code-style. All classes including
basic types are converted from their Java version to the Python one or vice versa automatically.
The following code sample shows how to place a market order on a new bar:
class CustomStrategy(StrategyService):
...
def on_bar(self, bar):
market_order = MarketOrder(quantity=Decimal("10000"), side="BUY",
strategy_id=1, account_id=101,
security_id=25)
self.python_to_at_entry_point.order_service.send_order(market_order)
...
The connect_to_algotrader function also has 3 optional parameters. First can be used to specify which
event handler methods the strategy wants to subscribe to. This can be used as a means of performance
optimization to prevent unnecessary calls from AlgoTrader to Python. If this optional parameter is not set, all
event handler methods are subscribed automatically. Other two can be used to configure ports that will be used
to communicate with AlgoTrader PythonService. It's needed to change default ports for every Python strategy
running simultaneously. By default AlgoTrader uses ports 25333, 25334.
66
CONFIDENTIAL Strategy Development in Python
When overriding default ports in python strategy it's needed to change them also for Java part of the strategy.
It can be done using following VM arguments in StrategyStarter:
-DpythonInterface.java.port=25335
-DpythonInterface.python.port=25336
Depending on the development environment you use you should have all necessary facilities for development,
e.g. code completion functionality in PyCharm IDE:
AlgoTrader Python Interface uses type hint comments that are compatible with both 2 and 3 versions of Python.
They serve as documentation and also enable static analysis of types used in the Python strategy code that
uses the interface. Classes, methods and functions are documented using Google style docstrings.
67
CONFIDENTIAL Python Strategy Performance
Note that while services (e.g. OrderService) generally contain the same methods as their Java counterparts,
some methods are not included and some have different names because Python doesn't allow method
overloading (multiple methods with the same name and different parameters in the same class).
10
For a full documentation of available services and domain objects visit our Python Documentation
It is possible to use Section 5.4, “Automated Parameter Optimization” with Python based strategies This is done
by running AlgoTrader using SimulationStarter with optimizeSingleParamLinear, optimizeMultiParam, etc.
options. Each iteration started by the optimization resets the strategy implementation to its initial state. Note
that it's necessary to write Python strategies so that they don't use variables from outside of the strategy class
scope. Variables not defined in the strategy class are not reset between optimization iterations and could
wrongly affect the results of the simulation.
10
http://doc.algotrader.com/pythondoc/index.html
68
Chapter 5. CONFIDENTIAL
Strategy Backtesting
Historical data for back testing can be provided to strategies either via .csv files or via Section 19.1, “InfluxDB”.
Securities specified within the table subscription or securities subscribed to via the SubscriptionService are
fed to the Strategy.
To feed data from CSV files during a back test the following property needs to be set inside conf.properties.
Alternatively the properties can be changed via Section 2.4, “VM Options”:
For further details on file format and storage location of CSV files please see Section 19.8, “Market Data File
Format”.
Note
When feeding historical data with CSV files it is not possible to set a particular time range for
the simulation. If this is a requirement please feed data through InfluxDB
To feed data from InfluxDB during a back test the following properties need to be set inside conf.properties.
Alternatively the properties can be changed via Section 2.4, “VM Options”:
Backtesting strategies written in Python uses the same procedures as backtesting strategies written in Java,
for details see Section 4.5, “Strategy Development in Python”
AlgoTrader contains a DefaultExecutionModel which provides a reasonable default logic for executing
orders. Fees/commissions are calculated based on security / security_family properties:
69
CONFIDENTIAL Simulation Process
• EXECUTION_COMMISSION_PER_ORDER
• EXECUTION_COMMISSION_PER_CONTRACT
• EXECUTION_COMMISSION_IN_PERCENT
• SLIPPAGE_PCT
The DefaultExecutionModel always charges commissions in the quote currency of the order. E.g. when
buying BTC/USD the fees will be charged in USD.
It is possible to replace the DefaultExecutionModel with a custom implementation that implements the
interface ExecutionModel. The custom Execution Model needs to be registered as a Spring Bean in the
following locations:
• For live trading (to be used globally): /META-INF/applicationContext-env.xml. This file needs to be in
the class path, e.g. in the conf project under src/main/resources.
During the simulation process transaction as well as position and cash_balance updates are executed in
the database. It is therefore possible to use a standard database reporting tool to perform additional analysis
on it.
To use the Exchange Simulator the Spring profile simulation has to be used, e.g.
-Dspring.profiles.active=simulation...
Note
Note than when using the Exchange Simulator in live trading, orders will be executed against
live data internally and will not get sent to the external Broker or Exchange. If the Spring Profile
simulation is enabled all other external Order Services will be disabled.
-Dsimulation=true denotes a back test and will effectively disable external Market Data
services, so if the intention is to run exchange simulator against live market data, make sure
that this parameter is set to false
All external order services must be disabled, e.g. Spring profiles like bFX, bFL etc must be
inactive
70
CONFIDENTIAL Single Run Simulation
3. An initial amount (USD 1'000'000 per default) is allocated to each strategy (the initial amount can be changed
through the simulation.initialBalance setting inside conf.properties)
5. The life cycle phase INIT is broadcasted to all strategies. During this phase potential initiation steps can
be invoked.
6. All strategy initModules Modules are deployed (if using Esper based strategies)
7. The life cycle phase PREFEED is broadcasted to all strategies. During this phase technical indicators can be
initialized using historical data
8. All strategy runModules Modules are deployed (if using Esper based strategies)
9. Market data subscriptions are initialized based on entries in the table subscription
10.The life cycle phase START is broadcasted to all strategies. During this phase eventual actions like security
subscriptions can be taken care of
11.At that time the actual simulation starts and market data events are starting to be sent into the Esper Engines
12.The life cycle phase EXIT is broadcasted to all strategies. During this phase eventual cleanup actions can
be taken care of
13.At the end of each simulation run, metrics are printed to the console (if enabled), see Chapter 29, Metrics
22.The Excel based back test report is created and statistics are displayed to the console, see Section 5.5,
“Performance Statistics”
71
CONFIDENTIAL Automated Parameter Optimization
Using Numerical Optimization functions (i.e. Brent & Newton) optimal parameter ranges can be determined
in an automated fashion.
simulateBySingleParam
One Simulation run with a parameter set to the defined value. The example below will do one run with parameter
a set to 0.8
simulateBySingleParam a:0.8
simulateByMultiParam
One Simulation run with multiple parameters set to defined values. The example below will do one run with
parameter a set to 0.8 and b set to 12.0
simulateByMultiParam a:0.8,b:12.0
optimizeSingleParamLinear
Multiple Simulation runs by incrementing the value of one parameter within a defined interval. The example
below will increment the value of parameter a starting at 0.1 to 0.9, incrementing by 0.1 for each run
optimizeSingleParamLinear a:0.1:0.9:0.1
optimizeSingleParamByValues
Multiple Simulation runs by iterating the value of one parameter according to defined list. The example below
will iterate the value of parameter a through the following list: 0.2, 0.8, 0.9 and 1.2
optimizeSingleParamByValues a:0.2:0.8:0.9:1.2
optimizeSingleParam
Multiple Simulation runs by setting the value of one parameter within the defined range and trying to find the
maximum Sharpe Ratio. The optimizer being used is UnivariateRealOptimizer. The example below will set
the value of parameter a between 0.1 and 1.0 (accuracy 0.01).
1
https://www.algotrader.com/cloud-based-trading-strategy-optimization-using-algotrader-2-1-amazon-elastic-map-reduce/
72
CONFIDENTIAL Automated Parameter Optimization
optimizeSingleParam a:0.1:1.0:0.01
optimizeMultiParamLinear
Multiple Simulation runs by doing a matrix Optimization of 2 or 3 parameters by incrementing their values within
a defined interval. The example below will iterate through all possible combinations by incrementing the value
of parameter a starting at 0.1 to 0.9 (increment: 0.1), and incrementing the value of parameter b starting at
10.0 to 100.0 (increment: 5.0)
optimizeMultiParam
Multiple Simulation runs by adjusting the value of multiple parameters around their start values and trying to
find the maximum Sharpe Ratio. The example below will start the optimization by setting the value of parameter
a to 85.0 and parameter b to 150.0
In order to process parameters with the correct decimal scale the following property needs to be updated inside
conf.properties. Alternatively the property can be changed via Section 2.4, “VM Options”:
Note
In order for the parameter optimization to work the following properties need to be updated inside
conf.properties. Alternatively the properties can be changed via Section 2.4, “VM Options”:
# if set to true, the Excel back test report will open at the end of a
simulation
report.openBackTestReport = true
Note
Before each back test run the Esper Engines will be reset. However Strategy services are not
reset. Due to this any state that is maintained within the Strategy service needs to be reset
within the onInit method.
73
CONFIDENTIAL Performance Statistics
Note
The values of Esper variables as well as Java properties get initialized on startup using Spring.
The actual optimization only happens once the Spring context is fully initialized. Due to this it
is necessary to overwrite the default values in the onInit from system. properties. This can be
done as follows for Esper variables:
getEngine().setVariableValue("propertyA", System.getProperty("propertyA"));
this.propertyB = System.getProperty("propertyB");
74
CONFIDENTIAL Performance Statistics
75
CONFIDENTIAL Performance Statistics
• BackTestReport.xlsm: the Excel based back test report (see image above)
The Excel based back test report can be modified in terms of formatting and layout if needed.
In addition when running a single simulation run, statistics will be displayed to the console in the following
format:
When running parameter optimizations, statistics will be displayed in the following summary format showing
the current parameter values as well as corresponding performance statistics of one run on one single line:
In addition to above General Performance statistics, strategy specific performance statistics are printed to the
console. These are retrieved by calling the method StrategyService.getSimulationResults of the strategy.
The amount of output during the simulation can be adjusted by setting the Log Level according to Chapter 30,
Logging.
76
CONFIDENTIAL
Subscribing/Unsubscribing securities during a simulation
Some strategies that are based on multiple securities need to subscribe and unsubscribe securities during the
simulation. A typical example for this would be a Futures bases strategy that needs to unsubscribe an expiring
Future and at the same time subscribe to the next Future in the chain.
As of now subscribing/unsubscribing in simulation is supported only for the InfluxDB event feed
dataSource.0.dataSourceType = DB
To subscribe or unsubscribe securities during a simulation call the respective method(s) of the
SubscriptionService Section 7.2.20, “Subscription Service”:
Subscribing securities during strategy runtime adds some performance overhead, especially if you subscribe
multiple securities at once. If you want to subscribe a batch of securities at once and increase performance,
you can pause the data stream, add your subscriptions and then resume. This affects only simulation mode
to make dataSource coordination more optimal. This has no effect on live mode and therefore can be safely
used for both backtesting and live runs.
77
CONFIDENTIAL
Subscribing/Unsubscribing securities during a simulation
Warning
As already mentioned, this feature is applicable only for the InfluxDB based simulation. When
you subscribe/unsubscribe securities in a simualtion, other data sources (e.g. CSV) will be reset
and closed, and will stop supplying events until the end of the simulation or throw an Exception.
78
Chapter 6. CONFIDENTIAL
Architecture
The architecture of AlgoTrader is composed of the following components.
The AlgoTrader Server provides the infrastructure for all strategies running on top of it. The AlgoTrader Server
holds the main Esper Complex Event Processing (CEP) engine. It is responsible for all domain model objects
and their persistence in the database. Different market data adapters are available to process live and historical
market data. On the other end adapters for different execution brokers and exchanges are available, which are
responsible for placing orders and receiving executions.
The AlgoTrader Server also provides business components for back testing, parameter optimization, analysis,
execution management, risk management, reporting and hedging.
On top of the AlgoTrader Server any number of strategies can be deployed. Strategies can either be coded
purely in Java or in a combination of Java and Esper code. Esper based strategies make use of a dedicated
Esper CEP engine. A strategy can deploy any number of SQL-like Esper statements for time-based market
data analysis and signals generation. Esper statements can invoke any number of procedural actions, such
as placing an order or closing a position, which are coded in Java. The combination of Esper statements and
Java Code provides a best-of-both-worlds approach.
For management and monitoring of the system different GUI clients exist. The AlgoTrader UI provides trading
related functionality like charting, orders, positions & market data. In this manual we describe using IntelliJ
IDEA for strategy development.
79
Chapter 7. CONFIDENTIAL
Domain Model
The following sections describe the Domain Model of the system using UML (unified modeling language).
7.1. Entities
The Main Entities of the system are specified within the following table:
Entity Description
Strategy Each object of this class represents a running strategy within the system
Security This is the base class of all securities in the system
SecurityFamily A group of Securities (e.g. all S&P 500 Futures)
Subscription Market Data Subscriptions of a Strategy for a particular Security are represented
by this class. For every Subscription the Strategy will receive Live Market Data
for the corresponding Security
MarketDataEvent Represents any type of market data related to a particular Security
Order An Order for a particular Security
Account An account held with an external Broker or Exchange
80
CONFIDENTIAL Entities
Entity Description
Transaction Each Fill is recorded as a transaction in the database using this entity. In addition
the table transaction also stores transactions like interest, debit, credit & fees
Position Represents an exposure to a certain Security on the Market
Exchange An electronic exchange or venue
Quote_Request Represents a request for quote sent to a broker/exchange
Quote A quote response for a Quote_Request
A full list of all Entities of the system will be discussed throughout the next sections. Entities of the system can
be categorized into the following three areas:
Reference Data
Represent static referential data like:
Market Data
Represent external events (Tick and Bar) coming from market data providers or internal events (Generic
Events) coming from another trading strategy. Market Data is typically immutable and of only momentary
interest to the trading strategies. Market Data Events are available as Value Objects only (but not as
Entities):
MarketDataEventVO and its subclasses TickVO, BarVO, QuoteVO, BidVO, AskVO, TradeVO and
GenericTickVO as well as any type of GenericEventVO
Transaction Data
Represent the financial state of trading strategies. Some of them (e.g. Transactions and Measurements)
are immutable whereas others (e.g. Positions and Balances) are mutable and change their values while
Orders are getting executed:
Besides providing Getters and Setters all Entities provide the following common features:
VO Converter
The static inner Converter class can be used to automatically convert the Entity to its corresponding Value
Object, see Section 7.3, “Value Object”
Factory
The static inner Factory class can be used to create new instances of an Entity
81
CONFIDENTIAL Strategy
7.1.1. Strategy
Regarding the question "what is a productive strategy?". It essentially up to the user, what he would like to
consider as one strategy. A strategy can have one or multiple instruments. And also regarding trading logic
there is no limitation.
However please note that the entire performance and reporting functionality of AlgoTrader happens on the
strategy level. So if one would like to see performance metrics on an instrument level one would have to
instantiate multiple strategies. Also, if it is a requirement to start and stop individual functions separately, it is
best to put them into two separate strategies.
On the technical side each separate strategy allocates a certain amount of overhead (memory and CPU). For
that reason it is best to combine functionality into as few strategies as possible if there are no good reasons
not to separate them.
The field autoActivate means that if a strategy is set to active corresponding market data subscriptions are
initiated automatically upon startup of the system. This is useful in distributed mode when strategies and the
server run in different processes. If you restart the server in this scenario, subscriptions for the strategies are
automatically loaded again (without having to restart the strategies).
82
CONFIDENTIAL Strategy
There are several classes that are directly related to the strategy
Class Description
PortfolioValue On regular time intervals certain portfolio values (e.g. NetLiqValue,
CashBalance, etc.) are saved to the database for every strategy.
Attribute Description
cashBalance Market value of all open forex positions + cash amount available to the
strategy
marketValue Market value of all open (non-forex) positions
netLiqValue Cash balance + market value
realizedPL Realized P&L of all positions
unrealizedPL Unrealized P&L of all positions
All valuations (strategy and position level) can be queried via the PortfolioService. Fees are considered in
the calculations if properly configured.
83
CONFIDENTIAL Security
7.1.2. Security
The above UML Class diagram shows all available Security classes
Entity Description
Option A tradable Option
Future A tradable Future
Forex A Foreign Exchange Currency (FX) or Crypto Currency
Stock A Single Stock
Fund An ETF, Mutual Fund, etc.
Index An Index (e.g. Equity, Volatility, Commodity)
GenericFuture A virtual Future with a fixed duration
84
CONFIDENTIAL Market Data Events
Entity Description
IntrestRate Any type of Interest Rate
Bond A corporate or government Bond
Commodity A physical Commodity (e.g. Energy, Metals, Agriculture or Livestock). For
Commodity Futures use Future.
PerpetualSwap A perpetual swap contract supported by various crypto derivatives exchanges
(e.g. BitMEX)
Combination A synthetic security composed of one or many Components (see Chapter 25,
Synthetic Securities and Derivative Spreads)
SecurityReference A generic link between one security and another
• getValue which calculates the current (market) value of the instrument based on a quantity and a price
parameter
• getPrice which calculates the current price of the instrument based on a (market) value and a quantity
parameter
For most instruments the formula is:
A Security Family contains common information about an entire family of securities (i.e. all general information
about options on S&P500 are stored using this class). The class provides fields like MIN_QTY, MAX_QTY and
MIN_PRICE. This information is used by ReferenceDataService when downloading new future and option
changes, values from Security Family will then be copied onto the newly created Futures and/or Options. In
regular operation mode (i.e. simulation of live trading) the information from Security Families are not used but
only the information contained within Securities.
SecurityReference Is a generic link between one security the owner and another the target. Using this class
it is possible for a Security to have links to multiple other Securities.
85
CONFIDENTIAL Market Data Events
Entity Description
BarVO Open-High-Low-Close Price Bars, also containing volumes and volume weighted
average prices
TickVO Snapshot of the market at a particular point in time, containing information like
a
last price, last time, bid, ask, volume , etc..
QuoteVO Its subclasses represent the current best bid and offer BidVO and AskVO
TradeVO An actual order that was executed on the market, containing information like last
price, last size and volume
GenericTickVO Represents additional price information made available by market data providers
(e.g. open price, close price, vwap price)
OrderBookVO A snapshot of the order book for a security from the trading venue at a particular
moment in time. It contains bid and ask price levels represented by the class
OrderBookLevelVO. OrderBookLevelVO, in turn, contains a price, the number of
orders with that price and the total amount of a security in those orders.
AggregatedOrderBookVO Combines by symbol order books for a security from multiple venues. Like
its regular counterpart, it contains bid and ask price levels represented
by the class AggregatedOrderBookLevelVO. The
difference between
AggregatedOrderBookLevelVO and OrderBookLevelVO is that the former
provides the number of orders and the amount of a security summarized across
venues.
a
Cumulative traded volume within the specified interval, stored in the tradedVolumeInInterval field of TickVO . The interval length
in seconds is defined by the tradedVolumeInterval configuration property
For simulation purposes Bars and Ticks can be supplied through CSV files (see Section 19.8, “Market Data
File Format”) or through InfluxDB (see Chapter 19, Historical Data). In live trading Trades, Bids and Asks are
received by the broker / exchange specific MarketDataService.
For conversion between Ticks and Bars please see Section 18.1, “Creation of Bars based on Ticks”.
Note
• misc.minNumOrderBookLevels sets the minimal number of levels on each side of the order
book in case the misc.maxOrderBookVOdepth filter was too strict and caused removing a lot
of levels (applies often for low-priced securities)
86
CONFIDENTIAL Market Data Events
• {adapter}.orderbookfilter sets the minimum price level for an order book, where
{adapter} is a shorthand for adapter, e.g. bmx.orderbookfilter for Bitmex adapter
Note
87
CONFIDENTIAL Order
7.1.4. Order
The following UML Class diagram shows the Order and its related subclasses.
Entity Description
Order Base Class for all Order Types
OrderStatus Order Status changes received back from the Broker / Exchange (e.g.
PARTIALLY_EXECUTED or CANCELLED) are represented by this class
OrderCompletion Similar to Order Status but only gets created once an order is fully
executed or cancelled and all corresponding database activity has been
completed.
OrderProperty An arbitrary property that can be attached to an Order. Through the type
attribute the OrderProperty can be marked as internal only or as fix
property or as IB property.
Fill Filled orders are represented by this Class
Transaction Each Fill is recorded as a transaction in the database using this entity.
In addition the table transaction also carries transactions like INTREST,
DEBIT, CREDIT & FEES
88
CONFIDENTIAL Account
Entity Description
SimpleOrder An Order that can be sent directly to the market
MarketOrder Predefined SimpleOrder types
LimitOrder
StopOrder
StopLimitOrder
Note
AlgoOrders and Order parent/child associations are persisted to the database. After a system
restart, pending AlgoOrder will be visible but it will not continue execution automatically - it will
not create new child orders. Execution reports for existing child orders will be processed.
7.1.5. Account
89
CONFIDENTIAL Account
An Account represents either an actual account, an account group (IB specific) or an allocation profile (IB
specific). An account is assigned to a particular adapterType (e.g. IB_NATIVE or FXCM_FIX) which identifies
the OrderService to use for this account. In addition the field sessionQualifier which is needed to define the
actual session in place (for FIX Connections). With this setup, it is possible to have multiple Sessions (session
qualifiers) per AdapterType and to have multiple Accounts per Session. If the field active is set to true a
potential corresponding Fix session will be activated.
Optionally an accountServiceType (e.g. IB_NATIVE or BFX) can be added which identifies the
AccountService to use for this account.
Accounts have an optional dependency to Exchange for cases when an account can only be used to trade on
one single Exchange (typical for Crypto Currency Exchanges).
Note
Orders sent to the market will always contain Account related information in an adequate way
(e.g. as a FIX Tag 1). Also Transactions which are based on an actual order will have an
association with a particular Account. However Positions do not hold any information regarding
Accounts. It is thus possible that a Position holds aggregated Quantities from several external
Accounts. Also it is possible to open a position through on account but then close it through
another (i.e. when using separate execution and clearing brokers). With this setup Strategies
do not have to worry about the actual Accounts the funds are located in. This way, a strategy
will always only see one Position per Security.
90
CONFIDENTIAL Transaction
7.1.6. Transaction
Each Fill is recorded as a transaction in the database using this entity. In addition the table transaction also
stores transactions like INTREST, DEBIT, CREDIT & FEES. A transaction is immutable and contains all relevant
information like dateTime, quantity, price, executionCommissions, clearingCommissions and fees as
well as references to Account, Strategy, Security and Position.
Depending on the type of transaction the field quantity has the following values:
• BUY: > 0
• SELL: < 0
• CREDIT: 1
• EXCHANGE_CREDIT: 1
• INTREST_RECEIVED: 1
91
CONFIDENTIAL Position
• REFUND : 1
• DIVIDEND : 1
• DEBIT: -1
• EXCHANGE_DEBIT: -1
• INTREST_PAID: -1
Some crypto exchanges provide fee information. If the fees are in the currency of the transaction, they are
stored in the fee attribute of the transaction. In case the fees are charged in another currency (for example
Binance charges in its own currency - BNB), a new transaction is created with transactionType = FEES,
quantity = -1 for fees paid (and quantity = -1 for fees received, e.g. maker rebates), price = fee value and
currency = fee currency.
7.1.7. Position
For any Strategy holding a particular Security a Position is created in the database. Even if this position is later
on closed (i.e. quantity = 0) the position will still remain in the database, because the associated Transactions
still have references to it.
In general, position values (e.g. marketPrice, marketValue, averagePrice, cost, unrealizedPL &
realizedPL) are calculated per actual strategy related position and show the price that would need to payed
if the position was closed at this moment
92
CONFIDENTIAL Cash Balance
Attribute Description
realizedPL Total profit of closed parts of a position (parts of a position might still be open)
unrealizedPL Profit of the currently open part of a position
cost Total cost incurred to open the current position (potentially through multiple
orders). These values are based on the fee configurations
All valuations (strategy and position level) are available through the Section 7.2.12, “Portfolio Service”.
A CashBalance represents the current cash amount of a particular strategy in a particular currency.
Warning
Cash Balances are derived by taking all Transactions of the given Security and Strategy into
account. It is therefore important not to modify Cash Balance entries directly in the database. In
case transactions are added or modified manually to the database, please use the management
action reset position and cash balances in the Figure 11.3, “AlgoTrader UI Settings”
7.1.9. Subscription
Market Data Subscriptions of a Strategy for particular Securities are represented by this class. For every
Subscription the Strategy will receive Live Market Data for the corresponding Security
93
CONFIDENTIAL Exchange
7.1.10. Exchange
Exchanges around the world have different trading hours. Quit often there are different trading hours even for
different securities trading on the same exchange. In addition each exchange typically has different holidays
or days where trading starts late or trading stops early. Especially for futures trading there are often small
gaps between different trading periods of the same trading date. FX trading is often available 24 hours a day
without any gaps.
All of these scenarios are captured and maintained through the Entities Exchange, TradingHours and Holiday:
Entity Description
Exchange Represents an individual Security, a group of Securities or an entire Exchange
(if all Securities have the same trading hours). An Exchange has a name, a code
(typically MIC) as well as a time zone.
TradingHours Defines an individual trading period (e.g. 09:00am to 16:30pm). In addition
TradingHours identify the weekdays they are valid for.
94
CONFIDENTIAL Order Preference
Class Description
OrderPreference This class allows definition of order default values (e.g. account, order type,
delays, etc.). Except for the order type, all values have to be defined through
Properties.
95
CONFIDENTIAL Quote Request and Quote
A request for quote (RfQ) is a process in which a company requests a quote from broker/exchange for the
purchase or sale of a specific security.
Class Description
Quote_Request This class allows definition of request sent to broker/exchange for the
purchase or sale of specific security.
Quote This class represents response provided by broker/exchange for the quote
request.
96
CONFIDENTIAL Services
7.2. Services
The system is based on a Service Oriented Architecture (SOA). All operations of the system are provided as
Spring Services / Beans. The following groups of services exist:
1. Main Services, are available to both the AlgoTrader Server and Strategies
2. Client Services, which will be instantiated by each Strategy (and the AlgoTrader Server itself)
1
For a full list of all Services please visit our JavaDoc
Inside strategies all services are injected by the Spring Framework and can be accessed as follows withing
the strategy service:
Service Description
AccountService Responsible for retrieval of account balances and initiation of
withdrawals
CalendarService Responsible for information about Exchange trading hours and holidays
CombinationService Responsible for handling all Combination / Component related DB-
Operations.
FutureService Responsible for all future specific operations
HistoricalDataService Responsible for the retrieval of historical data from Historical Data
Providers
MarketDataService Responsible for the retrieval of market data as well as Subscription
Management.
1
http://doc.algotrader.com/javadoc/ch/algotrader/service/package-frame.html
97
CONFIDENTIAL Client Services
Service Description
MeasurementService Responsible for persistence and retrieval of Measurements related to
Strategy
OptionService Responsible for all option specific operations
OrderService Responsible for sending orders to the Broker / Exchange
PortfolioService Responsible for providing portfolio values
PositionService Responsible for management of positions, e.g. close position and
reduce position
PropertyService Responsible for persistence of Properties related to a PropertyHolder
ReferenceDataService Responsible for the download of option and future chains
RfqService Responsible for sending requests for quotes to the Broker / Exchange
Service Description
MarketDataCacheService Provides a strategy local cache of market data and FX conversion rates
LookupService Provides general data lookup operations to other services
ConfigAwareStrategyService Base class for all strategy services which has references to all necessary
services and implements all event listener interfaces. In addition the
service receives a reference to the strategy config
StrategyService Base class for all strategy services which has references to all necessary
services and implements all event listener interfaces
SubscriptionService This service is used by the strategy for subscription management. The
actual DB related operations are carried out by the MarketDataService.
The MarketDataService should not be called directly by strategies.
Especially when trading multiple exchanges around the globe the CalendarService becomes very useful. It
provides convenient methods like:
• isOpen (is the specified exchange open at the current time or at the specified date time). Will return true if
no TradingHours are defined
98
CONFIDENTIAL Combination Service
• isTradingDay (is the current day or the specified day a trading day at the specified exchange)
• getOpenTime (gets the open time of the specified exchange on the current day or the specified day)
• getCloseTime (gets the close time of the specified exchange on the current day or the specified day)
• getNextOpenTime (gets the next open time of the specified exchange after the current date time or the
specified date time)
• getNextCloseTime (gets the close open time of the specified exchange after the current date time or the
specified date time)
In addition the Calendar service provides methods to identify a particular trading day, which will be important
to associate a particular order for clearing. If a trading session overlaps from one day to another (e.g. starts on
Sunday 23:00pm), the trading day will be considered the day when the session ends (e.g. Monday). However
in this example Monday would need to be set to true in the corresponding TradingHours object.
Note
All dates and times in the CalendarService are converted to the system time, e.g. the market
opens at 09:30 EST but the system time zone is CET then the market opening time in the
CalendarService will be 15:30.
When trading one single exchange it is usually easiest to set the system time to the same time
zone of the exchange.
When trading exchanges in different time zones one has the choice of setting the system to
clock to the same time zone as one of the exchanges or leave the system time set to the local
time zone.
99
CONFIDENTIAL Market Data Service
AlgoTrader provides several Market Data Interfaces out-of-the-box. Live market data is available to trading
strategies running within the system. For further details please see Chapter 18, Market Data
The MeasurementService allows storage of arbitrary measurements in the database. Measurements contain
a name, a time stamp and a value of type Integer, Double, Money (BigDecimal), Text (String) or Boolean.
Only one value is allowed per measurement (i.e. one record cannot store both Integer and String values for
example. In addition a Measurement also needs to have a reference to a strategy.
A Measurement can be created as follows whereas the time stamp will be set according to the current system
time:
getMeasurementService().deleteMeasurement(measurementId);
To read Measurements from the database the Section 7.2.18, “Lookup Service” has to be used which provides
various Measurement lookup methods, e.g. getMeasurementByMaxDate or getAllMeasurementsByMaxDate.
Note
Only one measurement entry per strategy and name is allowed for a given time stamp. If there
is an existing measurement with matching strategy, name and time stamp then creating a new
measurement with new value will overwrite the previous value.
100
CONFIDENTIAL Option Service
Since some values (e.g. market value) depend on whether the position is long or short, aggregated position
values of different strategies for the same security cannot be retrieved just by adding position values from the
corresponding strategies. Example:
The sum of above market values would be -1'000 which is obviously wrong.
As a consequence the PortfolioDAO provides lookup-methods that aggregate positions from the same
security (of different strategies) in the correct manner (e.g. findOpenPositionsAggregated).
Warning
Positions are derived by taking all Transactions of the given Security and Strategy into account. It
is therefore important not to modify Position entries directly in the database. In case transactions
are added or modified manually to the database, please use the management action reset
position and cash balances in the Figure 11.3, “AlgoTrader UI Settings”
• Back test report and performance statistics display at the end of a simulation run (see Section 5.5,
“Performance Statistics”)
101
CONFIDENTIAL Portfolio Service
All Performance Measurement features depend mainly on the Entity Portfolio Value which has the following
attributes
• dateTime
• netLiqValue
• marketValue
• realizedPL
• unrealizedPL
• cashBalance
• openPositions
• leverage
• cashFlow (optional)
In Live-Trading Mode Portfolio Values are recorded to the database for all running strategies on an hourly basis.
In addition Portfolio Values are recorded every time a transaction occurs that influences performance. For the
AlgoTrader Server these are Credits and Debits and for strategies, these are Rebalances. The corresponding
value of the transaction is recorded in the optional attribute cashFlow of the Portfolio Value.
In Simulation Mode Portfolio Values are recorded to the file PortfolioReport.csv through the
PortfolioReport class on a daily-basis using the AlgoTrader Reporting Functionality, see: Chapter 31,
Reporting.
In case a transaction that influences performance needs to be recorded for a prior period in time, all Portfolio
Values since that time period are invalid and need to be restored.
Note
The Portfolio Value restoration can take a considerable amount of time to complete.
102
CONFIDENTIAL Position Service
• resetPositions calculates all Position based on Transactions in the database and makes adjustments if
necessary.
Note
Closing and Reducing a position through the PositionService requires the definition of an
order_preference with the name DEFAULT. Fur further details see Section 17.2.1, “Order
Preferences”
The default order preference also includes an account, which means this feature is typically
only usable with one account/adapter. If more than one account is in use, positions should be
closes through the Section 7.2.11, “Order Service” by sending an order with a quantity that will
offset the current position.
• Account
• Exchange
• Order
• OrderPreference
• Position
• Security
• SecurityFamily
• Strategy
• Subscription
103
CONFIDENTIAL Reference Data Service
• Transaction
These classes are derived from the abstract class PropertyHolder. One or more Properties can be assigned
to them. A Property can be any Java type (including Integer, Double, BigDecimal, String, Date, Boolean,
etc.) but also arbitrary Java objects as long as the type implements Serializable
The above example will add a Property named myPropertyName and value = 12.12345 to Strategy with id = 12.
104
CONFIDENTIAL Market Data Cache Service
Note
Accepting quote / placing order is possible with Order Service similarly like in Chapter 17,
Order Management. Use PreviouslyIndicatedOrderVOBuilder and method setQuoteId to
link the order to the received quote.
To access the last traded price of an instrument one can use the following code inside strategies:
To access the access the current exchange rate between USD and EUR one can use the following code inside
strategies:
In addition to standard lookup methods above the LookupService also provides the following the generic
lookup methods find and findUnique that can be used in situations where a standard lookup method is not
available. These methods can be used as follows:
105
CONFIDENTIAL
Strategy Service & Config Aware Strategy Service
2
Please consult the JavaDoc for a full list of available methods.
In order to minimize the number of hits to the database the LookupService uses various levels of caching
when reading from the database.
Note
The adapterType specifies the adapter to use when subscribing for market data (e.g.
IB_NATIVE specifies the InteractiveBrokers native API adapter)
2
http://doc.algotrader.com/javadoc/ch/algotrader/service/LookupService.html
106
CONFIDENTIAL Reset Service
Note
Upon subscription, market data will be fed to the trading strategy that initiated the market data subscription.
Market data will be fed to the corresponding Section 4.3.1.2, “Event Handler Methods” (e.g. onBar, onTick,
onOrderBook) and also into the Esper Engine (if using Esper) where they are available as Bar and Tick events.
The SubscriptionService also supports the subscription for GenericEvents, see Section 18.6, “Generic
Events”
The ResetService can be used to reset the state of the database to a pre-defined state either before a
simulation or if a reset of live trading is required.
To reset a live trading system multiple types of resets can be specified to the reset method using the
Enumeration ResetType
TRADES
deletes all transactions (except the initial CREDIT)
resets all cash balances (except the one associated with the initial CREDIT)
ORDERS
delete all orders, order stats as well as order properties
107
CONFIDENTIAL Value Object
SUBSCRIPTION
deletes all subscriptions
COMBINATIONS_AND_COMPONENTS
deletes combinations and components
MEASUREMENTS
deletes measurements
PORTFOLIO_VALUES
deletes portfolio values
OPTIONS
deletes all options
FUTURES
deletes all futures
MARKET_DATA
deletes all bar and tick data
The method resetSimulation will reset the following items before each Simulation: Trades, Subscriptions,
Combinations/Components, Properties, Options (if option prices are simulated) and Futures (if future prices
are simulated).
Each Entity contains an inner Converter class that can be used to convert the Entity to its corresponding Value
Object.
In addition to Value Objects ValueObjectBuilders exist which help creating Value Objects. Example:
3
For a full list of all Value Objects please visit our JavaDoc
3
http://doc.algotrader.com/javadoc/ch/algotrader/vo/package-frame.html
108
CONFIDENTIAL Enumerations
7.4. Enumerations
For selectable items with a fixed number of choices AlgoTrader contains Java 5 Enumerations. For a full list
4
of all Enumerations please visit our JavaDoc
4
http://doc.algotrader.com/javadoc/ch/algotrader/enumeration/package-frame.html
109
Chapter 8. CONFIDENTIAL
Esper Engine
1
AlgoTrader uses the CEP (Complex Event Processing) engine Esper . AlgoTrader based strategies can
optionally make use of a dedicated Esper engine in addition to the Esper engine used by the AlgoTrader server.
A tailored Event Processing Language (EPL) allows expressing rich event conditions, correlation, possibly
spanning time windows, thus minimizing the development effort required to set up a system that can react to
complex situations.
Esper is a lightweight kernel written in Java which is fully embeddable into any Java process. It enables rapid
development of applications that process large volumes of incoming messages or events.
While discrete events when looked one by one might be meaningless, event streams (i.e. an infinite set of
events) considered over a sliding window and further correlated, are highly meaningful, and reacting to them
with the minimal latency is critical for effective action and competitive advantage.
Relational databases or message-based systems such as JMS make it really hard to deal with temporal data
and real-time queries. Indeed, databases require explicit querying to return meaningful data and are not suited
to push data as it changes. JMS systems are stateless and require the developer to implement the temporal
and aggregation logic himself. By contrast, the Esper engine provides a higher abstraction and intelligence
and can be thought of as a database turned upside-down: instead of storing the data and running queries
against stored data, Esper allows applications to store queries and run the data through. Response from the
Esper engine is real-time when conditions occur that match user defined queries. The execution model is thus
continuous rather than only when a query is submitted.
In Esper, a tailored EPL allows registering queries in the engine. A listener class, which is basically a POJO,
will then be called by the engine when the EPL condition is matched as events flow in. The EPL enables to
1
http://www.espertech.com/esper/
2
Most of this section has been reproduced from the Esper website
110
CONFIDENTIAL Event representations
express complex matching conditions that include temporal windows, joining of different event streams, as
well as filtering, aggregation, and sorting. Esper statements can also be combined together with "followed by"
conditions thus deriving complex events from more simple events. Events can be represented as JavaBean
classes, legacy Java classes, XML document or java.util.Map, which promotes reuse of existing systems
acting as messages publishers.
A trivial yet meaningful example is as follow: assume a trader wants to buy Google stock as soon as the price
goes below some floor value, not when looking at each tick but when the computation is done over a sliding
time window, say of 30 seconds. Given a TickVO event bean with a last price field and a reference to a Security
ID and the following EPL, a listener POJO would get notified as ticks come in to trigger the buy order:
select
avg(last)
from
TickVO.win:time(30 sec)
where
securityId=12
In addition to Java classes, Maps and XML are an alternative way of representing events.
EPL is similar to SQL in it's use of the select clause and the where clause. However EPL statements instead
of tables use event streams and a concept called views. Similar to tables in an SQL statement, views define
the data available for querying and filtering. Views can represent windows over a stream of events. Views can
also sort events, derive statistics from event properties, group events or handle unique event property values.
This is a sample EPL statement that computes the average of the last price for the last 30 seconds of Tick
events:
select
avg(last)
from
TickVO.win:time(30 sec)
111
CONFIDENTIAL
Combining Pattern Matching with Event Stream Analysis
A sample EPL that returns the average of the last price per symbol for the last 100 Ticks.
select
securityId
avg(last) as averagePrice
from
TickVO.win:length(100)
group by
securityId
This example joins 2 event streams. The first event stream consists of Bar events for which we keep the last
30 minutes (1800 seconds). The second stream is Tick events for which we consider the last 30 seconds. The
streams are joined on securityId.
select
bar.securityId as securityId,
max(bar.high) as maxHigh,
min(bar.low) as minLow,
last(tick.last) as lastPrice
from
BarVO.win:time(30 min) as bar,
TickVO.win:time(30 sec) as tick
where
bar.securityId = tick.securityId
Patterns match when a sequence (or absence) of events is detected. Pattern match results are available for
further analysis and processing.
The pattern below detects a situation where an OrderStatus event is not followed by another OrderStatus
event corresponding to the same internal order id within 10 seconds. The statement further counts all such
occurrences grouped per internal order id.
select
a.intId,
count(*)
from
pattern [every a=OrderStatus
-> (timer:interval(10 sec) and not OrderStatus(intId=a.intId)]
group by
id
112
CONFIDENTIAL Named windows
create window
SecurityWindow
as
(symbol String, triggerPrice double)
One can trigger a select, update or delete when an event arrives. Here we show a select that simply counts
the number of rows:
on
TriggerEvent
select
count(*)
from
SecurityWindow
8.1.6. Variables
A variable is a scalar, object or event value that is available for use in all statements including patterns. Variables
can be used in an expression anywhere in EPL.
AlgoTrader provides a number of Value Objects that can be used as Esper Events (e.g. TickVO, BarVO,
OrderStatusVO, etc.)
3
Most of this section has been reproduced from the Esper website.
113
CONFIDENTIAL Creating a Statement
A statement is a continuous query registered with an Esper engine instance that provides
results to listeners as new data arrives, in real-time, or on demand via the iterator API ( see
ch.algotrader.esper.Engine.executeQuery ).
The next code snippet shows an Esper module containing a continuous query. The query returns the average
price over all TickVO events that arrived in the last 30 seconds:
select
avg(price) as avgPrice
from
TickVO.win:time(30 sec)
Each of the Esper engines inside AlgoTrader can contain several modules. Modules specified through the
initModules and runModules attribute of the Esper Engine Spring Bean Definition are loaded automatically
on start-up.
Note
A module definition of market-data will look for a module file called module-market-data.epl.
A subscriber object is a direct binding of query results to a Java object. The object, a POJO, receives statement
results via method invocation. The subscriber class does not need to implement an interface or extend a
superclass. Only one subscriber object may be set for a statement.
Subscriber objects have several advantages over listeners. First, they offer a substantial performance benefit:
Query results are delivered directly to the Java method(s) through Java virtual machine method calls, and there
is no intermediate representation (EventBean). Second, as subscribers receive strongly-typed parameters, the
subscriber code tends to be simpler.
114
CONFIDENTIAL Adding a Listener
The subscriber class must provide a public method to receive events. The number and types of parameters
declared by the update method must match the number and types of columns as specified in the select clause,
in the same order as in the select clause.
@Subscriber(className='ch.algotrader.listener.MySubscriber#process')
select
orderId, price, count(*)
from
OrderEvent;
Listeners are invoked by the engine in response to one or more events that change a statement's result set.
Listeners implement the UpdateListener interface and act on EventBean instances as the next code snippet
outlines:
By attaching the listener to the statement via the following annotation the engine provides the statement's
results to the listener:
@Listeners(classNames={'ch.algotrader.listener.MyListener'})
select
avg(price) as avgPrice
from
TickVO.win:time(30 sec)
115
CONFIDENTIAL Sending events
Incoming market data events (e.g. Ticks), submitted Orders, OrderStatus events, received Fills, etc are
automatically sent into the corresponding Esper engines.
Additionally custom events can be sent into an Esper engine. The following code snipped creates an arbitrary
event and sends it into the Esper engine instead an AlgoTrader strategy named EXAMPLE.
engine.sendEvent(event);
8.2.6. Configuration
Esper Configuration helps make statements more readable and provides the opportunity to plug-in extensions.
Each Esper Engine loads the default esper-common.cfg.xml file. In addition strategies load all Esper
configuration files named esper-xxx.cfg.xml in the class path. This configuration file defines settings like:
• Event Types
• Variables
The following chapters of the Esper Documentation are relevant for developing trading strategies with
AlgoTrader based on Esper:
5
• 2. Event Representations
6
• 3. Processing Model
7
• 5. EPL Reference: Clauses
4
http://esper.espertech.com/release-7.0.0/esper-reference/html/index.html
5
http://esper.espertech.com/release-7.0.0/esper-reference/html/event_representation.html
6
http://esper.espertech.com/release-7.0.0/esper-reference/html/processingmodel.html
7
http://esper.espertech.com/release-7.0.0/esper-reference/html/epl_clauses.html
116
CONFIDENTIAL AlgoTrader specific Esper Artifacts
8
• 6. EPL Reference: Patterns
9
• 8. EPL Reference: Operators
10
• 9. EPL Reference: Functions
11
• 12. EPL Reference: Views
12
In addition Esper Examples, Tutorials, Case Studies are available.
8.4.1.1. Engine
The Engine interface has methods available for the following tasks:
• sending events
• synchronized processing (coordination) of events from different sources into the Esper engine
For testing purposes there is an abstract do-nothing implementation of the Engine interface available named
AbstractEngine.
8.4.1.2. EngineManager
The EngineManager interface represents the main entry point to different Engines running inside the JVM. The
EngineManager has methods available for the following tasks:
8
http://esper.espertech.com/release-7.0.0/esper-reference/html/event_patterns.html
9
http://esper.espertech.com/release-7.0.0/esper-reference/html/epl-operator.html
10
http://esper.espertech.com/release-7.0.0/esper-reference/html/functionreference.html
11
http://esper.espertech.com/release-7.0.0/esper-reference/html/epl-views.html
12
http://esper.espertech.com/release-7.0.0/esper-reference/html/examples.html
117
CONFIDENTIAL Modules
Note
Engine instances are managed and configured through Spring configuration. Engines are
standard Spring managed beans that get automatically registered with EngineManager upon
startup.
8.4.2. Modules
Tag Description
module-algo-xxx.epl Each Execution Algo has its own module
module-combination.epl Combination / Component related functionality (see Chapter 25,
Synthetic Securities and Derivative Spreads)
module-current-values.epl Store current market data values
module-ib.epl IB specific statements
module-market-data.epl Statements related to market data
module-metrics.epl Statements needed for Engine Metrics
module-performance.epl Evaluation of performance metrics
module-portfolio.epl Portfolio management functions
module-prepared.epl Prepared Statements available to strategies
module-server-prepared.epl Server-Side prepared Statements
module-trades.epl Statements related to orders and executions
Note
init and run modules of the AlgoTrader Server can be defined through config properties in
conf-core.properties.
118
CONFIDENTIAL Tags
• Creation of technical indicators (e.g. Moving Average, Bollinger Bands, ATR, etc.)
• Trend evaluation
• Pattern recognition
Note
It is generally recommended to use Esper statements for anything up to signal generation but
then use Java for execution of actions (e.g. send and order, set a stop or close a position)
8.4.3. Tags
13
In addition to the Esper standard tags the following tags are available:
Tag Description
@Condition(key='xxx') Statement is only deployed if defined configuration parameter is set
to "true"
@SimulationOnly Statement is only deployed in simulation
@RunTimeOnly() Statement is only deployed in Live-Trading mode
@Listeners(classNames={'...'}) attaches one or multiple listeners to the statement
@Subscriber(className='...') attaches a subscriber to the statement
8.4.4. Subscribers
The system provides the following Subscribers out-of-the-box:
IndicatorSubscriber
Prints all values as a comma-separated-list (CSV) to the file files/report/IndicatorReport.csv
(Headers are not available).
13
http://esper.espertech.com/release-7.0.0/esper-reference/html/epl_clauses.html#epl-syntax-annotation
119
CONFIDENTIAL Listeners
TestSubscriber
Prints all values to the Log by using the toString method of the event object.
VoidSubscriber
Do-nothing subscriber, useful when select clauses call static methods
ExceptionSubscriber
Prints a value as an Error to the Log.
Any public method of a component defined in the Spring application context can potentially be used as a
subscriber provided the parameter signature of the method can be supported by Esper: One can define a
subscriber by specifying a Spring bean name followed by hash (#) followed by a method name exposed by
this bean.
@Name('TAKE_PROFIT')
@Subscriber(className='boxService#takeProfit')
The syntax also supports property placeholder expansion. This can especially useful when using multiple
instances of the same strategy in the same JVM process.
@Name('TAKE_PROFIT')
@Subscriber(className='${strategyName}Service#takeProfit')
8.4.5. Listeners
The system provides the following Listeners out-of-the-box:
IndicatorListener
Prints all values as a comma-separated-list (CSV) to the file files/report/IndicatorReport.csv.
Headers will be extracted from the supplied Statement.
RendererListener:
Prints all values to the Log in XML format.
TestListener
Prints all values to the Log by using the toString method of the event object.
StatementAwareTestListener
Prints all values including the statement name to the Log by using the toString method of the event object.
By default AlgoTrader exposes the following services to Esper statements, which strategies can make use of:
120
CONFIDENTIAL Aggregation Functions
• LookupService
• PortfolioService
• CalendarService
• OrderService
• PositionService
• MarketDataService
• OptionService
Here are some examples. To retrieve a security based on its securityId one can use the following statement:
select
bar,
security
from
BarVO as bar unidirectional,
method:lookupService.getSecurity(bar.securityId) as security;
To retrieve an open order by its intId on can use the following statement:
select
fill,
openOrder
from
FillVO as fill unidirectional,
method:orderService.getOrderByIntId(fill.orderIntId) as openOrder;
8.4.7.1. ExponentialMovingAverage
121
CONFIDENTIAL Aggregation Functions
This will create a 10-period exponential moving average of the Tick last price.
8.4.7.2. GenericTALibFunction
14
The GenericTALibFunction is a port of ta-lib to AlgoTrader. It supports all TA-Lib operations.
15
Please consult TA-Lib for a list of all TA-Lib methods and their parameters.
If the TA-Lib Function returns just one value, the value is directly exposed by the AggregationFunction.
Example: The TA-Lib function movingAverage has just one double typed return value which can be accessed
directly.
select result
from MovingAverage;
If the TA-Lib Function returns multiple-values, a dynamic class will be generated on the fly, which gives access
to properly typed return-values. All return value names are lower-case!
Example: The TA-Lib function stochF has return values: outFastK and outFastD. The returned dynamic class
will have double typed properties by the name of: fastk and fastd (all lowercase).
Some functions are influenced by the entire range of the past data. These functions are sometimes called
functions with memory. An example is the EMA (Exponential Moving Average). For these functions an optional
unstable period parameter can be specified. The following statement will create a 30 period moving average
with an unstable period of 10.
14
http://ta-lib.org/
15
http://doc.algotrader.com/ta-lib.html
122
CONFIDENTIAL Callbacks
16
For further details about the unstable period please see: SetUnstablePeriod
17
For additional information please visit the corresponding JavaDoc .
Note
As an alternative to the ta-lib based exponential moving average function the Esper aggregation
function Section 8.4.7.1, “ExponentialMovingAverage” can be used which keeps the entire
history and not just the unstable period.
8.4.8. Callbacks
In order to correctly associate the trade callback with a specific order an orderId has to be retrieved from the
order service and set onto the order before attaching the trade callback.
16
https://ta-lib.org/d_api/ta_setunstableperiod.html
17
http://doc.algotrader.com/javadoc/ch/algotrader/esper/aggregation/GenericTALibFunction.html
123
CONFIDENTIAL Callbacks
order.setIntId(orderId);
getOrderService().sendOrders(orders);
The Engine#addFullExecutionCallback() method can be used to register a callback logging an error if the
order did not execute fully.
order.setIntId(orderId);
engine.addFullExecutionCallback(Collections.singleton(orderId));
getOrderService().sendOrders(orders);
Note
With Fix based Broker / Exchange connections the TradeCallback only works with the initial
order but not with any subsequent order modifications.
This callback is particularly useful for situations where one needs to have a guarantee that all order related
database transactions have been fully executed before continuing with next steps, e.g. to retrieve the current
position quantity after an order has been executed. If using a regular trade callback for this, the Position Entity
might not have been fully persisted by the time the consumer is executed. However when using the trade
persisted callback it is guaranteed that the Position Entity has been fully updated in the database.
In order to correctly associate the trade callback with a specific order an orderId has to be retrieved from the
order service and set onto the order before attaching the trade callback.
124
CONFIDENTIAL Callbacks
order.setIntId(orderId);
getOrderService().sendOrders(orders);
Note
The Trade persisted callback is only supported in runtime mode but it is not supported in
simulation mode. It is recommended to use the Section 8.4.8.2, “Trade callback” instead in
simulation mode. The Trade persisted callback will only get executed if there has been at least
one (partial) execution but not if an order has been cancelled or rejected before there has been
any execution.
Note
It is guaranteed that the position is fully persistent to the database by the time the consumer
is called.
125
CONFIDENTIAL Esper Threading
In Live-Trading Mode AlgoTrader uses outbound threading with 3 threads by default. This means that all
Subscriber / Listener Tasks are handled by a thread-pool of 3 threads. The number of outbound threads can
be changed inside conf.properties or via Section 2.4, “VM Options”:
# number of Esper outbound threads to be used in Live Trading Mode for the Server
Engine
misc.outboundServerEngineThreads = 3
# number of Esper outbound threads to be used in Live Trading Mode for the Strategy
Engines
misc.outboundStrategyEngineThreads = 3
For debugging reasons AlgoTrader logs the name of the thread using log4j, see Chapter 30, Logging
18
http://esper.espertech.com/release-7.0.0/esper-reference/html/api.html#api-threading
126
Chapter 9. CONFIDENTIAL
Caching
1
AlgoTrader uses an in-memory data-grid solution called Hazelcast . This layer resides between the application
layer (business logic) and persistence. It is responsible for providing easy and fast access to any persistent
data for both read and write operations.
Note
The Hazelcast product family offers various features and software packages. Algotrader relies
on the IMDG product.
2
As a general rule we can assume, that there is at least 1 magnitude difference in speed between reading
from RAM and from disks. Algotrader uses in-memory caching not only to provide clear separation between
persistence and application layer, but to be able to perform high-speed trading without being bound to
disk speed. This approach however requires some changes to what could be considered "standard" way of
implementing persistence in Java applications.
9.1.1. Persistence
The caching layer separates the application layer from the persistence logic. The application layer does not
directly access DAO methods anymore and is required to go through CacheFacade classes to access data.
3
These CacheFacade classes internally rely on Hazelcast IMaps . IMaps have similar characteristics to the
standard Java Map interface. The biggest difference being the possibility to attach MapStores to these maps,
giving them the ability to use persistent storage.
It is important to remember that objects in the Algotrader application layer are no longer attached to any
Hibernate session. They get detached on read and merged back to the persistence context upon save. This
also means that any mutation on these object have to be explicitly saved or otherwise the change will not be
persisted. Objects served out of caches are - by default - not shared and will be created by deserialization
whenever requested.
9.1.1.2. ID assignment
In a traditional environment objects belonging to the relational database often get an ID assigned to them by
the database itself via auto-generated fields or sequences. In Algotrader's case this is no longer true, since
we assign these IDs prior to put them into caches. For this purpose we use the AutoIncrementIdGenerator
1
https://hazelcast.org/imdg/features/
2
https://colin-scott.github.io/personal_website/research/interactive_latency.html
3
https://docs.hazelcast.org/docs/3.8/javadoc/com/hazelcast/core/IMap.html
127
CONFIDENTIAL Cache access
class. This solution allows us to generated IDs prior to saving objects. Please note that this ID pool is shared.
This means that after having persisted a set of objects in one table (order for example), the next ID assigned
for another table (transaction) will be consecutive from the one last seen on the previous table. It is not
advised to assign IDs yourself.
In order to drastically increase the throughput of the system (both live and simulation), Algotrader halts the
application logic only the smallest amount of time possible to save its current state. Most trading applications
would suffer the largest part of their latency due to having to save their internal state (be that, orders, positions,
transactions) to a storage before they can continue on further operations. Using Hazelcast caches Algotrader
only stops for the time needed to save changes in memory, but will delegate the task of long-term storage to
other threads, thus unblocking the main application threads. This async write behavior (often referred to as
write-behind) is configurable per cache/table in Algotrader. For details see the configuration section.
Due to the async nature of the persistence layer, database constraints cannot be utilized the same way as
for synchronous DB operations. The simplest example to highlight the problem is the relation between orders
and transactions. A freshly created order might results in a new transaction after having received a fill. Saving
this transaction however can be problematic now since there is no guarantee that the original order has been
saved already since both of them being saved write-behind. To overcome this problem Algotrader does not
rely on database level constraints. To provide the same level of correctness checking, we have a constraint
checking system in place. This is enabled by default, but can be switched off in case in a certain situation (like
backtesting) the potential corruption of the database state is not considered to be a real risk.
In certain situations (backtesting/unit testing) truly persistent DB operations might not be needed as the data
would be discarded anyway. In this case it is possible to omit the pooledDataSource profile from any Algotrader
starter configuration. This will result in Algotrader starting up without any backing store, where data will only
be kept in memory. Be careful: the application will have lose its working memory on restarts and there is no
way to access that storage later.
Hazelcast my default makes many of its internal metrics available via JMX. These can be accessed by standard
tools, like JVisualVM (shipped with most Java distributions) or libraries like Jolokia. They allow to query the
internal state of caches and get relevant insights regarding current load, frequent and/or slow cache operations,
etc.
Algotrader also exposes a set of cache operations that can be useful for debugging/operational purposes.
These services are available locally under the following URL: http://localhost:9090/rest/cache/ on the machine
Algotrader is running. Using these endpoints users can query in JSON format (get/getAll), toString format (print/
128
CONFIDENTIAL Configuration
printAll) any caches that currently exists. There are also a number of non-readonly operations available, such
as evict/delete/refresh etc. These perform the corresponding operation on the cache itself, and should be used
with care. They are intended to be used during development phase, and primarily not in production.
Certain caches can grow indefinitely in size and keeping all items in-memory is not practical. For this case
Algotrader has a configurable eviction logic that comes with defaults but can be fine-tuned for individual cases.
Users might choose to use this facility in case they have a large number of orders / transactions created for
example.
During startup it is equally good idea to limit the number of entries that get preloaded into memory. It is not an
issue for small caches (like strategy, account, etc) but makes sense not to load very old transaction or orders
back into memory. These characteristics of each cache can be configured independently (see next section).
By default the caches store their content in a serialized format, using the highly efficient Kryo serialization
package. This reduced their memory footprint drastically, however it has a significant drawback. In case the
caches are often queried, this configuration requires the JVM to frequently deserialize its content. So in certain
cases it makes more sense to not make use of the serialization at all and store objects in their original format.
For small (and mostly static caches) this is the most efficient setup.
9.1.3. Configuration
9.1.3.1. Defaults
Algotrader comes with a set of generic cache-related configs and some others that are specific to individual
caches.
129
CONFIDENTIAL Configuration
Algotrader comes with a set of generic cache-related configs (see above) and some others that are specific
to individual caches. These can be individually overriden in case some special condition would require that.
In that case individual caches names can be substituted into the default param names (see above), in the
following format: hz.maps.POSITION_MAP.writeDelaySeconds=0. This line for example would make position
changes persisted immediately in a synchronous manner.
Warning
130
Chapter 10. CONFIDENTIAL
Database
10.1. Instances
1
AlgoTrader uses MySQL to store transaction data.
10.2. Flyway
2
AlgoTrader uses the database migration library flyway to keep databases in-line with the current version
of AlgoTrader. Flyway executes database migration scripts to ensure that the database is in the state
corresponding to the version of AlgoTrader installed.
Flyway is embedded into the AlgoTrader platform, and can perform a migration of the Database on each startup
automatically. In case the configured schema does not exist on MySQL, it will create it. This schemas default-
name is algotrader. The feature is activated on all startup-scripts including docker but deactivated in the
development environment. misc.flywayMigrateOnStartup is the property to control this behaviour, it can be
passed as a VM Argument.
-Dmisc.flywayMigrateOnStartup=true
In case you need to reset the Database, the easiest way is to delete the corresponding schema
on MySQL and start AlgoTrader. For further migration related issues, a class within AlgoTrader
ch.algotrader.starter.FlywayRunner can be used to execute other flyway commands. It is not
recommended to use Flyways command-line-tool instead, because of potential problems when using several
flyway versions on the same schema.
3
For additional information on flyway please visit the flyway documentation .
10.3. Files
The directory /bootstrap/conf contains all relevant database files:
• flyway/sql contains the flyway migration scripts that will be executed to initialize and update the MySQL
database
1
https://www.mysql.com/
2
https://flywaydb.org/
3
https://flywaydb.org/documentation/maven/
131
CONFIDENTIAL Data Source
-Dspring.profiles.active=<dataSource>
4
• pooledDataSource: A Data Source that uses connection pooling based on C3P0
• singleDataSource: A Data Source that uses one single database connection and no connection pooling.
• hybridDataSource: A Data Source prepared for backtesting purposes, it keeps only reference data in
physical DB (Components, Strategies, Exchanges, TradingHours, Holidays, Securities, SecurityFamilies,
Accounts, OrderPreferences, SecurityReferences) Other, transactional data (Transactions, CashBalances,
Positions, Orders, OrderStatuses, Subscriptions, PortfolioValues, Measurements, Quotes, QuoteRequests)
are kept only in the cache and are erased after restart.
4
https://www.mchange.com/projects/c3p0/
132
Chapter 11. CONFIDENTIAL
Client
AlgoTrader provides different types of clients all of which are targeting a different audience and use case:
• The html5 UI: used to monitor/manage trading activities while AlgoTrader is running
• IntelliJ IDEA: Contains the Strategy Creation Wizard, the Config Editor as well as the strategy simulation
environment
11.1. HTML5 UI
Note
Officially AlgoTrader only supports Google Chrome. However, the AlgoTrader UI will most likely
work with the most recent version of any modern browser.
• All tables provide (multicolumn) sorting, filtering, column selection and reordering, and scrolling.
• Since the UI is based on HTML5, it can easily be integrated into corporate IT infrastructures using firewalls,
VPNs, and remote locations.
To manually open the client, point the browser to one of the following URL.
http://localhost:9090
133
CONFIDENTIAL Header and toolbar
Using the strategy selection menu located at the top of the screen (to the right), one can select either an
aggregated view over the entire system or a strategy specific view.
When a single strategy is selected the client will show orders, transactions, positions and market data
subscriptions related to the selected strategy only. When ALL is selected the client will show orders,
transactions, positions and market data subscriptions for all strategies.
134
CONFIDENTIAL Header and toolbar
The header tiles show general figures (like Net Liquidity, Unrealized P&L, Cash, etc.). The default
valuation currency is USD. You can change it by updating the misc.portfolioBaseCurrency value in the
conf.properties file.
If one opens a settings menu form on bottom left corner one can see the following settings are available there:
2. Order defaults - default order related values like default quantity and default time-in-force
3. Data throttling - Sets the update interval of all tables, e.g. if the interval is 333ms, the tables will buffer all
data updates and only make display changes every 333ms.
5. Source of chart's data - Preferably the source of chart's data is AT's own historical data source, if that's not
present then TradingView's delayed data can be used.
9. Reset Position and Cash Balance - Resets all Cash Balances and Position quantities based on Transactions
in the database and makes adjustments if necessary.
10.Restore default settings - clicking it will remove any custom UI settings saved in browser's storage. This
includes visible columns, columns order and all settings described above.
135
CONFIDENTIAL Header and toolbar
Notifications are displayed in the lower right hand side of the screen
136
CONFIDENTIAL Order Table
There are three types of notifications: information-s (green), warnings (orange) and alerts (red). In addition to
warnings and alerts appearing in bottom right corner, a bell icon will appear at the top left of the screen.
To open the list of all warnings and alerts click on the bell icon.
The orders will appear in the Order Table in real time. Executed orders are removed from the table after a
preset number of seconds which can be configured through the Settings Dialog.
137
CONFIDENTIAL Order Table
Manual orders can be entered using the order entry form. After entering the order (by specifying security, trade
side, order type, quantity, strategy, account and trade type), click the Submit button.
To cancel all open orders, click the Cancel All button at the top right of the Order Table.
To cancel a specific open order, click the Cancel icon besides the order.
To modify an open order, click the Modify icon besides the order.
To specify additional order parameters (e.g. time in force and exchange) or place advanced order types (like
Algo Orders) click the Advanced Form button.
138
CONFIDENTIAL Advanced Order Form
This form lets one enter all types of supported orders, including Algo Orders and allows to use Smart Order
Routing feature.
The first field at top left corner, Order Type, lists all available order types. When Order Type is a simple
order type (i.e. Market, Limit, Stop, Stop Limit), then the form allows to specify Time in Force (TIF) and broker/
exchange specific parameters, in addition to the Simple Order Form.
For Algo Orders Smart Order Routing is available as well as additional details specific to that type of an Algo
Order.
There's also a possibility to use one of pre-defined Order Preferences to fill out the form, they're listed in the
header of Algo Orders properties section. For further details see Section 17.2.1, “Order Preferences”
139
CONFIDENTIAL Advanced Order Form
Figure 11.10. AlgoTrader UI Advanced Order Form - Routing section, Smart Routing
switched off
For Algo Orders you can switch Smart Routing on and off. With Smart Routing switched off you should specify
Security, Account and Exchange to be used.
Figure 11.11. AlgoTrader UI Advanced Order Form - Routing section, Smart Routing
switched on
With Smart Routing switched on you can lookup securities with the same symbol and pick the ones that you
want Algotrader to pick from.
140
CONFIDENTIAL Advanced Order Form
Figure 11.12. AlgoTrader UI Advanced Order Form - Routing section, Smart Routing
disabled
For Simple Orders (Market, Limit, Stop) Smart Routing switch is disabled. In order to use Smart Routing with
simple order types you should pick order type ending with "Smart Routing"
Figure 11.13. AlgoTrader UI Advanced Order Form - Routing section, Smart Routing
equivalent of Simple Order Type
141
CONFIDENTIAL Algo Order details UI
For details about Smart Order Routing see Section 17.4, “Smart Order Routing”
Figure 11.14. Execution Algo details icon visible in action column in the Orders table
Figure 11.15. Execution Algo details modal window with a grid listing all children of
a given Execution Algo
11.1.5. RFQ UI
Algotrader allows you to place Requests For Quotes via the user interface. If one of the configured accounts
supports RFQs, the UI will display the RFQ button.
If you press the RFQ button, you can submit a price inquiry.
142
CONFIDENTIAL RFQ UI
In the first step, complete the inquiry form. You must complete all fields on the form. Select the instrument and
the accounts to which you want to send an RFQ (you must select at least one account). Then complete the
rest of the fields (Strategy, Side, Quantity and TIF).
Note
Most market makers that support RFQ only allow TIF FOK (fill or kill).
The Submit button sends an RFQ to the selected accounts and takes you to the RFQ execution view.
143
CONFIDENTIAL RFQ UI
On the RFQ Execution form, you'll see offers with their statuses and the time remaining to accept the offer.
If you click an Accept button at the right of a row, an order to execute that quote will be sent out. You can
redeem more than one offer.
144
CONFIDENTIAL Transaction Table
Once the time expires, you can re-issue the RFQ by clicking the Retry button. The request will be sent only
for the selected Market Maker.
The executed trades are listed in the Transactions Table. Since strategies can produce a lot of transactions, only
the most recent 50 are shown on startup. All transactions can of course be seen/exported from the database.
To manually add a transaction, click the + button at the top right of the Transaction Table.
145
CONFIDENTIAL Positions Table
If a transaction's fee currency is different from the quote currency (e.g. for certain crypto-exchanges), the
transaction window will show additional rows to reflect the fees.
Where transaction and fee currencies are the same, the transaction fee will be visible in the fee column of
the transaction.
146
CONFIDENTIAL Market Data Table
To close all positions, click the Close All button at the top right of the Position Table.
Note
Closing all positions through the UI requires the definition of an order_preference with the
name DEFAULT. Fur further details see Section 17.2.1, “Order Preferences”
The default order preference also includes an account, which means this feature is only usable
with one account/adapter.
To close a specific position, click the Close x icon besides the position.
To increase a position by a certain quantity, click the Add + icon besides the position.
To reduce a position by a certain quantity, click the Reduce - icon besides the position.
All of these three actions will pre-fill the order form with appropriate data (security, side, amount in case of
close action) and move focus to the form. To send the order please validate the account setting is correct and
click Submit.
To open a position's security chart, click the Chart icon besides the position.
147
CONFIDENTIAL Column Selection and Grouping
To subscribe for a security's market data, click the + button at the top right of the Market Data Table.
To unsubscribe to a security's market data, click the Unsubscribe icon besides the security.
For any given strategy, it is only possible to unsubscribe from securities the strategy has no position. The
unsubscribe icon will only be enabled if the corresponding strategy has no position for the given security.
The security's chart can be opened by clicking the Chart icon besides the security.
All Tables have a configuration button at the top right of the table. Click the Table Settings option in table's
dropdown menu on top right corner to select which columns to show. See the following example for the
Transaction Table.
To see all columns of a certain type (e.g. Transaction or Strategy) please click on the expand button.
148
CONFIDENTIAL CSV Export
In every table, any column can be sorted (ascending or descending) by clicking on the column header.
A filter can be applied to any column by clicking at the far right part of the column header. The following image
shows the transaction table filtered by a specific symbol.
TradingView has regular and advanced chart types and it comes with a massive library of over 100 pre-built
technical indicators covering the most popular trading concepts.
149
CONFIDENTIAL Chart Widget
The chart widget is useful during strategy development (for initial idea generation, validation, etc.) and for
monitoring.
Note
TradingView widget can work in two modes. It can either use data provided by TradingView
itself, or it can use custom market data adapters which are configured in AlgoTrader.
In case of TradingView market data source there might be slight differences between market
data shown in the market data table and the chart widget.
1
Please, see the TradingView documentation .
To switch market data source between TradingView and custom ones, open settings panel.
1
https://www.tradingview.com/wiki/Main_Page
150
CONFIDENTIAL Chart Widget
Another feature you get while using your custom historical data source is that AlgoTrader will display your
orders and executions on the chart as well. The longer arrows are your orders (aggregated by status) and the
shorter are the executions.
151
CONFIDENTIAL Chart Widget
If you hover over an order arrow, you will see the current status and details of the orders placed in that bar:
If you hover over an execution arrow, you will see the summary of executions that took place in that bar:
152
CONFIDENTIAL Chart Widget
To select particular security to be displayed in the chart, click on the chart icon in the operations column in
Market Data or Positions grids.
153
CONFIDENTIAL Chart Widget
154
CONFIDENTIAL Technologies
After you switch to the order book tab, you can toggle to the aggregated order book view
11.1.12. Technologies
155
CONFIDENTIAL HTML5 Custom Widgets
• HTML5
2
• React
3 4
• STOMP over WebSockets
5
• Bootstrap
6
• TradingView chart component
7
• AGGrid component
It is possible to extend the AlgoTrader UI with custom widgets to visualize strategy specific data or let the
user interact with strategy specific functionality (e.g. modify parameters or state of a strategy). The following
screenshot shows an example of the custom widget in use by the Appendix B, Example Strategy "Box":
2
https://reactjs.org/
3
https://stomp.github.io/
4
http://www.websocket.org/
5
https://getbootstrap.com/
6
https://www.tradingview.com/
7
https://www.ag-grid.com/
156
CONFIDENTIAL HTML5 Custom Widgets
HTML5 custom widgets use WebSockets over STOMP to communicate with the strategy.
To integrate the HTML5 custom widget into the main AlgoTrader UI the following items need to be created
inside the strategy module (in case you are using the EmbeddedStrategyStarter) or inside the algotrader-
core module (in case you are using the ServerStarter). The examples are based on the Appendix B, Example
Strategy "Box".
/src/main/resources/html5/widgets.json
This file is a descriptor for all of widgets used in strategy (it is possible to add multiple widgets for single
module). The descriptor in JSON format should be an Array type which contain declarations for each widget:
157
CONFIDENTIAL HTML5 Custom Widgets
[
{
"id": "BOX_STRATEGY",
"title": "Box Strategy",
"type": "iframe",
"entryPoint": "box.html"
}
]
id
Unique id of the Widget
title
Title that will be presented in UI component palette and component itself
type
Currently only "iframe" is supported (the Widget will be loaded in its dedicated IFRAME)
entryPoint
The URL pointing to the Widget's HTML code (the Widget's code can contain any further imports
needed)
/src/main/resources/html5/box.html
This file should contain the HTML code for the custom widget. Individual tags will be referenced by
JavaScript code through tag ids.
<div class="widget-container">
<h3 style="align-self:center;">Box Strategy</h3>
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>State</td>
<td id="box_state"></td>
</tr>
<tr>
<td>Units</td>
158
CONFIDENTIAL HTML5 Custom Widgets
<td id="box_units"></td>
</tr>
<tr>
<td>Upper Target</td>
<td id="box_upperTarget"></td>
</tr>
<tr>
<td>Upper Buffer</td>
<td id="box_upperBuffer"></td>
</tr>
<tr>
<td>Top</td>
<td id="box_top"></td>
</tr>
<tr>
<td>Bottom</td>
<td id="box_bottom"></td>
</tr>
<tr>
<td>Lower Buffer</td>
<td id="box_lowerBuffer"></td>
</tr>
<tr>
<td>Lower Target</td>
<td id="box_lowerTarget"></td>
</tr>
</tbody>
</table>
<button id="box_terminate" style="align-self:center;" class="btn btn-danger btn-
xs" role="button">TERMINATE TRADE</button>
</div>
/src/main/resources/html5/box.js
This file should contain the JavaScript code for the custom widget:
$.get("/rest/broker/url/ws", function(wsURI) {
// connect to stomp
var ws = new WebSocket(wsURI, "stomp");
var stompClient = Stomp.over(ws);
stompClient.connect({}, function(frame) {
159
CONFIDENTIAL Reference Data Manager
}, { "activemq.retroactive" : true});
/src/main/java/ch/algotrader/strategy/box/BoxService.java
The strategy service class is responsible for sending events to the custom widget and for processing
incoming events from the custom widget.
Strategy service classes can send events to the custom widget by using the JsonTemplate available inside
the strategy service. The following code snippet will send a box event to the topic strategy.box.metrics:
getJsonTemplate().convertAndSend("strategy.box.metrics", box);
Strategy service class methods can be annotated with the JmsListener annotation in order to receive
incoming events from the custom widget. The following code snippet will attache the terminateSeries
method to the topic strategy.box.terminate:
@JmsListener(destination = "strategy.box.terminate")
public void terminateSeries() {
...
}
To see the full source code of above examples please see the corresponding source code of the Appendix B,
Example Strategy "Box". Additional HTML5 custom widgets are available inside the example strategies
Appendix D, Example Strategy "IPO" and Appendix C, Example Strategy "Pairs Trading".
160
CONFIDENTIAL Reference Data Manager
• Account
• Component
• Exchange
• Holiday
• Measurement
• OrderPreference
• Strategy
• SecurityFamily
• SecurityReference
• Security
The Reference Data Manager also allows running the reference data download from the user interface without
having to run ReferenceDataStarter separately.
In order to use RDM you need to start AlgoTrader with html5 Spring profile enabled. You can then access
RDM through the left-side menu of the AlgoTrader client, menu item Reference data.
161
CONFIDENTIAL Reference Data Manager
If you start AlgoTrader with a reference data Spring profile enabled (see Chapter 20, Reference Data), RDM
will allow you to run the reference data download from its interface. After running it, the new securities, security
families, etc. will be immediately available to use with AlgoTrader without a restart. The following image
shows an example where the reference data download was run with AlgoTrader set up with Bitfinex exchange
reference data Spring profile.
162
CONFIDENTIAL Reference Data Manager
It is possible to enable a FIX adapter at run time, by activating the relevant Account table entry via RDM
163
CONFIDENTIAL Historical Data Manager
You can access the HDM through the left-side menu of the AlgoTrader client.
164
CONFIDENTIAL Historical Data Manager
In the following screen shot, the view of 1 minute AMZN stock historical data is selected. The data table can be
ordered by dateTime in ascending or descending order. After selecting an instrument in the tree menu on the
left side of the screen, all instrument's data with the relevant parameters (i.e. adapter type and bar size)
is displayed.
165
CONFIDENTIAL Historical Data Manager
The date and time range of displayed data is visible in the Min. date and Max. date fields at the top of the
screen. The date and time range of displayed data may be changed by editing the two fields and clicking the
Set range button. Note also the Delete all button at the top, it removes all data that is currently visible.
After clicking on a row in the historical data table, a window is opened from where an individual measurement
may be edited or deleted.
166
CONFIDENTIAL Historical Data Manager
Clicking the Add new bar button opens the window for entering a new measurement.
Note
The HDM only displays dates of measurements down to seconds, even if they have smaller than
a second fractions defined in the InfluxDB store. InfluxDB allows storing measurements with
167
CONFIDENTIAL Historical Data Manager
precision down to nanosecond. Adding a new measurement with a date that is exactly same as
an existing measurement (same in nanoseconds), will effectively overwrite the existing one.
The Export into CSV button lets the user export the data currently displayed in the historical data table in
CSV file format. The HDM supports several different CSV file formats.
168
CONFIDENTIAL Historical Data Manager
When selecting Historical Data Import in the tree menu on the left, the following screen is displayed. It
provides a facility to import CSV files in several formats. Imported data is stored in InfluxDB.
Note that importing consists of 2 phases, the file upload phase where the uploaded file is stored in a temporary
file in the operating system where AlgoTrader server runs, and the file processing phase which converts and
stores the data in InfluxDB.
169
CONFIDENTIAL Historical Data Manager
When selecting Historical Data Download in the tree menu on the left, the following screen is displayed.
It provides a facility to download data via the historical data adapter AlgoTrader is currently configured with.
Downloaded data is directly stored in InfluxDB. This functionality is only available in HDM when a historical
data adapter is configured. The functionality is identical to running a Historical Data Starter (see Section 19.3,
“Historical Data Download”). After finishing the historical data download, the last few lines of the AlgoTrader
server log is displayed.
170
CONFIDENTIAL Historical Data Manager
Note
An individual historical data download might take a considerable amount of time depending on
the date range and granularity (e.g. 1 year worth of 1 second bars).
171
Chapter 12. CONFIDENTIAL
Performance Monitoring
AlgoTrader provides a sophisticated performance metrics tracking functionality. The main components are
meters, registries and Grafana.
• Meters are used to monitor certain performance aspects (metrics) of the application.
• Registries are acting as data pipelines that can be used to store/forward the measurements taken by the
meters. Currently Influx, Logging and JMX are the supported solutions.
#Log level for metrics (only matters if the LOGGING registry is enabled)
#{"type":"String","label":"Log level"}
metrics.log.level=Debug
172
CONFIDENTIAL Grafana Configuration
To tweak monitoring behavior, configuration parameters can be set/overriden via program arguments,
see Section 2.4, “VM Options”. To disable metrics set the metrics.filter parameter to empty (i.e.: -
Dmetrics.filter=""), this can be useful if the hardware resources running AlgoTrader are limited, and we want
to minimize memory consumption and maximize performance.
1
• Grafana is installed on the same host as AlgoTrader
• The influxDB spring profile must be enabled, see Section 26.2, “Spring Profiles”
• The INFLUX registry must be enabled, see Section 12.1, “Metrics Configuration”
Please be aware that for specific dashboards to work, that metric has to be enabled on the AlgoTrader side
too, otherwise AlgoTrader would not collect/persist that data and Grafana would have no way of reading it from
Influx. e.g.: If Esper metrics are not enabled on the AlgoTrader side (see Section 12.1, “Metrics Configuration”),
then all he Esper Statements and Engine related dashboards will stop displaying data.
Metrics and dashboards including general CPU, Process, Thread, Memory and JVM monitoring.
1
http://grafana.com
173
CONFIDENTIAL Esper Metrics
Dashboard Panels:
• CPU - Shows the CPU count and and current CPU usage (current system load).
• Threads - Shows the number of threads and their states. Thread usage statistic that shows how well threads
make use of the available resources. High blocked threads may point to locking issues, and similarly a high
number of waiting threads could indicate that the CPU cannot keep up with the load or that there are not
enough cores to split the work in an efficient manner.
• GC Pause - Shows when and for what reason garbage collection pauses happen and how long they last
(in nanoseconds).
• GC - Displays general garbage collector tracked memory usage. Could indicate the reason why garbage
collection happens.
• JVM Memory - Monitors the java virtual machines memory management in terms of memory type (heap, non-
heap) and area/generation. This can be used to detect memory leaks, programming inefficiencies, e.g.: a 10x
"heap|PS Eden Space" type memory allocation compared to "heap|PS Old Gen" could indicate unnecessary
object creations/memory leaks. We can also determine memory boundaries available to the application
looking at the maximum values. Co-relating this with other charts can be useful in narrowing down memory
management issues in the application.
• JVM Buffer - Shows the jvm buffer count and memory usage.
174
CONFIDENTIAL Esper Metrics
Engine Metrics can be seen at the top at all times and have the following attributes as per Esper:
• inputCount - Cumulative number of input events since engine initialization time. Input events are defined
as events send in via application threads as well as insert into events.
2
See engine metrics .
Statement Metrics can be seen on the bottom panel and can be set to display only selected statements.
• wallTime - Statement processing wall time in nanoseconds (based on System.nanoTime). This is the most
useful metric from esper as it indicates how much time is spent on a specific Esper statement, that can
indicate either a bottleneck in the code called by the esper statement, or that the statement itself is too
resource heavy, complicated or overloaded.
• numOutputIStream - Number of insert stream rows output to listeners or the subscriber, if any.
• numOutputRStream - Number of remove stream rows output to listeners or the subscriber, if any.
2
http://esper.espertech.com/release-7.0.0/esper-reference/html/api.html#api-instrumentation-enginemetrics
175
CONFIDENTIAL Hazelcast Metrics
3
See statement metrics .
Two types of hazelcast metrics are tracked. One is the Hazelcast side general IMap operation performance, as
opposed to the Facade metrics that are AlgoTrader's abstraction over Hazelcast, tracking AlgoTrader specific
operations.
Dashboard Parameters:
This dashboard is useful to monitor Hazelcast cache performance (call-counts, memory-usage, latency). Allows
the user to pinpoint slow, overloaded or memory intensive caches that could be a source of performance issues.
Provides actual operation call-count (count), operation-time mean (average), upper (maximum) and sum
(cumulative) measurements for each measurement period.
3
http://esper.espertech.com/release-7.0.0/esper-reference/html/api.html#api-instrumentation-statementmetrics
176
CONFIDENTIAL Market Data Metrics
This dashboard is similar to Cache Metrics in that it tracks cache usage performance (call-counts, latency), but
at a higher level and allows the user to pinpoint specific methods that can be the source of bottlenecks. This
is the main metric used to find the ideal performance hot-spots to optimize in the caches.
Used to monitor Exchange and internal AlgoTrader latency and event count, measuring how much it takes for
specific types of market data (including ticks) to arrive from different market data providers, and how long it
takes to propagate them internally. This is not available for all providers as not all venues provide the necessary
data (sending-time).
177
CONFIDENTIAL Market Data Metrics
There are two blocks of panels. The upper section has Internal count and latency figures, while the bottom
block of panels contains the Exchange figures. The connection between the two lies in the adapter layer,
so internal really means Adapters-to-Strategies and exchange means Exchanges-to-Adapters, describing the
external (network) and internal path market data takes. These metrics are useful for monitoring the network
connection to the exchanges and to detect outages and general responsiveness, to determine the source of
adapter issues, whether it is internal/external, load/network/latency related.
• Count By
178
CONFIDENTIAL Market Data Metrics
• Adapters and Classes - Identifies how many of a type (internal data class) of event an adapter (from the
exchange) propagates internally (to Strategies) during the last measurement period.
• Adapters - The number of events an adapter propagates to strategies, this is an aggregation of the above
mentioned data by adapters.
• Classes - The number of events grouped by type propagated from all the adapters combined, this is an
aggregation of the first panel's data by event type (internal data class).
• Delay By
• Adapters and Classes - Measures the latency of by type (internal data class) of event an adapter
propagates internally (to strategies) during the last measurement period.
• Adapters - Latency of events an adapter propagates to strategies, this is an aggregation of the above
mentioned data by adapters.
• Classes - Latency of events grouped by type propagated from all the adapters combined, this is an
aggregation of the first panel's data by event type (internal data class).
• Count By
• Adapters and Classes - Identifies how many of a type of event (exchange data class) an exchange
sends to AlgoTrader (adapters) during the last measurement period.
• Adapters - The number of events an exchange sends to AlgoTrader (received by the exchange specific
adapter), this is an aggregation of the above mentioned data by adapters/exchanges.
• Classes - The number of events grouped by type sent to AlgoTrader (received by the exchange specific
adapter) from all the exchanges combined, this is an aggregation of the first panel's data by event type
(exchange data class).
• Delay By
• Adapters and Classes - Measures the latency of by type (exchange data class) of event an exchange
sends to AlgoTrader (adapter) during the last measurement period.
• Adapters - Latency of events an exchange sent to AlgoTrader (received by the exchange specific adapter),
this is an aggregation of the above mentioned data by adapters/exchanges.
• Classes - Latency of events grouped by type sent to AlgoTrader (received by the exchange specific
adapter) from all the exchanges combined, this is an aggregation of the first panel's data by event type
(exchange data class).
179
CONFIDENTIAL Order Metrics
These metrics track exchange and internal AlgoTrader latency and event count, measuring the delay between
sending orders and a receiving a response/status (ack, fill, reject, cancel) from the target trading venue. This
is not available for all providers as not all venues provide the necessary data (sending-time).
Note: the numbers on this screenshot are not representative as they have been recorded on a demo account
that has some order limitations put in place inflating the numbers.
There are two blocks of panels the upper section has internal count and latency figures, while the bottom block
of panels contains the exchange figures. The connection between the two lies in the adapter layer, so Internal
really means Adapters-to-Strategies and exchange means Exchanges-to-Adapters, describing the external
(network) and internal path market data takes. These metrics are useful for monitoring the network connection
to the exchanges and to detect outages and general responsiveness, to determine the source of adapter issues,
whether it is internal/external, load/network/latency related.
180
CONFIDENTIAL Order Metrics
• Count By
• Adapters and Classes - Identifies how many of a type (internal data class) of order were sent (by
strategies) internally (to adapters) during the last measurement period.
• Adapters - The number of orders strategies propagate to an adapter, this is an aggregation of the above
mentioned data by adapters.
• Classes - The number of orders grouped by type propagated to all the adapters combined, this is an
aggregation of the first panel's data by event type (internal data class).
• Delay By
• Adapters and Classes - Measures the latency by type (internal data class) of order sent (by strategies)
internally (to adapters) during the last measurement period.
• Adapters - Latency of events an adapter propagates to strategies, this is an aggregation of the above
mentioned data by adapters.
• Classes - Latency of events grouped by type propagated from all the adapters combined, this is an
aggregation of the first panel's data by event type (internal data class).
• Count By
• Adapters and Classes - Identifies how many of a type of order (exchange data class) an exchange sent
to AlgoTrader (adapters) during the last measurement period.
• Adapters - The number of order responses an exchange sends to AlgoTrader (received by the exchange
specific adapter), this is an aggregation of the above mentioned data by adapters/exchanges.
• Classes - The number of order responses grouped by type sent to AlgoTrader (received by the exchange
specific adapter) from all the exchanges combined, this is an aggregation of the first panel's data by event
type.
• Delay By
• Adapters and Classes - Measures the latency of atype of order response (SUCCESS, FAIL) an Exchange
sent to AlgoTrader (adapter) during the last measurement period.
• Adapters - Latency of order responses an exchange sent to AlgoTrader this is an aggregation of the above
mentioned data by adapters/exchanges.
• Classes - Latency of order responses grouped by type sent to AlgoTrader from all the exchanges
combined, this is an aggregation of the first panel's data by event type.
181
CONFIDENTIAL Tick-to-Trade
12.3.6. Tick-to-Trade
Unlike other metrics this one is not readily available and calculated, and needs some additional math/guesswork
to have. All the necessary data to calculate the Tick-to-Trade metric is available as smaller parts of other metrics
and panels on the Section 12.3.4, “Market Data Metrics” and Section 12.3.5, “Order Metrics” dashboards. To
have a clearer picture lets have a look at how the Tick-to-Trade is build and what components we specifically
need from those two dashboards to be able to calculate it. If the whole process is automated via a strategy
then the data path is the following:
Order Path:
Adding up the latencies on these paths, gives us an accurate approximation of the Tick-to-Trade metric.
Depending on the requirements it can be calculated in a variety of ways, of which the simplest is to take the
Delay Average panel values and add them up by path, be aware that this is only an average though and
we can have outliers. The way it translates is the following: the first three points directly correspond to the
values displayed on the Market Data and Order dashboards, and the last free can be seen as a single path
that we cannot separately measure, only as a cumulative network latency value and is displayed on the Order
dashboard.
Since the panels contain more specific data history filtered/grouped by exchange, order type and market data
type, mirroring the previous data path calculation process with carefully selected data can determine the Tick-
to-Trade metric at a certain time for a fixed order type, market data type and exchange if desirable.
In addition to being able to calculate the Tick-to-Trader metric, having the sub-component panels helps tracking/
narrowing down and potentially solve the issue when the value is becomes overinflated.
182
CONFIDENTIAL Influx Metrics
A dump of Influx's own usage data that it keeps, useful to track memory usage and general influx performance.
183
CONFIDENTIAL UI Metrics
12.3.9. UI Metrics
Tracks page loads, memory consumption and tick, order book and aggregated order book messages that are
streamed into the browser instance. Metrics are discriminated by browserId - an unique identifier of given
browser instance (it's a local storage variable, i.e. it is set uniquely for each URL and browser combination).
BrowserId can be checked in either local storage variables (AG_1_BROWSER_ID) or in requests parameters.
Metrics are first aggregated on UI side and then sent periodically (html5.metricsPushInterval) to backend
and saved to metrics store. So for example if single data point states that the number of order book messages
was equal to 100, it means that 100 messages were received by UI in given period.
184
CONFIDENTIAL UI Metrics
185
Chapter 13. CONFIDENTIAL
Risk Management
Using the provided functionality of the system, the following risk metrics can be enforced by AlgoTrader based
strategies:
• Minimum Cash-Balance
• etc.
Note
Enforcing these rules requires coding and is not available through configuration only.
• etc.
1. Create a client-specific base project which has a maven dependency to the algotrader-core module. This
Project will be used to start the application.
2. Inside this base project provide as many implementations of the OrderValidator class as needed.
3. Provide a custom wiring-class inside the base-project that is initializing these OrderValidators.
186
CONFIDENTIAL Pre-Trade Checks
When AlgoTrader is started, all OrderValidator implementations are injected into the OrderService. Every
time an Order is sent or modified (not on cancel) and one of the OrderValidators throws an exception, the
Order will be rejected and will not go out to the broker or exchange.
187
Chapter 14. CONFIDENTIAL
Forex Handling
The System provides full Forex and Currency Exchange Management. FX Rates can be retrieved in real-time.
All portfolio figures are calculated based on up-to-date FX-Rates.
FX conversion is provided through the MarketDataService. When subscribing for a non-portfolio currency
instrument the system will automatically subscribe the Forex instrument necessary to convert the non-portfolio
currency balance (e.g. realized PnL and market value) into the portfolio currency. In some cases multiple Forex /
Currency Pairs (based on the same base and quote currency) are available in the system which are traded
through different brokers / exchanges.
For those cases a special setting misc.defaultMarketAdapters defines the priority in which market adapters
and exchanges are used. The default value is the following:
misc.defaultMarketAdapters =
BITMEX:CNP,OKEX:CNP,OKCOIN:CNP,BINANCE:CNP,HUOBI:CNP,BITFINEX:CNP,BITHUMB:CNP,HITBTC:CNP,KRAKEN:C
This is a comma separated list of preferred <exchange>:<adapterType>. Exchange code is taken from the
database security.exchange_code value and adapter type is ch.algotrader.enumeration.AdapterType.
Optional specific security pairs are also supported, using '@' symbol, e.g. 'BTCUSD@BITF:CNP'. When the
platform needs to make a conversion for a given forex, it will iterate over this list and determine the first match.
Match means all of the below:
• Current adapter type is active, e.g. it's Spring profile is enabled (e.g. if cNPMarketData is active then 'CNP'
will be matched for CoinApi securities)
To change the default settings the following property needs to be updated inside conf.properties.
Alternatively the properties can be changed via Section 2.4, “VM Options”
188
CONFIDENTIAL Futures
14.1.1. Futures
• Futures are fully margined, that's why buying a Future does not actually influence cash but only the margin
requirement.
• AlgoTrader however treats Futures as regular Securities (i.e. add Future Market Value to System Market
Value and deduct Transaction Price from cash)
Note
• To compare AlgoTrader Balances to IB Balances (if there are Future Positions), one has to
compare the Net Liquidation Value and not Cash / Market Value individually
14.1.2. Forex
• Forex (e.g. EUR.USD) consists of the Base Currency (e.g. EUR) and Quote Currency (e.g. USD)
• In Balances Forex are attributed towards Cash (and not system Market Value) in the Base Currency
• The gross value of a transaction is booked in the Quote Currency, whereas the commission is booked in
the Base Currency.
Note
The TWS Trades Window displays commissions in Trade Currency, but IB Flex Reports displays
commissions correctly in the Base Currency.
189
CONFIDENTIAL Forex-Hedging
The following table describes Currency Attribution of Transactions. The logic is implemented by
Transaction.getAttributions()
14.2. Forex-Hedging
The system provides automatic Forex-Hedging by the Service ch.algotrader.service.ForexService. This
service will maintain multiple FX Positions to hedge all non base currency balances. For actual Forex-Hedging
the following two options exist
Exchange trading allows you to exchange/convert one crypto/fiat amount into another (e.g. converting USD to
BTC). Using exchange trading short trades are not possible.
Margin trading allows you to have long and short positions on any pair (e.g. long BTC/USD or short ETH/BTC).
The SimpleOrder property exchangeOrder (which is false per default) drives which account you are trading
against:
Note
Note that every broker / exchange differs on how to submit exchange account vs. margin account
orders.
Some require you to use different securities (e.g. Bitflyer), others different order types or price
types.
190
CONFIDENTIAL FX Future
Margin positions can be useful also for Hedging purposes. Depending on the current exposure of a non-base
currency equity portfolio, an offsetting margin position can be maintained to result in a zero non-base currency
exposure.
14.2.2. FX Future
The second option for FX Hedging is by means of FX Futures which is a subclass of Future.
For some FX security families there are multiple entries available with different contract sizes (e.g. 12'500,
62'500 and 125'000 for EUR.USD). Because of this the hedgingFamily has to be defined as a Property on
the EUR.USD subscription.
Since FX Futures expire, the Hedging Position has to be rolled before Expiration, which is also done
automatically based on configured parameters.
191
Chapter 15. CONFIDENTIAL
For hints on how to roll futures and options, see Section 4.3.1.8, “Rolling of Futures and Options”.
In addition to the expiration date (sometimes also called lastTradingDay) Futures also have the following
two fields:
• firstNoticeDay: this is the day on which the buyer of a futures contract can be called upon by the exchange
to take delivery
Note
expiration and maturityMonthYear do not necessarily need to be within the same month.
e.g. maturityMonthYear: 2015-12, expiration: 2015-11-30
The following table contains references on how these three fields are used by different market data providers
For an detailed explanation between lastTradingDay and firstNoticeDay please visit this page on futures
1
expiration
Note
IB also shows an expiration date in TWS which is either the same day or the next day after
the last trading day
1
http://www.futurestradingpedia.com/futures_expiration.htm
192
CONFIDENTIAL Symbol, ISIN & RIC
CS
Contract Size
CV
Current Value
S
Underlying Spot price
D
Delta
Q
Quantity
Note
193
CONFIDENTIAL Option & Future Chain Download
Since some underlying have more than one Futures Chain based on them, the property hedgingFamily needs
to be defined on the Subscription of the underlying. In addition the method hedgeDelta can also be invoked
with the ServerManagementService.
• implied volatility (through Black-and-Scholes, Newton Rapson Method and SABR Surface)
• intrinsic value
• delta
• vega
• theta
• forward price
• moneyness
• strike by delta
Based on historical Volatility at different Moneyness levels (e.g. ATM, ATM +10%, ATM +20%, ATM -10% &
ATM-20%) or Delta levels (e.g. 50%, 35%, 75%) volatility parameters are calculated (=calibration) and used
for option pricing.
SABR Calibration can be done either by actual Option Prices or directly by the Implied Volatility. Also there
are methods to do a SABR Calibration just for one expiration (returning one SABR Smile Value Object) or
194
CONFIDENTIAL Option Pricing
for an entire Volatility Surface (returning a SABRSurface ValueObject which consist of multiple SABRSmile
ValueObjects)
The SABR Calibration depends on different Implied Volatilities (a subclass of Security) being defined in the
database. A Implied Volatility needs to define either a moneyness or a delta (in addition to Duration and Option
Type).
1. For all available expirations a volatility is calculated for the requested strike
2. Using spline interpolation the volatility for the requested expiration is calculated
15.7.3. References
2
• Hedging under SABR Model, Refined risk management under the SABR model.
3
• Extensions of the SABR model for equity options.
2
http://www.lesniewski.us/papers/published/HedgingUnderSABRModel.pdf
3
https://essay.utwente.nl/59228/1/scriptie_I_Khomasuridze.pdf
195
Chapter 16. CONFIDENTIAL
Broker/Exchange Interfaces
The System provides generic interface functions to connect AlgoTrader to different brokers / exchanges.
• Fix Interfaces
• B2C2
• Bitstamp
• Blockfills
• Bloomberg Tradebook
• Coinbase Pro
• CryptoFinance
• Currenex
• Deribit
• DukasCopy
• Enigma
• Exante
• EzeSoft/RealTick
• Fortex
• FXCM
• Gemini
• InteractiveBrokers
• JP Morgan
• LMAX Digital
• LMAX Global
• Nexus Prime
• One Zero
• PrimeXM
196
CONFIDENTIAL
• SocGen
• UBS
• B2C2
• Bitstamp
• Coinbase Pro
• Tilde
• Native Interfaces
• Bloomberg
• Interactive Brokers
• REST/WebSocket Adapters
• Binance
• Bitfinex
• Bitflyer
• BitHumb Pro
• BitMEX
• Bittrex
• CryptoFinance
• Enigma
• eToroX
• Huobi Spot
• Kraken Spot
• OKEx
• OKCoin
1
https://www.quickfixj.org/
197
CONFIDENTIAL
For further details on Broker/Exchange adapters please see Chapter 23, Adapters
198
Chapter 17. CONFIDENTIAL
Order Management
17.1. Order Validation
Before sending an Order, it is advised to call the validate method on the order. This will validate the order
regarding limits, amount, quantity, etc. In case validation fails an Exception will be thrown and the order can
be modified.
Note
The validate method will be called (again) inside the sendOrder method, in case the validation
fails an Exception will be thrown.
In addition to the validate method all configured Section 13.1, “Pre-Trade Checks” will be invoked. In case any
pre-trade check is breached the order will be rejected.
getOrderService().sendOrder(order);
The associated Entities (i.e. strategy, account and security) can be retrieved via the LookupService.
199
CONFIDENTIAL Place Order
getOrderService().sendOrder(order);
getOrderService().sendOrder(order);
Sending an algo order using Order Value Objects looks like this:
getOrderService().sendOrder(order);
The broker / exchange specific SimpleOrderExecService will create the broker / exchange specific order,
assign an intId if none has been assigned yet and send the order to the broker / exchange.
200
CONFIDENTIAL Order Preferences
After sending the Order to the broker / exchange, the order object is propagated to the AlgoTrader Server
Esper service instance (running inside the AlgoTrader Server) as well as to the Esper service instance of the
corresponding strategy (where potential actions like cancel order or modify order can be executed).
Open orders are kept in an internal order book until their full execution or cancellation. Completed
orders remain in the book and are accessible through OrderService until evicted. AlgoTrader evicts
completed orders at 24:00 local time daily by default. One can also manually evict orders by calling
OrderService#evictExecutedOrders() method.
The actual exchange an Order is sent to will be retrieved from the associated Security/SecurityFamily.
Alternatively it is possible to assign an Exchange to an Order Entity or Order Value Object directly.
As AlgoOrders typically have a lot of parameters (e.g. minQuantity, maxQuantity for the SlicingOrder) it is
possible to save a set of settings using the OrderPreference Entity. The following OrderPreference SLICING
is contained within the db-samples (/algotrader-conf/src/main/resources/db-samples/mysql/mysql-
data.sql):
(202,'SLICING','SLICING','{"minDelay":2,"maxDelay":3,"maxVolPct":1,"minDuration":1,"maxQuantity":20
The OrderPreference SLICING defines default settings for the Slicing Order. Through the column
DEFAULT_ACCOUNT_FK it is also possible to define a default account for the AlgoOrder. With this information
available in the database an order can now be created as follows:
getOrderService().sendOrder(order);
201
CONFIDENTIAL Order Properties
Order properties of type INTERNAL are kept inside the system and are not propagated to external brokers.
If the type of an Order property is FIX it is assigned to an outgoing Fix order as an additional fix tag. It is
therefore mandatory that the name of the order property is a number (representing the fix tag).
If the type of an Order property is FIX_LITERAL it is parsed and assigned to an outgoing Fix order as a list of
fix tags. It is therefore mandatory that the value of the order property is a string consisting of comma delimited
entries tag=value.
If the type of an Order property is IB the system will try to find an IB order field corresponding to the IB order
1 2
property name . In case no matching field is found the order property is added as an AlgoParams )
Any object can be attached to an order as a property value using addProperty(String name, Object value)
method, it can be done as follows:
order.addProperty("myProperty", "propertyValue");
order.removeProperty("name");
1
http://interactivebrokers.github.io/tws-api/classIBApi_1_1Order.html
2
http://interactivebrokers.github.io/tws-api/classIBApi_1_1Order.html
202
CONFIDENTIAL Order requests and confirmations
The method getOrderProperties cannot be used to manage order properties it's returning unmodifiable map
of OrderProperty objects excluding all other properties provided to order, to remove or update properties it's
needed to use methods above.
Note
OrderProperties are only supported on Order Entities but not on Order value objects (VOs).
• Modify Order - modifies already placed Order. Only one request for Order modification can be active at a
time. Also, modification request will be rejected if Order was requested to be cancelled already.
You can be explicitly notified inside the Strategy about confirmations or rejections for each
request that you placed via Order Service. This functionality can be considered an alternative
approach to being notified about OrderStatus changes (this is more extensive solution than
OrderStatus notification - as OrderStatus information won't give you information about Order
modification requests being rejected for example). To subscribe for Order Request Statuses,
use listener below in your StrategyService implementation:
@Override
public void onOrderRequestStatus(OrderRequestStatusEventVO event) {
}
203
CONFIDENTIAL Smart Order Routing
Note
• Smart Routing is only supported for Stock and Forex spot securities
• You can configure the estimated fees that are used by smart orders in the security or
security_family data by setting one or more of
• EXECUTION_COMMISSION_PER_ORDER
• EXECUTION_COMMISSION_PER_CONTRACT
• EXECUTION_COMMISSION_IN_PERCENT
Alternatively, you can set the estimated fees by security on the order by using the
expectedFees field on routing target (see the JSON/Java examples below)
• Smart limit and stop orders are managed/monitored by our system until they are triggered
by market data events, at which point they are sent to a broker/exchange. This also means
you can place e.g. a smart stop order including an exchange that does not natively support
stop orders
• All smart orders are algos, which are ended when AlgoTrader is stopped. This is also true for
"simple" smart orders at the moment
In order to place a smart routing order using the API, you should populate the candidates parameter with a
list of potential targets Target consists of security, account and exchange
{
"@class": "ch.algotrader.entity.trade.algo.SmartMarketOrderVO",
"side": "BUY",
"strategyId": 2,
204
Additional
CONFIDENTIAL
Smart Order Configurations (Mostly Crypto-Relevant)
"exchangeOrder": true,
"quantity": "1",
"tif": "GTC",
"routingCandidates": [
{
"securityId": 911,
"accountId": 200,
"exchangeId": 200
},
{
"securityId": 903,
"accountId": 211,
"exchangeId": 210
},
{
"securityId": 898,
"accountId": 202,
"exchangeId": 202,
"expectedFees": 1.23
}
]
}
getOrderService().sendOrder(order);
205
CONFIDENTIAL Order Status
• Since crypto-exchanges are fairly diverse in what time in force options they support, choosing one option
might exclude a lot of exchanges, which do not support it.
We have a configuration on exchange adapter level that allows you to default an order to a different TIF if
the one on the order is not supported, e.g.
This behavior is disabled by default. If you want to make use of the TIF conversion, you need to set property
misc.algoOrderFallbackToDefaultTif to true.
You can configure them to execute market orders as limit orders, at an offset of the current market price, e.g.
Permitted Order Status transitions are depicted by the following state machine diagram.
206
CONFIDENTIAL Receive Fills
If an order does not receive either an Acknowledgment or Fill within a configurable time period (default: 1
sec) after sending the Order, an Exception is thrown, as there might be a problem with the broker / exchange
connection. This is enforced by the NOTIFY_MISSING_ORDER_REPLY statement which can be turned off by
changing the following property inside conf-core.properties. Alternatively the properties can be changed
via Section 2.4, “VM Options”
Once all fills corresponding to an Order are fully persisted an OrderCompletionVO event is generated and
propagated to the Strategy. By the time an OrderStatus event is received by the strategy, corresponding
database activity might not have been completed yet. However by the time an OrderCompletionVO event is
received, it is guaranteed that all database activity has been completed. It is therefore safe to invoke any sort
of the database lookup at this time. For further details see Section 8.4.8, “Callbacks”.
207
CONFIDENTIAL Handling of Fees and Commissions
The Fill events trigger the creation of a Transaction object (a persistent Record in the database). In addition
the Fill and corresponding Transactions are also propagated to the strategy, where actions can be taken upon.
Note
Fills and Transactions are separated from each other for the following reason. A Fill contains all
the information received from the broker / exchange (and a reference to the Order). Whereas
a Transaction contains all the information related to accounting (i.e. references to position and
strategy). In addition to Transactions related to Fills, there are Transactions that are independent
of Fills (i.e. Deposits, Withdrawals, Interest, etc.).
• Exchange Fees
Most adapter for traditional asset classes (e.g. equities, forex and derivatives) do not provide fee information
on execution messages. Some crypto exchanges provide fee information. If the fees are in the currency
of the transaction, they are stored in the fee attribute of the transaction. In case the fees are charged in
another currency (for example Binance charges in its own currency - BNB), a new transaction is created with
transactionType = FEES, quantity = -1 for fees paid (and quantity = -1 for fees received, e.g. maker
rebates), price = fee value and currency = fee currency.
For the other adapters, AlgoTrader uses the internal Execution Model (see Section 5.1, “Exchange Simulator”)
to assign fees and commissions based on configuration (e.g. commission-per-contract).
Transactions:
208
CONFIDENTIAL Exchange Order with Fee in Base Currency
Cash Balances:
CURRENCY AMOUNT
USD -8.7438528
Positions:
QUANTITY COST
0.002 8.7438528
Transactions:
Cash Balances:
CURRENCY AMOUNT
USD -13.12270318
BTC 0.002994
Transactions:
209
CONFIDENTIAL Internal Order Id Format
Cash Balances:
CURRENCY AMOUNT
USDT -13.18653000
BTC 0.00300000
BNB -0.00179554
<session_qualifier><id>.<version>
Example: lmax1.1
• id: an integer which is auto-incremented per session. For Fix, the last id is retrieved from the order table
during start up
• version: The number of modifications that took place on the Order, starting with 0 when the order is first
submitted.
By default AlgoTrader automatically assigns an IntId value to all outgoing orders. Open and executed orders
can be identified and looked up by their IntId.
Especially when using a Section 8.4.8.2, “Trade callback” it is necessary to generate and assign an IntId
value to the order prior to submitting it to the order service. The OrderService#getNextOrderId() method
can be used to generate a unique IntId value per session associated with an Account record.
order.setIntId(orderId);
210
CONFIDENTIAL Symbology
});
getOrderService().sendOrders(orders);
Note
Please note that care must be taken when using OrderService#getNextOrderId() with the IB
order service. The IB native interface expects orders to be sent with their order ids in ascending
order. The Class IBOrderIdSynchronizer is responsible to make sure order ids are actually
in ascending order. In case an order id is skipped the IBOrderIdSynchronizer will wait for up
to maxOrderSyncTime milliseconds for the order with the correct order id to arrive.
17.10. Symbology
In the electronic trading domain there are different ways to identify a security, some of which are:
• Symbol
• Bloomberg ID
• etc.
Different Brokers employ different types of Symbology to identify a security. For this purpose AlgoTrader
provides the notion of SymbologyResolver which is responsible for assigning appropriate information to
outgoing broker / exchange communication. These SymbologyResolvers can be extended on a per adapter
basis.
211
Chapter 18. CONFIDENTIAL
Market Data
AlgoTrader provides Market Data Interfaces with the following market data providers:
• Fix Interfaces
• B2C2
• CryptoFinance
• Enigma
• Native Interfaces
212
CONFIDENTIAL
• REST/WebSocket Interfaces
AlgoTrader allows having multiple market data interfaces active at the same time so market data received from
different market data providers can be compared in real-time.
To enable either of those Market Data Interfaces the following two steps have to be executed:
1. The correct Spring Profile has to be activated according to Section 26.2, “Spring Profiles”
2. For Bloomberg market-data-bb and for InteractiveBrokers market-data-ib has to be added to the VM
argument server-engine.init when running the AlgoTrader server.
• BarVO Open-High-Low-Close Price Bars, also containing volumes and volume weighted average prices
• TickVO: The top of the order book at a particular point in time, containing information like last price, last
time, bid, ask, volume, etc.
• QuoteVO: Its subclasses represent the current best bid and offer BidVO and AskVO
213
CONFIDENTIAL Creation of Bars based on Ticks
• TradeVO: An actual order that was executed on the market, containing information like last price, last size
and volume
• GenericTickVO: Represents additional price information made available by market data providers (e.g. open
price, close price, vwap price)
• OrderBookVO: A snapshot of the full order book for a security from the trading venue at a particular moment
in time
• AggregatedOrderBookVO: Contains price levels of the order books from multiple venues combined by a
symbol
As the following diagram shows, market data providers deliver Price Events (TradeVO, BidVO & AskVO) or
individual TickVO Fields.
In back testing AlgoTrader supports both Ticks or Bars. In both live trading and back testing Price events and
Tick events can be aggregated into Bar events
Inside each strategy the MarketDataCacheService keeps a copy of the last MarketDataEvent for each
Security. For further details see Section 7.2.17, “Market Data Cache Service”.
In addition, it is possible to aggregate ticks into bars through Esper code in both Simulation and Live Trading
by using an Esper time_batch window:
select
214
CONFIDENTIAL Creation of Bars based on Bars
first(last) as open,
max(last) as high,
min(last) as low,
last(last) as close
from
TickVO.win:time_batch(1 min)
group by
securityId;
select
max(last) as high,
min(last) as low,
first(last) as open,
last(last) as close
from
TickVO.win:expr_batch(sum(volume) > 1000)
group by
securityId;
Warning
Some market data providers (e.g. Interactive Brokers) will only provide market data snapshots
at regular time intervals. This can cause deviations in the bar high and low price.
Due to clock differences between the local machine and the market data provider's servers there
might be slight deviations in the bar open and close price. It is therefore important to enable
system clock synchronization on the server where AlgoTrader is installed.
• Using Esper
• Using Java
215
CONFIDENTIAL Java Bar Aggregation
@Name('AGGREGATE_BAR_TO_BAR')
insert into
BarVO
select
first(bar.dateTime),
last(bar.adapterType),
last(bar.securityId),
Duration.valueOf('MIN_10'),
first(bar.open),
max(bar.high),
min(bar.low),
last(bar.close),
sum(bar.vol)
from
BarVO(barSize = Duration.valueOf('MIN_1')).win:time_batch(10 min, 0L, "FORCE_UPDATE")
as bar
group by
bar.securityId,
bar.adapterType;
@Override
public void onBar(BarVO bar) {
// add bar to the aggregation
aggregation.add(bar);
}
216
CONFIDENTIAL Price normalization
There are also other parameters that describes order minimums and maximums for quantity and price. They
are described in section: Section 23.2.2, “Crypto-Order Constraints”
Crypto currency exchanges are typically using web sockets to deliver market data. Web socket connections
are typically not very stable and it can happen that a web socket connection disconnects or suddenly stops
receiving data. For this purpose AlgoTrader has a feature that automatically reconnects the corresponding
adapter if no market data has been received for a prolonged period of time. This is enforced by the
CHECK_ADAPTER_TICK_GAP statement which can be turned on by changing the following property inside conf-
core.properties. Alternatively the properties can be changed via Section 2.4, “VM Options”
217
CONFIDENTIAL Generic Events
• External data: For example feeding Corporate Actions events from external data provider.This use case
requires an external data adapter to be implemented. AlgoTrader has an integrated dividend data feed to
demonstrate the feature (through the Intrinio data provider). A strategy can subscribe to these events and
use them as market signals or inputs. Our Appendix J, Example Strategy "Dividend Capture" shows how
this is done.
getGenericEventsService().subscribe("MSFT",
MarketDataEventType.DIVIDENDS,
getStrategy(),
AdapterType.INTR,
Collections.singletonMap("selector", "MSFT"));
In distributed mode AlgoTrader must be started with the iNTRDividendGenericEvents Spring profile which
would enable the dividend data feed while the strategy must be started with genericEventsService profile,
which enables dividend data propagation between server and strategy.
• Strategy to strategy communication: two (or more) strategies can exchange information between
each other. A custom object extending GenericEventVO must be introduced and both strategies must have
references to it.
getSubscriptionService().subscribeGenericEvents(Collections.singleton(CustomEventVO.class))
A publisher strategy can emit custom events like this in distributed mode:
eventDispatcher.broadcast(customEvent, EventRecipient.REMOTE_ONLY);
218
CONFIDENTIAL Generic Events
eventDispatcher.broadcast(customEvent, EventRecipient.ALL_LOCAL_LISTENERS)
Alternatively instead of broadcasting, it is possible to send the events directly to the desired strategy as
follows:
eventDispatcher.sendEvent(strategy.getName(), customEvent);
If the event is sent directly to the strategy, the target strategy doesn't need to be explicitly subscribed to
this event.
All generic events can be persisted in InfluxDB by setting the following property in conf.properties:
Downloaded (or recorded) generic events can be used in simulations (both InfluxDB and CSV files are
supported).
It is also possible to feed Generic Events via CSV Files or InfluxDB in Simulation Mode. The following properties
control the data sources:
The configuration above will feed tick data from CSV and dividend data from InfluxDB. See more sample
configurations in conf.properties
The file name of the CSV File has to be according to this schema:
<className>.<rank>.csv
219
CONFIDENTIAL Generic Events
• rank is the sort order for situations where there are multiple GenericEvent types for the same time stamp
Suppose you have created your own class extending GenericEventVO, say MyEvent. In order to make it
persistable into InfluxDb, complete the following steps:
@Measurement(name = "MyEvent")
public class MyEvent extends GenericEventVO {
@Column(name = "Info")
private String info;
public MyEvent(){}
dataSource.N.dataSourceType = DB
dataSource.N.eventType = CUSTOM
dataSource.N.fullyQualifiedName = namespace.MyEvent
where N is the ordinal of the datasource configuration entry, namespace.MyEvent is the fully qualified name
of your class
220
Chapter 19. CONFIDENTIAL
Historical Data
AlgoTrader provides Historical Data Interfaces with the following market data providers:
• Native Interfaces
• Bloomberg
• Interactive Brokers
• Quandl
• CoinAPI
• CoinMarketCap
1
AlgoTrader uses the time series database InfluxDB for storage of historical data. InfluxDB is an open
source database written in Go specifically designed to handle time series data with high availability and high
performance requirements.
In addition the platform also provides a feature for downloading historical data from external market data
providers. This historical data can be used for strategy simulations or for any type of analysis.
The Historical Data Manager (Section 11.3, “Historical Data Manager”) client provides a convenient UI for
managing historical data.
• Storage: storeHistoricalBars
To use the Historical Data Service the corresponding Spring profile has to be added via VM argument:
-Dspring.profiles.active=influxDB,bBHistoricalData
221
CONFIDENTIAL InfluxDB
-Dspring.profiles.active=influxDB,iBHistoricalData
-Dspring.profiles.active=influxDB,qDLHistoricalData
-Dspring.profiles.active=influxDB,cNPHistoricalData
-Dspring.profiles.active=influxDB,cMCHistoricalData
-Dspring.profiles.active=influxDB,noopHistoricalData
Note
The Noop Historical Data Service does not have a connection to an external data source. It can
be used during Simulation to access existing historical data from InfluxDB.
Note
When running a strategy in distributed mode in case that requires historical data service, a
special historicalData profile must be specified on the strategy side. In addition an actual
historical data profile (e.g. iBHistoricalData) must be specified on the server side.
-Dspring.profiles.active=live,historicalData
19.1. InfluxDB
2
For detailed information on InfluxDB please have a look at the InfluxDB Documentation .
InfluxDB can be installed locally or using Docker, please see Chapter 2, Installation and Deployment.
Data in an InfluxDB instance can be managed via the AlgoTrader Historical Data Manager (Section 11.3,
“Historical Data Manager”).
2
https://docs.influxdata.com/influxdb/
222
CONFIDENTIAL InfluxDB
InfluxDB provides both a command line client (CLI) as well as a REST based client which is used by various
3
client side libraries. AlgoTrader uses the influxdb-java library to communicate with InfluxDB. For all operations
that involve the time series database InfluxDB, the following spring profile has to be specified via VM argument:
-Dspring.profiles.active=influxDB
If InfluxDB is installed locally, the influx command should be available via the command line. Executing
influx will start the CLI and automatically connect to the local InfluxDB instance. The output should look like
this:
Note
• The InfluxDB HTTP API runs on port 8086 by default. Therefore, influx will connect to port
8086 and localhost by default. If these defaults need to be altered please run influx --
help.
• The -precision argument specifies the format/precision of any returned timestamps. In the
4
example above, rfc3339 tells InfluxDB to return timestamps in RFC3339 format (YYYY-MM-
DDTHH:MM:SS.nnnnnnnnnZ).
The command line is now ready to take input in the form of the Influx Query Language (a.k.a. InfluxQL)
statements. To exit the InfluxQL shell, type exit and hit return.
Most InfluxQL statements must operate against a specific database. The CLI provides a convenience
statement, USE <db-name>, which will automatically set the database for all future requests. To use the
algotrader database please type:
Now future commands will only be run against the algotrader database.
At this point SQL-like queries can be executed against the database. In InfluxDB tables are called
measurements. AlgoTrader uses the two measurements tick and bar. Columns that hold actual data (e.g.
open or high) are called fields, and columns holding static data (e.g. barSize) are called tags.
3
https://github.com/influxdata/influxdb-java
4
https://www.ietf.org/rfc/rfc3339.txt
223
CONFIDENTIAL InfluxDB
As an example the following query shows all current bars in the database:
5
For an in depth description of the query syntax please visit the InfluxDB query language documentation .
To import existing data into InfluxDB please use the following command:
# DML
# CONTEXT-DATABASE: algotrader
bar,securityId=25,adapterType=IB,barSize=MIN_1
open=1.30319,high=1.30402,low=1.30319,close=1.30367,vol=0 1324245720000000000
bar,securityId=25,adapterType=IB,barSize=MIN_1
open=1.30369,high=1.30369,low=1.30351,close=1.30352,vol=0 1324245780000000000
bar,securityId=25,adapterType=IB,barSize=MIN_1
open=1.30353,high=1.30383,low=1.30353,close=1.30382,vol=0 1324245840000000000
bar,securityId=25,adapterType=IB,barSize=MIN_1
open=1.30381,high=1.30411,low=1.30373,close=1.30373,vol=0 1324245900000000000
bar,securityId=25,adapterType=IB,barSize=MIN_1
open=1.30378,high=1.30428,low=1.30376,close=1.30425,vol=0 1324245960000000000
bar,securityId=25,adapterType=IB,barSize=MIN_1
open=1.30426,high=1.30426,low=1.30396,close=1.30399,vol=0 1324246020000000000
bar,securityId=25,adapterType=IB,barSize=MIN_1
open=1.30401,high=1.30411,low=1.30371,close=1.30378,vol=0 1324246080000000000
# DML
5
https://docs.influxdata.com/influxdb/v1.1/query_language/
224
CONFIDENTIAL InfluxDB
# CONTEXT-DATABASE: algotrader
tick,securityId=25,adapterType=IB
last=1.303670,lastDateTime=1324245720000,bid=1.303670,ask=1.303670,volBid=0,volAsk=0,vol=0
1324245600000000000
tick,securityId=25,adapterType=IB
last=1.303670,lastDateTime=1324245720000,bid=1.303670,ask=1.303670,volBid=0,volAsk=0,vol=0
1324245660000000000
tick,securityId=25,adapterType=IB
last=1.303670,lastDateTime=1324245720000,bid=1.303670,ask=1.303670,volBid=0,volAsk=0,vol=0
1324245720000000000
tick,securityId=25,adapterType=IB
last=1.303520,lastDateTime=1324245780000,bid=1.303520,ask=1.303520,volBid=0,volAsk=0,vol=0
1324245780000000000
tick,securityId=25,adapterType=IB
last=1.303820,lastDateTime=1324245840000,bid=1.303820,ask=1.303820,volBid=0,volAsk=0,vol=0
1324245840000000000
tick,securityId=25,adapterType=IB
last=1.303730,lastDateTime=1324245900000,bid=1.303730,ask=1.303730,volBid=0,volAsk=0,vol=0
1324245900000000000
tick,securityId=25,adapterType=IB
last=1.304250,lastDateTime=1324245960000,bid=1.304250,ask=1.304250,volBid=0,volAsk=0,vol=0
1324245960000000000
6
For further information on InfluxDB import please visit the InfluxDB documentation
Note
• The last column in the import file represents the time stamp, which needs to be defined in
nanoseconds since the 1970-01-01
• It is also possible to compress import files. In this case the command line switch -compressed
has to be used when importing files.
To export bar data from InfluxDB into the AlgoTrader CSV file format (see Section 19.8, “Market Data File
Format”) please use the following command:
To export tick data from InfluxDB please use the following command:
6
https://docs.influxdata.com/influxdb/v1.2/tools/shell/
225
CONFIDENTIAL Live Data Recording
Note
The InfluxDB export adds an extra column named "name" as the first column. In order to use the
exported .csv file for simulations one has to remove the first column of the file. The following
Linux command can be used to accomplish this:
To convert an AlgoTrader CSV file into an InfluxDB import file the following two Utility classes can be used:
ch.algotrader.util.influxdb.CSVBarToInfluxDBConverter
ch.algotrader.util.influxdb.CSVTickToInfluxDBConverter
In addition recorded tick-level data can be aggregated into bar-data on the fly by using the following properties
inside conf-core.properties. Alternatively the properties can be changed via Section 2.4, “VM Options”:
# the bar size used for tick-to-bar aggregation and end-of-day historical bar download
historicalData.barSize = MIN_1
In case a certain instrument provides trade information (e.g. Equities and Crypto Currencies) the last traded
price is used to calculate the Bar values. In case no trading information is available (e.g. Forex and Indices)
the midpoint price (average of bid and ask) is used. The bar aggregation feature will also create bars for time
periods when no market data arrives, in this case open, high, low and close will be equal to the previous bars
close price.
226
CONFIDENTIAL Historical Data Download
replace is set to true the method storeHistoricalBars however will replace all current Bars in the database
within the specified time period
Download and storage of historical data can be invoked via the HistoricalDataStarter.
For example:
AlgoTrader also provides features to download missing historical data for all subscribed instruments either on
startup or at a specific time of the day. For these functions the following properties are available inside conf-
core.properties where they can be changed. Alternatively the properties can be changed via Section 2.4,
“VM Options”:
# the bar size used for tick-to-bar aggregation and end-of-day historical bar download
historicalData.barSize = MIN_1
# the market data event type used by the end-of-day historical bar download
historicalData.marketDataEventType = MIDPOINT
Note
• TRADES
• MIDPOINT
• BID
• ASK
• BID_ASK
• BEST_BID
227
CONFIDENTIAL Interactive Brokers Historical Data Download
• BEST_ASK
Depending on whether InteractiveBrokers, Bloomberg or Quandl is used for the historical data download the
corresponding marketData profile has to be specified via VM argument.
InteractiveBrokers:
-Dspring.profiles.active=influxDB,iBHistoricalData
Bloomberg:
-Dspring.profiles.active=influxDB,bBHistoricalData
Quandl:
-Dspring.profiles.active=influxDB,qdlHistoricalData
• Making six or more historical data requests for the same Contract, Exchange and Tick Type within two
seconds.
The AlgoTrader Historical Data Download can optionally avoid potential pacing violation by separating
subsequent download requests by 10 seconds. This feature can be enabled via the following property inside
conf-ib.properties has to be updated. Alternatively the properties can be changed via Section 2.4, “VM
Options”
8
The Historical Data Download also takes the Valid Duration and Bar Size Settings for Historical Data Requests
into account and splits large requests into subsequent smaller requests.
7
http://interactivebrokers.github.io/tws-api/historical_limitations.html
8
http://interactivebrokers.github.io/tws-api/historical_limitations.html
228
CONFIDENTIAL Quandl Historical Data Download
/<baseDir>/<eventType>/<dataSet>/<filename>.csv
• baseDir is the parent directory where all market data files are stored. This is either the files/ directory
under the project algotrader-core or an arbitrary directory defined via the following property inside
conf.properties has to be updated. Alternatively the properties can be changed via Section 2.4, “VM
Options”
• eventType is either tickData, barData or customData (see Section 18.6, “Generic Events”).
• dataSet is the name of the dataset used for the simulation run. This can be defined via the following property
inside conf.properties has to be updated. Alternatively the properties can be changed via Section 2.4,
“VM Options”
9
https://www.quandl.com/
10
https://www.coinapi.io/
11
https://coinmarketcap.com/
229
CONFIDENTIAL Tick Data Files
• isin
• symbol
• bbgid
• ric
• conid
• securityId
An alternative approach is to feed market data for multiple securities using one file. E.g. it is possible to feed
market data for futures using market data from the corresponding generic future. In this approach an additional
column security has to be added to the market data file which will be used to identify the actual Security.
The file name for Section 18.6, “Generic Events” follows a different logic.
• dateTime
• last
• lastDateTime
• volBid
• volAsk
• bid
• ask
• vol
• security (optional)
dateTime and lastDateTime values are expected to be in the yyyy-MM-dd HH:mm:ss format and to represent
local time. Alternatively one can also use long values that represent Java milliseconds since 1970.
Example:
230
CONFIDENTIAL Bar Data Files
• dateTime
• open
• high
• low
• close
• vol
• vwap (optional)
• security (optional)
dateTime values are expected to be in the yyyy-MM-dd HH:mm:ss format and to represent local time.
Alternatively one can also use long values that represent Java milliseconds since 1970.
Example:
231
Chapter 20. CONFIDENTIAL
Reference Data
Amongst others reference Data consists of static data like Security, SecurityFamily, SecurityReference,
Account Entities.
Reference Data can either be configured in the database directly through the corresponding tables, one can
use the ReferenceDataService and corresponding ReferenceDataStarter or you can use the Reference
Data Manager UI, see Section 11.2, “Reference Data Manager”.
Depending on the Reference Data Adapter in use the following download options are available for download:
For further details please see the JavaDoc of the ReferenceDataStarter class.
Example: To download missing Futures of a specified Security Families use the following command
It is recommended to run this Service in the interval of Option / Future Expirations to make sure that the entire
chain is available to strategies.
Depending on the Reference Data Adapter in use the corresponding referenceData profile has to be specified
via VM argument.
Bloomberg:
-Dspring.profiles.active=<dataSource>,bBReferenceData
B2C2:
-Dspring.profiles.active=<dataSource>,b2C2ReferenceData
Binance:
-Dspring.profiles.active=<dataSource>,bNCReferenceData
232
CONFIDENTIAL
Bitfinex:
-Dspring.profiles.active=<dataSource>,bFXReferenceData
Bitflyer:
-Dspring.profiles.active=<dataSource>,bFLReferenceData
BitHumb Pro:
-Dspring.profiles.active=<dataSource>,bHBReferenceData
BitMEX:
-Dspring.profiles.active=<dataSource>,bMXReferenceData
Bitstamp:
-Dspring.profiles.active=<dataSource>,bTSReferenceData
Bittrex:
-Dspring.profiles.active=<dataSource>,bTXReferenceData
CoinAPI:
-Dspring.profiles.active=<dataSource>,cNPReferenceData
Coinbase Pro:
-Dspring.profiles.active=<dataSource>,cNBReferenceData
CoinMarketCap:
-Dspring.profiles.active=<dataSource>,cMCReferenceData
CryptoFinance:
-Dspring.profiles.active=<dataSource>,cFReferenceData
Deribit:
-Dspring.profiles.active=<dataSource>,dRBReferenceData
233
CONFIDENTIAL
Enigma:
-Dspring.profiles.active=<dataSource>,eGMReferenceData
eToroX:
-Dspring.profiles.active=<dataSource>,eTXReferenceData
Huobi Spot:
-Dspring.profiles.active=<dataSource>,hBIReferenceData
InteractiveBrokers:
-Dspring.profiles.active=<dataSource>,iBReferenceData
Kraken Spot:
-Dspring.profiles.active=<dataSource>,kKSReferenceData
OKEx/OKCoin:
-Dspring.profiles.active=<dataSource>,oKXReferenceData
Tilde:
-Dspring.profiles.active=<dataSource>,tLDReferenceData
CryptoFinance:
-Dspring.profiles.active=<dataSource>,cFReferenceData
Enigma:
-Dspring.profiles.active=<dataSource>,eGMReferenceData
LMAX Digital:
-Dspring.profiles.active=<dataSource>,lMAXDReferenceData
OKEx:
-Dspring.profiles.active=<dataSource>,oKEXReferenceData
234
CONFIDENTIAL
OKCoin:
-Dspring.profiles.active=<dataSource>,oKCoinReferenceData
Trading Technologies:
-Dspring.profiles.active=<dataSource>,tTReferenceData
Note
When running a strategy in distributed mode that requires reference data service, a special
referenceData profile must be specified on the strategy side.. In addition an actual historical
data profile (e.g. iBReferenceData) must be specified on the server side.
-Dspring.profiles.active=live,referenceData
235
Chapter 21. CONFIDENTIAL
Account Data
AlgoTrader provides Account Data Service for the following adapters:
1
https://github.com/binance-exchange/binance-java-api
2
https://docs.bitfinex.com/docs
3
https://bitflyer.com/api
4
https://github.com/bithumb-pro/bithumb.pro-official-api-docs
5
https://www.bitmex.com/app/apiOverview
6
https://bittrex.github.io/api/v1-1
7
https://www.bitstamp.net/api/
8
https://docs.pro.coinbase.com/
9
https://docs.deribit.com/v2/
10
https://etorox.github.io/docs/#/README
11
https://docs.gemini.com/rest-api/
12
https://huobiapi.github.io/docs/spot/v1/en/#introduction
13
https://docs.kraken.com/websockets/
14
https://www.kraken.com/features/api
15
https://www.okex.com/docs/en/
16
https://www.okcoin.com/docs/en/
236
CONFIDENTIAL
Depending on the Account Data Adapter in use the corresponding account profile has to be specified via VM
argument.
InteractiveBrokers:
-Dspring.profiles.active=iBAccount
Binance:
-Dspring.profiles.active=bNCAccount
Bitfinex:
-Dspring.profiles.active=bFXAccount
Bitflyer:
-Dspring.profiles.active=bFLAccount
BitHumb Pro:
-Dspring.profiles.active=bHBAccount
BitMEX:
-Dspring.profiles.active=bMXAccount
Bitstamp:
-Dspring.profiles.active=bTSAccount
Bittrex:
-Dspring.profiles.active=bTXAccount
Coinbase Pro:
-Dspring.profiles.active=cNBAccount
Deribit:
-Dspring.profiles.active=dRBAccount
Gemini:
237
CONFIDENTIAL Account balances
-Dspring.profiles.active=gMNAccount
Huobi Spot:
-Dspring.profiles.active=hBIAccount
Kraken Spot:
-Dspring.profiles.active=kKSAccount
OKEx:
-Dspring.profiles.active=oKEXAccount
OKCoin:
-Dspring.profiles.active=oKCoinAccount
Note
When running a strategy in distributed mode in case that requires account data service, a special
account profile must be specified on the strategy side. In addition an actual historical data profile
(e.g. iBAccount) must be specified on the server side.
-Dspring.profiles.active=live,account
21.2. Withdrawal
The AccountService interface defines a method to initiate a crypto withdrawal for crypto exchanges. The
withdraw method can be called from the strategy like this:
238
CONFIDENTIAL Deposit address
The withdrawContext parameter contains additional information that might be required by certain exchanges
(e.g. address and/or paymentId). The method returns a WithdrawStatusVO which contains information like
message and externalId.
For withdrawal operations exchanges typically require additional security constraints, which might include:
• IP address whitelisting
• Email confirmation
Please consult the corresponding exchange's documentation about the details on how to enable withdrawals.
Note
Typically each adapter has a configurable list of supported currencies, for example for Bitfinex
this list is configured in conf-bfx.properties file. This is adapter specific, but often a
withdrawal operation is only allowed if the currency is explicitly listed (please check the
corresponding adapter section).
This returns the deposit address for an exchange, currency and wallet type (wallet type is required for Bitfinex
only). It returns the value as a String. Please check the exchange documentation on how to create deposit
addresses. The getDepositAddress method sends the request to an enabled exchange (see Section 26.2,
“Spring Profiles”). If the requested exchange profile is not present, an exception is thrown. Some exchanges
support different currencies (please check the corresponding adapter section).
239
CONFIDENTIAL Account Events
getAccountService().subscribeAccountEvent(accountId);
The AccountEventVO has a method getAccountBalances which returns the received balances.
List<NamedCurrencyAmountVO> getAccountBalances();
Unlike the retrieveAccountBalances which always return all balances, the account update event may contain
only the balance which has changed.
Note
Subscription for account events is supported only by selected exchanges (please check the
corresponding adapter section).
240
Chapter 22. CONFIDENTIAL
AlgoTrader API
The following sections describe how the AlgoTrader system can be accessed by external systems.
Using the JSON messages in combination with the AlgoTrader REST API and WebSocket/STOMP API any
popular development language can be used to build trading strategies making use of the AlgoTrader platform,
for example:
• C#
• C++
• Python
• R
• MatLab
• JavaScript / NodeJS
HTTP GET endpoints can easily be queried via the Browser. To retrieve a JSON formatted list of all accounts
open to the following URL in the Browser:
http://localhost:9090/rest/account
2
In addition one can use Curl , a popular utility for execution of HTTP requests. The following example shows
how to retrieve a JSON formatted list of all accounts by executing HTTP GET request:
1
http://doc.algotrader.com/apidocs/index.html
2
https://curl.haxx.se/
241
CONFIDENTIAL WebSocket/STOMP API
[{"id":100,"name":"IB_NATIVE_TEST","active":true,"adapterType":"IB",...},
{"id":101,"name":"IB_FIX_TEST","active":false,"adapterType":"IB",...},
{"id":103,"name":"DC_TEST","active":false,"adapterType":"DC",...},
{"id":104,"name":"JPM_TEST","active":false,"adapterType":"JPM",...},
{"id":105,"name":"RT_TEST","active":false,"adapterType":"RT",...},
{"id":106,"name":"LMAX_TEST","active":true,"adapterType":"LMAXG",...},
{"id":107,"name":"FXCM_TEST","active":false,"adapterType":"FXCM",...},
{"id":108,"name":"CNX_TEST","active":false,"adapterType":"CNX",...}]
Similarly one can request AlgoTrader to subscribe to market data for security with id 11 by executing HTTP
PUT request:
AlgoTrader publishes events to multiple predefined event topics. Note: for each topic AlgoTrader creates
additional topic related to particular strategy,order,instrument.
For exmaple: all ticks for security with ID 53 are published to topic tick.53, for instrument ID 46: tick.46
To receive all the ticks one need to subscribe for topic tick.>
You can see all available topics and description of its content via Rest request, e.g. if you have AlgoTrader
running on your local machine: http://localhost:9090/stomp-info.html)
Some topics are listed below. Please note: content can be either of class specified below or a subclass. See
4
more details in apidocs )
3
https://stomp.github.io/
4
https://doc.algotrader.com/apidocs/index.html#syntax_json
242
CONFIDENTIAL WebSocket/STOMP API
/topic/ib-generic-event.<StrategyName>.<EventId> IBGenericTickVO
/topic/order-request-result.<StrategyName>.<OrderId> OrderRequestStatusEventVO
/topic/tick.<security_id> TickVO
/topic/market-data- MarketDataSubscriptionVO
subscription.<strategy_name>.<security_id>.<adapter_type>
/topic/log-event.<LogLevel> LogEventVO
/topic/quote.<QuoteId> SingleQuoteEventVO
/topic/aggregated-order-book.<BookSymbol> AggregatedOrderBookVO
/topic/transaction.<strategy_name>.<uuid> TransactionVO
/topic/algo-order- AlgoOrderStateVO
state.<StrategyName>.<AlgoOrderIntId>
/topic/position.<strategy_name>.<id> PositionVO
/topic/order.<strategy_name>.<order_int_id> OrderVO
/topic/order-status.<strategy_name>.<order_int_id> OrderStatusVO
/topic/cash-balance.<strategy_name>.<id> CashBalanceVO
/topic/order-book.<SecurityId> OrderBookVO
/topic/bar.<SecurityId> BarVO
/topic/account-event.<account_id> AccountEventVO
TickVO
{
"dateTime": 1585146085447,
"adapterType": "CNB",
"securityId": 854,
"last": 6607.47,
"lastDateTime": 1585146083014,
"bid": 6606.2,
"ask": 6607.47,
"volBid": 0.0018634,
"volAsk": 0.91054995,
"vol": 36881.57425883,
"objectType": "TickVO",
"currentValue": 6606.84
}
243
CONFIDENTIAL WebSocket/STOMP API
SingleQuoteEventVO
{
"id": 574,
"intId": "546",
"extId": "Asde",
"side": "BUY",
"bidPx": 86.99,
"bidSize": 1200000,
"askPx": 87.22,
"askSize": 1800000,
"dateTime": 1585141115408,
"validUntil": 1585145145648,
"quoteRequestId": 2136068173,
"securityId": 184,
"accountId": 19544,
"objectType": "SingleQuoteEventVO"
}
{
"id": 520434899,
"intId": "43563564",
"extId": "rwAXs",
"parentIntId": "56434",
"dateTime": 1585145145648,
"side": "SELL_SHORT",
"quantity": 6859,
"tif": "FOK",
"tifDateTime": 1585145145648,
"exchangeOrder": false,
"exchangeId": 1651,
"parentOrderId": 433384635,
"securityId": 1132,
"accountId": 12971,
"strategyId": 21,
"lastStatus": "EXECUTED",
"objectType": "MarketOrder"
}
244
CONFIDENTIAL WebSocket/STOMP API
OrderStatusVO
{
"id": 627598574,
"dateTime": 1585145145648,
"extDateTime": 1585145145648,
"status": "EXECUTED",
"filledQuantity": 1298227,
"remainingQuantity": 0.0,
"lastQuantity": 100000,
"avgPrice": 363.62,
"lastPrice": 363.02,
"intId": "1254",
"extId": "aret",
"sequenceNumber": 134,
"reason": "",
"orderId": 2063904335,
"objectType": "OrderStatus"
}
OrderBookVO
{
"dateTime": 1585146085447,
"adapterType": "CNB",
"securityId": 854,
"id": 0,
"bids": {
"6606.20": {
"price": 6606.2,
"amount": 0.0018634,
"count": 0
},
"6605.58": {
"price": 6605.58,
"amount": 0.25,
"count": 0
},
"6494.51": {
"price": 6494.51,
"amount": 0.001,
245
CONFIDENTIAL WebSocket/STOMP API
"count": 0
}
},
"asks": {
"6607.47": {
"price": 6607.47,
"amount": 0.91054995,
"count": 0
},
"6607.48": {
"price": 6607.48,
"amount": 0.08698364,
"count": 0
},
"6607.89": {
"price": 6607.89,
"amount": 0.1973434,
"count": 0
},
"6649.94": {
"price": 6649.94,
"amount": 0.01,
"count": 0
}
},
"objectType": "OrderBook",
"currentValue": 6606.84
}
Topics are organized by name spaces. A consumer wishing to receive market data for security with id 12 only
can subscribe to the following topic:
/topic/tick.12
A consumer wishing to receive market data all securities can subscribe to the following wild card topic.
/topic/tick.*
Strategy specific events are organized by strategy name. A consumer wishing to receive order status updates
for the order with internal id 10 issued by strategy MY_STRATEGY can subscribe to the following topic
/topic/order-status.MY_STRATEGY.10
A consumer wishing to receive order status updates for all orders issued by strategy MY_STRATEGY can
subscribe to the following wild card topic
246
CONFIDENTIAL WebSocket/STOMP API
/topic/order-status.MY_STRATEGY.*
The * wild card selects all elements within the same namespace
A consumer wishing to receive order status updates for all orders of all strategies can subscribe to the following
wild card topic
/topic/order-status.>
The > wild card selects all topics within the same namespace and their sub-namespaces.
In order to ensure optimal performance of HTML5 clients AlgoTrader can throttle market data event delivered
by the WebSockets transport. The embedded message broker by default attempts to ensure that the total rate
of events per connection does not exceed 50 per second. At the same time instruments with infrequent market
data updates are not throttled if their total event rate is below 0.1 per second (less that one event every 10
seconds).
activeMQ.maxRatePerConnection = 50
activeMQ.minRatePerConsumer = 0.1
activeMQ.stomp.port = 61617
<html>
<head>
<script src="https://unpkg.com/@stomp/[email protected]/lib/stomp.min.js"></script>
<script type="text/javascript">
var ws = new WebSocket("ws://localhost:61614", "stomp");
var stompClient = Stomp.over(ws);
stompClient.connect({}, function(frame) {
stompClient.subscribe('/topic/tick.*', function(message){
console.log(JSON.parse(message.body));
});
});
</script>
</head>
</html>
5
For further details please visit the STOMP JavaScript documentation .
5
http://jmesnil.net/stomp-websocket/doc/
247
CONFIDENTIAL WebSocket/STOMP API
AlgoTrader supports STOMP over normal TCP connections. It designed initially for Python clients.
import time
import sys
import stomp
class MyListener(stomp.ConnectionListener):
def on_error(self, headers, message):
print('received an error "%s"' % message)
def on_message(self, headers, message):
print('received a message "%s"' % message)
hosts = [('localhost', 61618)]
conn = stomp.Connection(host_and_ports=hosts)
conn.set_ssl(for_hosts=hosts)
conn.set_listener('', MyListener())
conn.start()
print('started')
conn.connect( )
time.sleep(10000)
conn.disconnect()
To consume messages from java program the following code snippet provides details:
import org.apache.activemq.transport.stomp.Stomp;
import org.apache.activemq.transport.stomp.StompConnection;
import org.apache.activemq.transport.stomp.StompFrame;
import org.json.JSONObject;
while (true) {
248
CONFIDENTIAL Inbound FIX API
connect = connection.receive();
Example output:
Tick message:
{content-length=227, expires=0, destination=/topic/tick.1239,
priority=4, message-id=ID:DESKTOP-TE1MV6G-59998-1584355272592-4:1:10:1:7917,
persistent=true, timestamp=1584356107716}
Content:
{"dateTime":1584356107715,"adapterType":"CNB","securityId":1239,"last":139.38,"lastDateTime":1584
Order status changes from the broker/exchange are then forwarded back to the external FIX client. This
mechanism allows using the industry standard FIX API for order management via all trading adapters
AlgoTrader provides. Thus also for exchanges or brokers that do not natively support FIX.
The following is an example of the QuickFixJ config (fix.cfg) that you can use to make the Inbound FIX API
available.
249
CONFIDENTIAL Inbound FIX API
[session]
ConnectionType=acceptor
StartTime=00:00:00
EndTime=00:00:00
HeartBtInt=30
SenderCompID=AT
TargetCompID=BANZAI
# FIX client should have those 2 in reverse order:
# SenderCompID=BANZAI
# TargetCompID=AT
UseDataDictionary=Y
DataDictionary=inboundfix/FIX44.xml
FileStorePath=files/fix
FileLogPath=log
BeginString=FIX.4.4
SocketAcceptPort=9880
ValidateIncomingMessage=Y
ResetOnLogon=Y
RefreshOnLogon=Y
You can test AlgoTrader Inbound FIX API using test client (code path: tests/integration/src/main/java/quickfix
6
- based on code of Banzai FIX GUI client ).
The following is an example banzai.cfg config for connecting to locally running AlgoTrader:
[default]
FileStorePath=target/data/banzai
ConnectionType=initiator
SenderCompID=BANZAI
TargetCompID=AT
SocketConnectHost=localhost
SocketConnectPort=9880
UseDataDictionary=Y
DataDictionary=inboundfix/FIX44.xml
StartTime=00:00:00
EndTime=00:00:00
HeartBtInt=30
ReconnectInterval=5
This is an example runner configuration for starting AlgoTrader with Inbound FIX API enabled and connected
to Interactive Brokers:
6
https://github.com/quickfix-j/quickfixj/tree/master/quickfixj-examples/banzai
250
CONFIDENTIAL Inbound FIX API
Note that you can open the HTML5 UI (http://localhost:9090) and the orders you place via Inbound FIX API
will be visible there. QuickFixJ logs with FIX messages between Banzai and AlgoTrader can be found in \log
7
\FIX.4.4-AT-BANZAI.messages.log file. The raw FIX messages can be translated by e.g. FIX decoder .
The protocol version provided by the AlgoTrader Inbound FIX API is FIX 4.4. We use standard messages with
some custom tags and values which are provided below:
• NoRoutingCandidates(20020) - repeating group tag. This group defines routing candidates for smart order
routing.
Note: either SOR must be defined or triplet: {Account, SecurityId, Exchange}, exchange is optional
• Logon (A)
• Logout (5)
• Heartbeat (0)
7
https://drewnoakes.com/fix-decoder/
251
CONFIDENTIAL Logon message
252
CONFIDENTIAL Resend Request message
253
CONFIDENTIAL Order Cancel Request message
254
CONFIDENTIAL Execution Report message
255
CONFIDENTIAL Execution Report message
• F: TRADE, fill
256
Chapter 23. CONFIDENTIAL
Adapters
The following sections give a detailed overview of the different adapters available for AlgoTrader.
To configure a Fix trading connection the following steps have to be taken care of:
• Add the corresponding fix trading profile to the VM argument spring.profiles.active (e.g. cNXFix):
-Dspring.profiles.active=live,pooledDataSource,cNXFix,embeddedBroker,html5,InfluxDB
[session]
SessionQualifier=CNXT
BeginString=FIX.4.4
SenderCompID=xxx
TargetCompID=CNX
SocketConnectHost=dret-fix-ssl.currenex.com
SocketConnectPort=443
SocketUseSSL=Y
Username=xxx
Password=xxx
ValidateIncomingMessage=N
ResetOnLogon=Y
Inactive=Y
• Make sure there is an entry in the MySQL account table where the column ORDER_SERVICE_TYPE matches
the type of the fix interface (e.g. CNX_FIX), the column SESSION_QUALIFIER matches the SessionQualifier
specified in the file fix.cfg and the ACTIVE column is set to 1.
If market data is also received through a Fix interface the following items need to be added as well:
• Add the corresponding fix market data profile to the VM argument spring.profiles.active (e.g. cNXFix):
1
https://www.quickfixj.org/
257
CONFIDENTIAL Fix Interface
-
Dspring.profiles.active=live,pooledDataSource,cNXMarketData,embeddedBroker,html5,InfluxDB
[session]
SessionQualifier=CNXMD
BeginString=FIX.4.4
SenderCompID=xxx
TargetCompID=CNX
SocketConnectHost=dret-fix-ssl.currenex.com
SocketConnectPort=443
SocketUseSSL=Y
Username=xxx
Password=xxx
ValidateIncomingMessage=N
ResetOnLogon=Y
Inactive=Y
• When making subscriptions add the AdapterType corresponding to the Fix interface (e.g. CNX)
Important
Please make sure to have the setting Inactive=Y in both trading and market-data sections.
Without this setting the fix session will be initialized before the remaining system has been fully
initialized and might cause either trading or market data to malfunction.
2
For further information regarding QuickFix/J configuration please visit the QuickFix/J documentation
Per default Fix interfaces uses the following items to identify a particular instrument:
Options
Exchange IB_CODE
Option TRANSACTION_CURRENCY
SecurityFamily SYMBOL_ROOT
Option STRIKE
Option TYPE
Option EXPIRATION
2
https://www.quickfixj.org/usermanual/1.6.4//usage/configuration.html
258
CONFIDENTIAL FIX configuration
Option CONTRACT_SIZE
Future
Future TRANSACTION_CURRENCY
Exchange IB_CODE
SecurityFamily SYMBOL_ROOT
Future EXPIRATION
Future CONTRACT_SIZE
Forex
Forex TRANSACTION_CURRENCY
Exchange IB_CODE
Forex BASE_CURRENCY
Stock
Stock TRANSACTION_CURRENCY
Exchange IB_CODE
Stock SYMBOL
Fund
Fund TRANSACTION_CURRENCY
Exchange IB_CODE
Index SYMBOL
The file fix-template.cfg contains default parameters suggested by AlgoTrader for all FIX sessions. The
individual [session] blocks should be added after the [default] block.
[default]
ConnectionType=initiator
HeartBtInt=30
ReconnectInterval=5
FileStorePath=files/fix
FileLogPath=log
FileLogHeartbeats=N
FileIncludeMilliseconds=Y
259
CONFIDENTIAL FIX logging
FileIncludeTimeStampForMessages=Y
3
For further information regarding QuickFix/J configuration please visit the QuickFix/J documentation
In addition to stock QuickFix/J configuration capabilities AlgoTrader provides a custom option to select a logging
back-end out of those supported by QuickFix/J per individual session through custom Logimpl parameter.
file (default)
Log to QuickFix/J standard file logger.
The file option (which is the default) will create fix log files in the log sub-directory of the directory where
AlgoTrader was started. One log file will be created for messages and one for QuickFix/J internal events.
The name of both files contains the full FIX session name. To use the file logger the following settings are
required within the fix.cfg file:
FileLogPath=log
FileLogHeartbeats=N
FileIncludeMilliseconds=Y
FileIncludeTimeStampForMessages=Y
none
Disable logging. No FIX session events or messages will be logged.
The none option might be especially useful for volume intensive market data sessions where persistent
message log could be unnecessary or even excessive. Custom Fix logging options can be configured as
follows:
[session]
SessionQualifier=FIXMD
BeginString=FIX.4.4
...
LogImpl=none
screen
Logs all QuickFix/J events and messages to the standard console logger.
3
https://www.quickfixj.org/usermanual/1.6.4//usage/configuration.html
260
CONFIDENTIAL FIX logging
slf4j
Log to the Simple Logging Facade for Java (SLF4J). Log entries will be committed to the logging back-
end configured by SLF4J.
The slf4j allows log messages to be re-directed to the Log4J Chapter 30, Logging system which is highly
configurable. Here is an example:
[session]
SessionQualifier=FIXMD
BeginString=FIX.4.4
...
LogImpl=slf4j
It is also possible to customize the log categories per session for added flexibility. It is for example possible
to log FIX messages from different FIX sessions into separate Files. The following example has two
sessions, one for market data (FIXMD) and one for trading (FIXORD).
[session]
SessionQualifier=FIXMD
BeginString=FIX.4.4
...
LogImpl=slf4j
SLF4JLogIncomingMessageCategory=quickfixj.msg.md.incoming
SLF4JLogOutgoingMessageCategory=quickfixj.msg.md.outgoing
[session]
SessionQualifier=FIXORD
BeginString=FIX.4.4
...
LogImpl=slf4j
261
CONFIDENTIAL FIX message persistence
SLF4JLogIncomingMessageCategory=quickfixj.msg.ord.incoming
SLF4JLogOutgoingMessageCategory=quickfixj.msg.ord.outgoing
By adding the following sections to the log4j2.xml separate log files for market data (fix-md.log) and
trading (fix-ord.log) will be created.
...
<RollingFile
name="FixMD"
fileName="log/fix-md.log"
filePattern="log/fix-md-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern="%d %m %n"/>
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="250 MB"/>
</Policies>
</RollingFile>
<RollingFile
name="FixORD"
fileName="log/fix-ord.log"
filePattern="log/fix-ord-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern="%d %m %n"/>
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="250 MB"/>
</Policies>
</RollingFile>
...
<logger name="quickfixj.msg.md" level="info" additivity="false">
<AppenderRef ref="FixMD"/>
</logger>
<logger name="quickfixj.msg.ord" level="info" additivity="false">
<AppenderRef ref="FixORD"/>
</logger>
For both files a daily rolling file scheme is used where at the end of a day all contents of each file will be
zipped (e.g. fix-md-12-08-2019.log.gz). In addition if the file size reaches 250MB a new zip file will be
created as well.
One can use standard QuickFix/J facilities to store FIX messages either in a local file or in a relational database
through JDBC DataSource interface. For details please refer to the QuickFix/J documentation. For further
4
details please visit the QuickFix/J documentation
4
https://www.quickfixj.org/usermanual/1.6.4//usage/configuration.html#Storage
262
CONFIDENTIAL FIX Drop-copy support
When trading crypto currencies it is recommended to update the following properties inside conf.properties.
Alternatively the properties can be changed via Section 2.4, “VM Options”:
This will cause all balances to be displayed in BTC with a precision of 8 digits
Crypto reference data services set these values provided this information is made available by the exchange.
The crypto-adapters validate orders versus these constraints and reject them before sending them to the
exchanges/brokers.
263
CONFIDENTIAL Supported Crypto-Security Types
• MinNotional - minimum notional value of the order. For example for limit order: Quantity * Limit price
Securities are updated automatically if there is a change on the exchange side. To change this behaviour (not to
override those constraints), the user has to set the corresponding property inside the adapter specific property
file (e.g. inside the conf-bmx.xml file for the BMX adapter). Alternatively the properties can be changed via
Section 2.4, “VM Options”:
Check the corresponding crypto-adapter sections below on what constraints are validated for each broker/
exchange.
264
CONFIDENTIAL Supported Crypto-Order Types
The following table contains the valid order types per adapter
265
CONFIDENTIAL
Supported Crypto Adapter Account Functionality
266
CONFIDENTIAL Session life-cycle events
order to ensure stable connectivity with the exchange by, AlgoTrader outgoing HTTP calls are limited. Request
rate is configurable by properties.
xyz.rateLimits = 100/1s,1000/1m
The above example means that adapter xyz allows 100 requests per second, but no more than 1000 requests
per minute.
• s (seconds)
• m (minutes)
• h (hours)
• d (days)
Rate-limit examples:
Note
AlgoTrader comes with predefined rate-limit values and there is no need to override them unless
the exchanges have changed their limits of you have more restrictive requirements.
@Override
public void onSessionEvent(final SessionEventVO event) {
switch (event.getState()) {
case CONNECTED:
// session connected but not yet authenticated
break;
case LOGGED_ON:
// session connected and authenticated
267
CONFIDENTIALAutomatic order reconciliation after re-connect
break;
case DISCONNECTED:
// session disconnected
break;
}
}
Specially when connecting to a slow Market Data adapters it might be necessary to listing to those session
events and only subscribe for securities once the session is in the LOGGED_ON state.
For this purpose AlgoTrader provides an automatic order reconciliation feature. An automated order
reconciliation process is invoked once the AlgoTrader server reconnects to synchronize the orders statuses
between the exchange on the AlgoTrader server.
In case of trading adapters that use FIX interface, order reconciliation is provided automatically by the exchange
FIX server. This is done using the Resend FIX protocol message. Unfortunately the Resend message is not
supported by the Coinbase Pro exchange FIX server and BitStamp FIX server. Both adapters use AlgoTrader
provided order reconciliation via Rest on their FIX session reconnect.
In case you want to turn off the AlgoTrader provided order reconciliation, add noOrderReconciliation into
active Spring profiles list when starting the AlgoTrader server.
Please check the corresponding adapter section to see if the automatic order reconciliation is implemented
for your exchange.
If your Strategy relies on reconciliation process and required information about whether it is currently running or
not, it is possible to subscribe for ReconciliationEvents. After subscription, your Strategy will be notified about
reconciliation process being started and finished. Code example below shows how to subscribe to such events
from your StrategyService class:
@Override
protected void onReconciliationEvent(final ReconciliationEventVO event) {
// place code that reacts on reconciliation events here
}
One example use case that you can implement with such reconciliation events is state recovery processing
after AlgoTrader was stopped and started (it is recommended to wait until reconciliation is finished and all order
statuses are updated before starting your regular Strategy process)
268
CONFIDENTIAL Bloomberg
23.6. Bloomberg
The Bloomberg adapter supports Market Data, Historical Data as well as Reference Data.
The Bloomberg adapter provides both synchronous connections and asynchronous connections.
Asynchronous connections are generally used for live market data whereas synchronous connections are used
for retrieval of historical data as well as retrieval of reference data.
If market data is received through the Bloomberg interface the following items need to be added:
-
Dspring.profiles.active=live,pooledDataSource,bBMarketData,embeddedBroker,html5,InfluxDB
Bloomberg uses the BBGID field of the Security table to identify instruments.
5
For further details on the Bloomberg interface please visit the Bloomberg Open API
AlgoTrader Tradebook adapter allows access to Bloomberg Tradebook via FIX API. Execution algo orders,
'benchmark strategy orders' as they are called by Bloomberg can be used by the usual OrderService
methods with custom FIX tags specified using order object properties (see Section 17.2.3, “Order Properties”).
Tradebook adapter has convenience Tradebook adapter specific methods available for TWAP, VWAP and Go
Along benchmark strategy orders.
((TDBOrderServiceImpl)
orderService.getExternalOrderService(AdapterType.TDB)).sendTradebookVWAPOrder(...);
23.8. Currenex
The main features of the Currenex platform are
5
https://www.bloomberg.com/professional/support/api-library/
6
https://www.bloomberg.com/professional/solution/tradebook/
269
CONFIDENTIAL DukasCopy
• Uses FOREX_MARKET (type C) and FOREX_LIMIT (type F) for Market and Limit orders
Currenex uses the columns Forex BASE_CURRENCY and SecurityFamily CURRENCY to identify an instrument.
23.9. DukasCopy
AlgoTrader supports both trading and market data connectivity via broker DukasCopy.
Since the DukasCopy FIX protocol implementation does not follow the FIX standard very closely, we at the
moment don't support order modifications via Dukascopy trading adapter. Modification of an open order can
be achieved by cancelling and submitting a new order.
Exante provides its customers with a demo platform with the same characteristics as the live platform. Market
data in the Demo platform is delayed by at least 30 minutes. Live platform requires setting up an SSH tunnel,
details for which are available at their website.
Reference data download is currently not supported by AlgoTrader. Individual securities may be enabled on
AlgoTrader side for use with Exante by setting their XNTID database field with the correct Exante instrument
code.
The EzeSoft / RealTick Fix interface currently supports only Order Processing.
The Fix Implementation of EzeSoft / RealTick is well conforming with the Fix Standard no customizations had
to be made.
270
CONFIDENTIAL Fortex
The Fix interface uses standard Fix instrument definitions mentioned at the end of section Section 23.1, “Fix
Interface”.
23.12. Fortex
Fortex uses almost vanilla Fix/4.4 protocol with very few customizations. It supports FX only.
23.13. FXCM
FXCM interface FIX/4.4 protocol does not deviate much from the standard but has some peculiarities about
the way FIX sessions are established
• Unlike many other FIX connectivity providers who provide separate FIX sessions for market data and trading
interfaces FXCM by default offers one session for both market data feed and trading operations
• Uses extra UserRequest / UserResponse message exchange to authenticate the user and to fully initialize
the session
FXCM uses the columns Forex BASE_CURRENCY and SecurityFamily CURRENCY to identify an instrument.
The IB interface supports Market Data, Historical Data, Order Processing, Retrieval of account information as
well as Reference Data.
Note
connectivity via TWS is generally preferred. You can still use IBGateway for connectivity if you
choose to do it, but you should override this config property so that AT is aware of it (this is
important because execution flow is different between IBGateway and TWS in some cases):
ib.ibType=IBGateway
Note
You get market data for a minimum of 100 instruments with subscriptions (depends on your
commissions and assets with IB). You can buy up to 10 quote boosters for USD 30 each, which
271
CONFIDENTIAL IB Native Interface
provide 100 additional instruments each (max 1000). For details, consult the IB market data
7
fees.
8
Similar restrictions/extensions exist for historical data. Those details can be viewed here.
-
Dspring.profiles.active=live,pooledDataSource,iBNative,embeddedBroker,html5,InfluxDB
• Make sure there is an entry in the account database where the column ORDER_SERVICE_TYPE is set to
IB_NATIVE) .
If market data is also received through the IB interface the following items need to be added as well:
-
Dspring.profiles.active=live,pooledDataSource,iBMarketData,embeddedBroker,html5,InfluxDB
• Use instrument symbols and additional data depending on the instrument type:
Options
Exchange IB_CODE
SecurityFamily CURRENCY
SecurityFamily SYMBOL_ROOT
Option STRIKE
Option TYPE
Option EXPIRATION
SecurityFamily CONTRACT_SIZE
Future
SecurityFamily CURRENCY
7
https://www.interactivebrokers.com/en/index.php?f=14193#market-data-fees
8
http://interactivebrokers.github.io/tws-api/historical_limitations.html#hd_availability
272
CONFIDENTIAL IB Native Interface
Exchange IB_CODE
SecurityFamily SYMBOL_ROOT
Future EXPIRATION
SecurityFamily CONTRACT_SIZE
Stock
SecurityFamily CURRENCY
Exchange IB_CODE
Stock SYMBOL
Index
SecurityFamily CURRENCY
Exchange IB_CODE
Index SYMBOL
Combination
SecurityFamily CURRENCY
Exchange IB_CODE
SecurityFamily BASE_SYMBOL
Component QUANTITY
9
• The IB Native interface uses the RT_VOLUME events to process incoming trade events
• The IB Native interface propagates daily OPEN and CLOSE prices to strategies in case the following property
inside conf-ib.properties is enabled. Alternatively the properties can be changed via Section 2.4, “VM
Options”
• The IB Native interface propagates VWAP prices to strategies in case the following property inside conf-
ib.properties is enabled. Alternatively the properties can be changed via Section 2.4, “VM Options”
9
https://interactivebrokers.github.io/tws-api/tick_types.html#rt_volume
273
CONFIDENTIAL IB TWS/Gateway Shutdown/Restart
ib.emitVWAP = true
• The IB Native interface expects orders to be sent with their order ids in ascending order. The Class
IBOrderIdSynchronizer is responsible to make sure order ids are actually in ascending order. In case an
order id is skipped the IBOrderIdSynchronizer will wait for up to maxOrderSyncTime milliseconds for the
order with the correct order id to arrive.
• The IB Native interface supports trading of tradable / non-synthetic combinations by placing BAG orders
through the IB interface.
• The IB Native interface reports volBid, volAsk and vol in lots of 100 contracts for US equities. Please see
10
the following page for further details on handling of Odd Lot Orders
11
For further details on the IB native interface please visit the IB API Reference Guide
If you want to run a strategy continuously, you have the option to configure a daily restart time as per these
12
instructions .
Note that you will still have to re-enter your IB password on Sundays (the restart needs manual input once a
13
week) and there are other limitations, which could cause the restart to fail. See the IB notes on auto-restart .
IB provides free 15min delayed data. It is possible to obtain this free 15min delayed data when logged in
via a trial account. This however is available only when logged in via Trader Workstation (TWS). Please see
Section 23.14.3, “Delayed IB Market Data”
Market data can be accessed both through the IB paper trading account as well as the live trading account.
Note
• The paper trading account has one single username assigned to it. The live trading account
can have multiple user names.
10
https://ibkr.info/node/1062
11
https://www.interactivebrokers.com/en/software/api/api.htm
12
https://www.interactivebrokers.com/en/software/tws/usersguidebook/configuretws/configurelockandexit.htm
13
https://www.interactivebrokers.com/en/software/tws/usersguidebook/configuretws/auto_restart_info.htm
274
CONFIDENTIAL IB Market Data Subscriptions
• For each username (live account & paper trading account) only one session can exist at the
same time. If you login with the same username on a different machine the other session
will get logged out.
• If the live account username (that is sharing its market data subscription with the paper trading
account) is currently logged in, the paper trading account doesn't get market data until the
live account is again logged out.
• If a client wants to login to the live trading account at the same time that AlgoTrader is
connected to the paper trading account, he has to create a second username under the live
account and purchase additional market data subscriptions for that username.
14
To get a market data subscriptions one has to login to the IB account management with the live trading
account. Then follow these steps:
1. Select Settings / User Settings in the menu on the left. Then select Market Data Subscriptions on the right
14
https://gdcdyn.interactivebrokers.com/sso/Login
275
CONFIDENTIAL IB Market Data Subscriptions
• NASDAQ (Network C/UTP): live market data for NASDAQ listed equities
• NYSE (Network A/CTA): live market data for NYSE listed equities
• US Securities Snapshot and Futures Value Bundle: live market data for US futures and snapshot data
for US equities (AT cannot process snapshot data, so in addition NASDAQ and NYSE has to be subscribed
as well)
276
CONFIDENTIAL IB Market Data Subscriptions
To use these market data subscriptions through the paper trading account follow these steps:
1. Select Settings / User Settings in the menu on the left. Then select Paper Trading Account on the right
2. Then select Yes next to Share real-time market data subscriptions with paper trading account
3. Then Select the username whose market data you want to share. This will share the market data
subscriptions of the live account with the paper trading account.
277
CONFIDENTIAL Delayed IB Market Data
Note
In case no market data arrives through the IB interface it is usually best to login to
InteractiveBrokers Trader Workstation (TWS) as there are usually warning messages that
indicate what might be the issue
• TWS needs to be used. IB Gateway is not supported for free delayed market data
• Delayed market data subscriptions are available with trial accounts only. After starting the TWS, simply go
to Return to the demo and enter your email address (see screen shot below)
278
CONFIDENTIALCustom functions in IB Native Account adapter
• Similarly to IB Gateway, TWS should be configured to work with AlgoTrader: After logged in, go to Edit -
> Global Configuration... -> API -> Settings. Make sure following settings are used: Enable ActiveX and
Socket Clients should be enabled, Read-Only API should be disabled, Socket port should be set to 4001.
279
CONFIDENTIALCustom functions in IB Native Account adapter
Accounts Retrieval
Allows a financial advisor to retrieve the list of accounts in an account group.
Set<String> accounts =
((IBNativeAccountService) accountService
.getExternalAccountService(/*account group*/)
.getAccounts();
Set<String> managedAccounts =
((IBNativeAccountService) accountService
.getExternalAccountService(/*account number*/)
.getManagedAccounts();
List<SecurityPositionVO> positions =
((IBNativeAccountService) accountService
.getExternalAccountService(/*account number/account group/allocation
profile*/)
.retrieveAccountPositions(accountId);
((IBNativeAccountService) accountService.getExternalAccountService(/*allocation
profile name*/)
.updateAllocationProfile(Profile profile, int type);
280
CONFIDENTIAL IB Generic Tick Events
As IBGenericTickVO is a subclass of MarketDataEventVO a strategy will automatically get Generic Tick Events
delivered when it has subscribed to the corresponding instrument.
A Generic Tick has a TickType which can be one of OPEN, HIGH, LOW, CLOSE, SETTLEMENT, OPEN_INTEREST,
IMBALANCE or VWAP. A Generic Tick Event can hold either a BigDecimal, Double or Integer value.
The interface is fully capable of handling IB's Financial Advisor functionality like Sub Accounts, Account Groups
and Allocation Profiles.
15
For further details on the IB Fix interface please visit the IB FIX/CTCI Users' Guide
The IB Fix interface uses standard Fix instrument definitions mentioned at the end of section Section 23.1,
“Fix Interface”.
It can be enabled by activating the profile iNTRDividendGenericEvents and by setting the following property
in conf-intr.properties:
intr.apiKey = XXXX
23.17. JP Morgan
The JP Morgan Fix interface supports Order Processing only.
As the JP Morgan Fix Implementation is well conforming with the Fix Standard no customizations had to be
made
The JP Morgan Fix interface uses standard Fix instrument definitions mentioned at the end of section
Section 23.1, “Fix Interface”.
15
https://www.interactivebrokers.com/en/index.php?f=4988
16
https://intrinio.com/
281
CONFIDENTIAL LMAX Global
• Uses predefined contract modifiers for market data events and order quantities. The contract modifiers are
not included in FIX messages and have to be applied by the interface adapter.
• Supports DAY, GTC, IOC and FOK time-in-force parameters for market and limit orders.
• Supports only DAY and GTC time-in-force parameters for stop orders (stop and stop-limit).
• supports trading status signaling temporary suspension and resumption in trading of individual securities.
LMAX Global uses the column LMAXID of the security table to identify an instrument
• Orders cannot be modified, instead one needs to cancel the current order first and then resend a new one.
• Buy limit orders need to be placed below the market price. Sell limit orders need to be placed above the
market price
• Buy stop orders need to be placed above the market price. Sell stop orders need to be placed below the
market price.
• Minimum trade size allowed on most currency pairs is .01 lots which is 1000 notional
Nexus Prime uses the columns Forex BASE_CURRENCY and SecurityFamily CURRENCY to identify an
instrument.
OneZero Financial Systems LLC develops low-latency software systems. The Company provides traders,
managers, and brokers with software tools to identify market opportunities, automate their trading, and control
risk.
17
https://www.isriskanalytics.com/trading-technology/
282
CONFIDENTIAL PrimeXM
One Zero implements the FIX/4.4 protocol and requires to use TLSv1:
EnabledProtocols=TLSv1
23.21. PrimeXM
The PrimeXM FIX/4.4 interface implementation follows the Fix Standard closely, but uses MassQuote messages
for conveying the market data. Each MassQuote message has to be acknowledged by the FIX client.
Market, limit and stop orders are supported but only with time in force IOC (Instant or Cancel) or FOK (Fill or Kill).
23.22. Quandl
18
Quandl is a public service that provides a wide range of financial, economic and alternative data. It is mostly
end of day data but also some intra-day (e.g. hourly) data. To find out if they have what you are looking for, check
19
their data products page. AlgoTrader allows downloading historical data from Quandl. For more information
20
about Quandl please have a look at the Quandl Docs/Help .
Data on Quandl is divided into databases. Each database contains multiple datasets. For instance EOD
database contains end-of-day data for all publicly-traded US stocks. Each database/dataset pair is uniquely
identified by database_code/dataset_code pair. For instance EOD/AAPL is the globally unique code for the
21
AAPL stock dataset within the EOD database. The Quandl database browser can be used to find suitable
databases for desired instrument type, region and data type.
The QdlHistoricalDataService is integrated with the AlgoTrader Historical Data Download and needs
to be enabled by specifying the qdlHistoricalData Spring profile (see section Section 19.3, “Historical
Data Download”). The QdlHistoricalDataService transforms retrieved Quandl data into AlgoTrader bars.
Transformation rules between the Quandl data format and AlgoTrader Bar format are defined in the file
quandl.yml. By default the file quandl.yml already contains the transformation rules for most commonly used
Quandl databases. Additional transformation rules can be added to the file as needed:
EOD:
barSize: DAY_1
columnMapping:
dateTime: Date
open: Open
high: High
18
https://www.quandl.com/
19
https://www.quandl.com/search?query=
20
https://www.quandl.com/docs-and-help
21
https://www.quandl.com/search
283
CONFIDENTIAL QuantHouse
low: Low
close: Close
vol: Volume
The relevant properties for the Quandl adapter are defined inside the file conf-qdl.properties where they
can be changed. Alternatively the properties can be changed via Section 2.4, “VM Options”:
#{"type":"String","label":"API Key"}
qdl.apiKey = ATVxxxxxxxxxxxxx
To use the QdlHistoricalDataService please replace the property qdl.apiKey with the API Key that can
be retrieved through the Quandl Account Settings.
In terms of historical data download a mapping between the Quandl database and the Security entity is
defined by the quandl_database field in the security table. Similarly a mapping between the Quandl dataset
and the Security entity is defined by the quandl_dataset field in the security table. AlgoTrader sample
data files (samples/db/mysql/mysql-data.sql already contain quandl_database/quandl_dataset values
for all sample security families and most sample securities.
23.23. QuantHouse
The QuantHouse adapter is based on the QuantHouse ultra low latency market data feed QuantFEED. The
QuantHouse adapter supports live Market Data.
If market data is received through the QuantHouse interface the following items need to be added:
-
Dspring.profiles.active=live,pooledDataSource,qHMarketData,embeddedBroker,html5,InfluxDB
QuantHouse uses the Exchange MIC and Security SYMBOL fields to identify instruments.
22
For further details on the QuantHouse interface please contact QuantHouse
22
https://www.quanthouse.com/
284
CONFIDENTIAL SocGen
23
AlgoTrader supports market data using Websocket Api . The availability of data depends on the account held.
The securities need to be in the database and value of the field 'RIC' is used to communicate with Refinitiv.
The properties of the adapter are defined inside the file conf-refinitiv.properties. Alternatively they can
be changed via Section 2.4, “VM Options”
#{"type":"String","label":"API Key"}
refinitiv.apiKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"String","label":"API Secret"}
refinitiv.apiSecret = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
23.25. SocGen
The SocGen FIX/4.2 interface supports Order Processing only.
The SocGen Fix Implementation follows the Fix Standard closely, but some minor customizations according
to the 'SocGen FIX Rules of Engagement' had to be made. Additionally exchange specific restrictions rules
defining the allowed order type / TIF combinations were added.
23
https://developers.refinitiv.com/elektron/websocket-api
285
CONFIDENTIAL Trading Technologies (TT)
Only Future instrument orders are supported by the SocGen Fix Interface.
• Provides a reference data service that can be used to download contract definitions
The relevant properties for TT adapter are defined inside the file conf-tt.properties where they can be
changed. Alternatively the properties can be changed via Section 2.4, “VM Options”:
The tt.username property defines the username on the Trading Technologies side
23.27. UBS
The UBS Fix interface supports Order Processing for futures and options only.
As the UBS Fix Implementation is well conforming with the Fix Standard no customizations had to be made
The UBS Fix interface uses standard Fix instrument definitions mentioned at the end of section Section 23.1,
“Fix Interface”.
23.28. B2C2
B2C2 is a cryptocurrency market maker/OTC trading services provider.
The B2C2 interface supports Market Data, Order Processing, Request for Quote (RFQ) process, Retrieval of
account information as well as Reference Data. B2C2 only allows one RFQ to be in effect at a time and a
second one invalidates the previous.
The relevant properties for the B2C2 adapter are defined inside the file conf-b2c2.properties where they
can be changed. Alternatively the properties can be changed via Section 2.4, “VM Options”:
286
CONFIDENTIAL B2C2 Order Constraints
B2C2 does not have an order book but will stream prices to you at the requested level.
The price levels define the quantity (in base currency) you wish to receive streamed prices for.
Above a certain value (to be agreed with B2C2), you will not be able to execute orders directly but need to
go through the RFQ process.
In order to populate the database with B2C2 Accounts, Exchanges, Security Families and Securities run the
ReferenceDataStarter with b2C2ReferenceData spring profile enabled and program argument: all. For
further details please visit Chapter 20, Reference Data.
Note that time in force (TIF) for B2C2 Previously Indicated orders has to be Immediate or Cancel (IOC) or Fill
or Kill (FOK), and for non RFQ orders only FOK is supported.
23.29. Binance
24 25
Binance is a cryptocurrency exchange. Please see the API reference page for the technical details.
Binance provides Java library for interacting with Binance API. It supports REST requests to endpoint providing
orders functionality, account data and reference data. Support for market data is done using WebSocket API.
The relevant properties for the Binance adapter are defined inside the file conf-bnc.properties where they
can be changed. Alternatively the properties can be changed via Section 2.4, “VM Options”:
#{"type":"String","label":"API Key"}
bnc.apiKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"String","label":"API Secret"}
24
https://www.binance.com/
25
https://github.com/binance-exchange/binance-java-api
287
CONFIDENTIAL Binance Order Constraints
bnc.apiSecret = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
A Binance account is necessary in order to use Binance adapter. Unique apiKey and apiSecret settings must
be set to the actual values (either in the properties file or by setting a VM argument)
Note
Binance is very time sensitive , i.e. if your computer is ahead of the Binance system clock, the
API might reject your orders with an exception similar to
server's time
To prevent these issues, we suggest synchronizing your system clock with an internet reference
26
time using e.g. this time sync tool .
AlgoTrader currently supports market, limit, stop and stop limit orders on Binance.
Note
Note that Binance has restrictions to the amount of (algo) orders that can be placed on an instrument or
27
exchange. See the Binance API filter page for details.
26
http://www.timesynctool.com/
27
https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#filters
288
CONFIDENTIAL Binance Account Management
FunctionalitySupported Features
Withdrawals It is possible to withdraw BTC, ETH, LTC, NEO and BNB. The withdrawal address has to be
provided in withdrawContext. A secondary address identifier for coins like XRP, XMR etc has
to be provided as paymentId in the withdrawContext. The address description is optional.
Deposit It is possible to deposit BTC, ETH, LTC, NEO and BNB. Please check How to Register and
29
Addresses Deposit on Binance on how to query the corresponding addresses
Account Supported
Events
Account Supported.
Balance
Retrieval
23.30. Bitfinex
30
Bitfinex is a cryptocurrency exchange. The Bitfinex adapter provides order execution, market data, reference
31
data and account data functionality. Please see the Bitfinex API reference page for technical details about
the supported features.
The relevant properties for the Bitfinex adapter are defined inside the file conf-bfx.properties where they
can be changed. Alternatively the properties can be changed via Section 2.4, “VM Options”:
#{"type":"String","label":"API Key"}
bfx.apiKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"String","label":"API Secret"}
bfx.apiSecret = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
28
https://www.binance.com/en/trade-rule
29
https://www.binance.com/en/support/articles/115003764971
30
https://www.bitfinex.com/
31
https://docs.bitfinex.com/docs
289
CONFIDENTIAL Bitfinex Order Constraints
#{"type":"Integer","label":"API-level constant'}
bfx.scale = 5
A Bitfinex account is necessary in order to use Bitfinex adapter. Unique apiKey and apiSecret settings must
be set to the actual values (either in the properties file or by setting a VM argument)
Market, limit and stop orders are supported. For exchange account trading, different order types are used
(exchange market, exchange limit and exchange stop).
FunctionalitySupported Features
33
Withdrawals AlgoTrader uses the v1 API. Supported currencies can be found here . The withdrawal
address and payment id have to be provided in the withdrawContext. Bitfinex supports 3 types
32
https://api.bitfinex.com/v1/symbols_details
33
https://docs.bitfinex.com/v1/reference#rest-auth-withdrawal
290
CONFIDENTIAL Bitflyer
FunctionalitySupported Features
of wallets: trading exchange and deposit. The default is exchange. It can be changed in
conf-bfx.properties file.
34
Deposit The available currencies can be found here . Bitfinex supports three types of wallets: trading,
Addresses exchange and deposit. Note that the USDT deposit method only works for verified accounts,
otherwise this methods throws an exception.
Account Supported
Events
Account Supported.
Balance
Retrieval
23.31. Bitflyer
35
Bitflyer is a cryptocurrency exchange. The Bitflyer adapter supports order execution, market data, reference
36
data and account data functionality. Please see the Bitflyer API reference page for technical details.
Note
At this point (April 2018), Bitflyer does not yet support cross-border trading, so trading vs. USD
is only possible with a US account.
The relevant properties for the Bitflyer adapter are defined inside the file conf-bfl.properties where they
can be changed. Alternatively the properties can be changed via Section 2.4, “VM Options”:
#{"type":"String","label":"API Key"}
bfl.apiKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"String","label":"API Secret"}
bfl.apiSecret = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
34
https://api.bitfinex.com/v2/conf/pub:map:currency:label
35
https://bitflyer.com/en-jp/
36
https://bitflyer.com/api
291
CONFIDENTIAL Bitflyer Order Constraints
A Bitflyer account is necessary in order to use Bitflyer adapter. Unique apiKey, apiSecret as well as market
data subscription key settings must be set to the actual values (either in the properties file or by setting a VM
argument)
37
Bitflyer uses different instruments for exchange and margin trading (see Bitflyer margin trading. )
Note
ETH/BTC: 0.01
37
https://lightning.bitflyer.com/About-Fx?lang=en
38
https://bitflyer.com/en-jp/faq/4-5
292
CONFIDENTIAL Bitflyer Account Management
FunctionalitySupported Features
Withdrawals It is possible to withdraw JPY for Japanese accounts, USD for U.S. accounts, and EUR for
European accounts. The bank account id has to be provided in withdrawContext as address
parameter.
Deposit Bitflyer supports BTC, ETH, LTC, BCH, MONA, LSK. Before an address is returned, it needs
Addresses to be enabled/created under the Account Funding section after logging in to the BitFlyer
Web UI.
Account Not supported
Events
Account Supported.
Balance
Retrieval
The relevant properties for the BitHumb adapter are defined inside the file conf-bhb.properties where they
can be changed. Alternatively the properties can be changed via Section 2.4, “VM Options”:
#{"type":"String","label":"REST Url"}
bhb.restUrl = https://global-openapi.bithumb.pro/openapi/v1
#{"type":"String","label":"API Key"}
bhb.apiKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"String","label":"API Secret"}
bhb.apiSecret = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
39
https://www.bithumb.pro/en-us
40
https://github.com/bithumb-pro/bithumb.pro-official-api-docs
293
CONFIDENTIAL BitHumb Pro Order Constraints
A BitHumb account is necessary in order to use the BitHumb adapter. Unique apiKey, apiSecret as well as
market data subscription key settings must be set to the actual values (either in the properties file or by setting
a VM argument)
Minimum and maximum price and quantity increments are security specific and can be looked up in the
Security table after loading the reference data.
Automatic order reconciliation (on WebSocket reconnect) is implemented for BitHumb Pro.
Buy market orders sized in base currency are not supported by the exchange. An example is BTC-
USDT, when buying or selling using a market order in it, the API expects the quantity to be specified
in USDT, not in BTC. The adapter by default works around this by placing a buy limit order above the
current best ask price in order to immediately execute the buy order. A disadvantage of this workaround
is that account balance requirement on order placement is slightly higher than it would be with market
order. Another option is to execute market orders with quantity defined in the secondary currency by
converting the requested base currency amount using the current bid/ask prices. The disadvantage of
this approach is the quantity executed by the exchange is subtracted with fees and the price might
change during execution or on orders with quantity bigger that the relevant order book top level size.
294
CONFIDENTIAL BitHumb Pro Account Management
Which makes it difficult to execute an exact amount defined in the primary currency. In case you want to
configure this functionality, see configuration properties bhb.executeBuyMarketOrdersUsingLimitOrders
and bhb.executeBuyMarketOrdersUsingLimitOrdersPercentage.
FunctionalitySupported Features
Withdrawals Supported.
Deposit Not supported. Deposit addresses are not available on the BitHumb Pro API at the moment.
Addresses
Account Not supported. Account events are not available on the BitHumb Pro API at the moment.
Events
Account Supported.
Balance
Retrieval
23.33. BitMEX
41
BitMEX is a cryptocurrency futures exchange. The BitMEX adapter provides order execution, market data,
reference data and account data functionality through REST and WebSocket API. Please see the API
42
reference page for technical details about the supported features.
The relevant properties for the BitMEX adapter are defined inside the file conf-bmx.properties where they
can be changed. Alternatively the properties can be changed via Section 2.4, “VM Options”:
#{"type":"String","label":"API Key"}
bmx.apiKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"String","label":"API Secret"}
bmx.apiSecret = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"Integer","label":"API-level constant'}
bmx.balanceScale = 8
A BitMEX account is necessary in order to use the BitMEX adapter. Unique apiKey and apiSecret settings
must be set to the actual values (either in the properties file or by setting a VM argument)
41
https://www.bitmex.com/
42
https://www.bitmex.com/app/apiOverview
295
CONFIDENTIAL BitMex Order Constraints
Type Description
Future Regular future contracts expiring every 3 months. Please note that the XBT (BTC) contracts
43
have a variable contract size. For more information please see Futures Guide .
Bitcoin perpetual contract XBTUSD (BTCUSD) are represented by this class. For more
PerpetualSwap
44
information please see Perpetual Contract Specification
45
Index For a complete list of supported indices please see Indices
The minimum quantity for all contracts is 1 contract (lot size = 1). Only integer number of contracts are allowed.
The QUANTITY_SCALE for all securities is set to 0 and must not be changed.
Placing an order to buy one XBTUSD means buying the amount of Bitcoin worth 1 USD. For more information
46
please consult the BitMEX perpetual contract details page. .
43
https://www.bitmex.com/app/futuresGuide
44
https://www.bitmex.com/app/contract/XBTUSD
45
https://www.bitmex.com/app/index/.BXBT
46
https://www.bitmex.com/app/seriesGuide/XBT
296
CONFIDENTIAL BitMex Account Management
FunctionalitySupported Features
Withdrawals Only BTC is supported
Account Supported
Events
Account Supported.
Balance
Retrieval
23.34. Bitstamp
47 48
Bitstamp is a cryptocurrency exchange. Please see the API reference page for the technical details.
Order and market data related functionality is provided via FIX/4.4 protocol. Account data and reference data
is provided via REST API.
Bitstamp FIX/4.4 interface follows the standard closely, but offers only one session for both market data feed
and trading operations. Bitstamp market data supports only limited number of cryptocurrency (Forex) securities.
Order modifications are not supported. For more information about the Bitstamp FIX specification please have
49
a look at the Bitstamp public FIX interface .
The relevant properties for the Bitstamp adapter are defined inside the file conf-bts.properties where they
can be changed. Alternatively the properties can be changed via Section 2.4, “VM Options”:
#{"type":"String","label":"API Key"}
bts.apiKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"String","label":"API Secret"}
bts.apiSecret = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"String","label":"Customer ID"}
bts.customerId = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
47
https://www.bitstamp.net/
48
https://www.bitstamp.net/api/
49
https://www.bitstamp.net/fix/
297
CONFIDENTIAL Bitstamp Order Constraints
bts.importAllPairs = true
A Bitstamp account is necessary in order to use Bitstamp adapter. Unique apiKey and apiSecret settings
must be set to the actual values (either in the properties file or by setting a VM argument)
At the time of writing this, Bitstamp does not support order modifications.
Account Supported.
Balance
Retrieval
50
https://www.bitstamp.net/article/upcoming-changes-fee-schedule/
298
CONFIDENTIAL Bittrex
Order reconciliation is implemented by loading pending order statuses via Rest API when FIX session
reconnects, similar to adapters that work via Rest/Websocket interfaces and not via FIX (see Section 23.5,
“Automatic order reconciliation after re-connect”). The reason for this is that Bitstamp FIX API uses a single
session for both market data and trading and the automatic order reconciliation using FIX Resend message
doesn't work reliably. fix.cfg property ResetOnLogOn needs to be turned on otherwise the logon to the
Bitstamp FIX API might fail.
23.35. Bittrex
51
Bittrex is a cryptocurrency exchange. Bittrex adapter allows trading spot instruments (e.g. BTCUSD or
BTCUSDT),
Bittrex adapter supports order execution, market data, reference data and account data functionality. Please
52
see the Bittrex API reference page for technical details.
The relevant properties of the Bittrex adapter are defined inside the file conf-btx.properties where they can
be changed. Alternatively the properties can be changed via Section 2.4, “VM Options”:
#{"type":"String","label":"REST Url"}
btx.restUrl = https://api.bittrex.com/v3/
#{"type":"String","label":"API Key"}
btx.apiKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"String","label":"API Secret"}
btx.apiSecret = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
51
https://global.bittrex.com/
52
https://bittrex.github.io/api/v3
299
CONFIDENTIAL Bittrex Order Constraints
btx.orderbookfilter=1000
Note
Time In Force values supported: Good-till-cancel (GTC), Fill-Or-Kill (FOK), PO (Post-Only), Immediate-Or-
Cancel (IOC)
Bittrex adapter requires that either FOK or IOC TIF value is set with market orders. Market orders default their
TIF to FOK instead of usual GTC.
Rest calls rate limit is set to 60 calls per 1 minute by default in btx.rateLimits configuration property.
Order quantity increment is 0.00000001. Price increment and minimum quantity are security specific. They can
be looked up in the Security table after running the reference data starter with Kraken Spot adapter configured:
53
Chapter 20, Reference Data. For other trading restrictions applied by the exchange, see this article .
FunctionalitySupported Features
Withdrawals Supported with all crypto-currencies.
Wallet Supported with all crypto-currencies. Loads history of deposits and withdrawals.
History
53
https://bittrex.zendesk.com/hc/en-us/articles/360001473863-Bittrex-Trading-Rules
300
CONFIDENTIAL Blockfills
FunctionalitySupported Features
Account Supported.
Balance
Retrieval
23.36. Blockfills
54
Blockfills is a crypto liquidity provider. AlgoTrader provides an adapter access to Blockfills' trading and market
data functionality via their FIX API.
Blockfills adapter supports order execution and market data. Reference data is available in the provided sample
data. Account data functionality is not available in Blockfills API.
Blockfills provides a fully functional UAT test environment and the adapter can be configured to use it.
Connection properties and credentials for the FIX adapter need to be set in /bootstrap/conf/src/main/
resources/fix.cfg. You can copy there the content of the example fix-bf.cfg file at the same location.
Relevant properties of the Blockfills adapter can be found inside the file conf-bf.properties where they can
be adjusted. Alternatively these properties can be changed via Section 2.4, “VM Options”:
# Supported TIFs
bf.supportedTifs=GTC,IOC,FOK,GTD
Reference data functionality is not available in the Blockfills FIX API. All available securities and other necessary
values are available inside the sample data file mysql-data.sql
• RFS and RFQ trading is not available via Blockfills FIX API at the moment.
54
https://www.blockfills.com/
301
CONFIDENTIAL CoinAPI
• Contract sizes, quantity and price increments are specific to different securities and are loaded from the
Security table.
23.37. CoinAPI
55
CoinAPI is a market data gateway to multiple crypto exchanges. CoinAPI provides historical and live market
data. It also provides reference data for the supported instruments, however it doesn't provide trading related
56
functionality. Please see the API reference page for the technical details.
Historical data is available down to 1 second bars. Historical data availability varies by currency. Up to 100
57
daily requests can be placed for free. Consult their pricing if you require more.
Instruments and exchanges must have CNPID value setup in security and exchangedatabase tables.
The relevant properties for the CoinAPI adapter are defined inside the file conf-cnp.properties where they
can be changed. Alternatively the properties can be changed via Section 2.4, “VM Options”:
#{"type":"String","label":"API Key"}
cnp.apiKey = XXXXXXXXXXXXXXXXX
#{"type":"Integer","label":"API-level constant'}
cnp.scale = 5
Unique apiKey and apiSecret settings must be set to the actual values (either in the properties file or by
setting a VM argument)
55
https://www.coinapi.io/
56
https://docs.coinapi.io/
57
https://www.coinapi.io/pricing
58
https://pro.coinbase.com
302
CONFIDENTIAL Coinbase Pro
Note
Currently Coinbase Pro does not yet support cross-border trading, so trading vs. USD is only
possible with a US account.
The relevant properties for the Coinbase Pro adapter are defined inside the file conf-cnb.properties where
they can be changed. Alternatively the properties can be changed via Section 2.4, “VM Options”:
#{"type":"String","label":"API Key"}
cnb.apiKey = XXX
#{"type":"String","label":"API Secret"}
cnb.apiSecret = XXX
#{"type":"String","label":"API passphrase"}
cnb.passphrase = XXX
#{"type":"String","label":"REST Url"}
cnb.restUrl = https://api.pro.coinbase.com
#cnb.restUrl = https://api-public.sandbox.pro.coinbase.com
A Coinbase Pro account is necessary in order to use Coinbase Pro adapter, but not needed for market data.
60
Coinbase Pro provides a sandbox/testing environment, both for the public website (Sandbox website url ) and
the exchange. You'll need to generate (via the Coinbase website) and configure (see properties above) an API
key and API secret in order to use the Coinbase Pro Adapter. The sandbox/testing environment has different
URLs (see commented out values cnb.webSocketUrl, cnb.restUrl above).
59
https://docs.pro.coinbase.com
60
https://public.sandbox.pro.coinbase.com
303
CONFIDENTIAL CoinBase Pro Order Constraints
Note
0.01 BCH
0.01 ETH
0.1 LTC
MaxQty -
QtyIncr BaseMinSize scale
MinPrice -
MaxPrice -
PriceIncr Quote Increment
MinNotional -
61
Details For further details please see Limits
Automatic order reconciliation (on FIX reconnect) is implemented for Coinbase (required, as the Coinbase Pro
FIX server does not support the Resend message.
FunctionalitySupported Features
Withdrawals Support for all cryptocurrencies
Deposit Support for all cryptocurrencies. Note that the deposit address returned is for an account in
Addresses Coinbase (non-PRO). The transfer to Coinbase Pro (system for trading) needs to be done
manually via the Coinbase Pro website.
61
https://help.coinbase.com/en/pro/trading-and-funding/trading-rules-and-fees/limits.html
304
CONFIDENTIAL CoinMarketCap
FunctionalitySupported Features
Account Not supported
Events
Account Supported.
Balance
Retrieval
23.39. CoinMarketCap
62
CoinMarketCap - Cryptocurrency Market Capitalizations is a website providing information about all existing
crypto currencies and exchanges. The CoinMarketCap interface connects to the website via HTML and REST
63
API .
The CoinMarketCap interface provides the publicly available daily historical data and reference data for all
listed crypto currencies. No account is necessary in order to use the CoinMarketCap adapter.
23.40. CryptoFinance
CryptoFinance is a cryptocurrency market maker/OTC trading services provider.
The CryptoFinance interface supports Market Data, Order Processing, Request for Quote (RFQ) process as
well as Reference Data.
The relevant properties for the CryptoFinance adapter are defined inside the file conf-cf.properties where
they can be changed. Alternatively the properties can be changed via Section 2.4, “VM Options”:
62
https://coinmarketcap.com/
63
https://coinmarketcap.com/api/
305
CONFIDENTIAL CryptoFinance Order Constraints
cf.priceLevels=BTC=10
#{"type":"double","label":"Order book filter for filtering order book price levels"}
cf.orderbookfilter=1000
# Supported TIFs
cf.supportedTifs=FOK,GTC,GTD
cf.defaultTif=FOK
# Supported order types
cf.supportedOrderTypes=MARKET,LIMIT,PREVIOUSLY_INDICATED
CryptoFinance does not have an order book but will stream prices to you at closest to requested level for each
coin (e.g. CryptoFinance streams prices for 1, 5, 20 and 100 BTC, user requests price for 11 BTC, so price
for 20BTC would be streamed to user.).
In order to populate the database with CryptoFinance Accounts, Exchanges, Security Families and Securities
run the ReferenceDataStarter with cFReferenceData spring profile enabled and program argument: all.
For further details please visit Chapter 20, Reference Data.
Note that time in force (TIF) for CryptoFinance Previously Indicated orders has to be Fill or Kill (FOK), and for
non RFQ orders Good till Cancel (GTC) or Good till Day (GTD).
CryptoFinance supports previously indicated (for quote execution), market and limit orders. CryptoFinance also
supports order cancelation.
Note
306
CONFIDENTIAL Deribit
23.41. Deribit
64
Deribit is a crypto exchange which provides trading on derivatives based on Bitcoin and Ethereum. The
provided derivatives are futures, perpetual swaps and options. Derivatives are priced based on Bitcoin and
Ethereum indexes that follow BTCUSD and ETHUSD price weighted from several exchanges.
Deribit adapter supports order execution, market data, reference data and account data functionality. All
adapter functionality is implemented using FIX protocol except for Section 21.4, “Account Events” functionality
(available if the Deribit account adapter is turned on) that use Websocket. Please see the Deribit API
65 66
reference page for technical details and Deribit website for the list of available instruments and their
historical prices.
67
Deribit provides fully functional test environment and Deribit adapter can be configured to use it.
# SocketConnectHost=testapp.deribit.com
# SocketConnectPort=9881
SocketConnectHost=www.deribit.com
SocketConnectPort=9880
Relevant properties of the Deribit adapter including connection credentials are defined inside the file conf-
drb.properties where they can be adjusted. Alternatively these properties can be changed via Section 2.4,
“VM Options”:
#{"type":"String","label":"API key."}
drb.apiKey=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"String","label":"API secret."}
drb.apiSecret=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
64
https://www.deribit.com/
65
https://docs.deribit.com/v2/
66
https://www.deribit.com/main#/indexes
67
https://test.deribit.com/
307
CONFIDENTIAL Deribit Order Constraints
Note that futures and perpetual swaps in Deribit are defined using contracts valued in the base currency instead
of the quote currency. They are also referred to as inverse contracts instruments. An example is the BTC
perpetual swap, with its contract valued in BTC. This is an equivalent of BTCUSD (XBTUSD) perpetual swap
in BitMex, note that the instrument is not defined exactly the same way and its price may differ from the BitMex
one.
Options are priced and settled in the crypto, BTC or ETH. For details see Deribit's documentation at Options
68
information .
Valuation of inverse contracts changes PnL calculation, but is handled by AlgoTrader automatically. For details
69 70
see Deribit's documentation at Perpetual Swaps information and Futures information
Deribit index securities are loaded by the reference data adapter and market data is available on them. They
are not tradable. Because Deribit only provides a single price for each index, the market data is delivered with
bid and ask set both to this price and their respective quantities are set to 1.
• Contract sizes, quantity and price increments are specific to different securities and are loaded by the
reference data starter into Security table.
• Deribit's FIX API uses the same session for market data and order placement and statuses. Resend
messages from client to broker are not supported. Those are usually used for order reconciliation on restart
68
https://www.deribit.com/pages/docs/options
69
https://www.deribit.com/pages/docs/perpetual
70
https://www.deribit.com/pages/docs/futures
308
CONFIDENTIAL Deribit Account Management
or reconnect of FIX client which is AlgoTrader in this case. The order reconciliation is implemented on
AlgoTrader side by requesting order statuses from Deribit using OrderMassStatusRequest message. This
is triggered on LOGGED_ON session event (see Section 23.4, “Session life-cycle events”), which is trigerred
when AlgoTrader starts or the Deribit adapter is reconnected.
FunctionalitySupported Features
Withdrawals Supported. Withdrawal address needs to be added to the account via the exchange website
for security reasons.
Deposit Supported.
Addresses
Account Supported.
Events
Account Supported.
Balance
Retrieval
23.42. Enigma
Enigma is a cryptocurrency exchange that also supports RFQ process.
The Enigma interface supports Market Data, Order Processing, Request for Quote (RFQ) process as well as
Reference Data.
The relevant properties for the Enigma adapter are defined inside the file conf-egm.properties where they
can be changed. Alternatively the properties can be changed via Section 2.4, “VM Options”:
309
CONFIDENTIAL Enigma Order Constraints
Enigma does not have an order book but will stream prices to you at requested level for each coin (e.g. 5BTC).
In order to populate the database with Enigma Accounts, Exchanges, Security Families and Securities run
the ReferenceDataStarter with eGMReferenceData spring profile enabled and program argument: all. For
further details please visit Chapter 20, Reference Data.
Note that time in force (TIF) for Enigma for non RFQ orders must be Fill or Kill (FOK), Immediate or Cancel
(IOC), Good till Cancel (GTC) or Good till Day (GTD).
Note that Enigma allows RFQ process not for all instruments. Only instruments that are provided with egmId
can be quoted. Also, production or test environment can be choosed to execute rfq (egm.restInfra parameter).
Enigma supports previously indicated (for quote execution), market, limit, stop and stop limit orders.
CryptoFinance also supports order modifications and cancelation.
310
CONFIDENTIAL eToroX
23.43. eToroX
71
eToroX is a cryptocurrency exchange. The eToroX adapter provides order execution, market data, reference
72
data and account data functionality. Please see the eToroX API reference page for technical details about
the supported features.
The relevant properties for the eToroX adapter are defined inside the file conf-etx.properties where they
can be changed. Alternatively the properties can be changed via Section 2.4, “VM Options”:
#{"type":"String","label":"REST Url"}
etx.apiHost=https://xxxxxxxxxxx.hft.etorox.com
#{"type":"String","label":"Web Socket Url"}
etx.websocketHost=https://xxxxxxxxxxx.hft-ws.etorox.com
#{"type":"String","label":"API Key / public key generated by eToroX"}
etx.apiKey=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"String","label":"Path to API Secret file where private key generated by
eToroX is stored. The key provided by EtoroX webpage needs to be converted first:
https://gist.github.com/etorox/094eb6d22cf83d72218d2d28ff304bc4"}
etx.apiSecretPath=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"Boolean","label":"if true import all currencies, otherwise only those
defined in ch.algotrader.enumeration.Currency"}
etx.importAllPairs=true
An eToroX account is necessary in order to use eToroX adapter. Unique apiHost, websocketHost, apiKey and
apiSecret settings must be set to the actual values (either in the properties file or by setting a VM argument).
Note
API host, websocket host, API key and API secret are uniquely generated for eToroX
73
accounts. API secret provided by eToroX platform should be converted as described here .
Then the secret should be stored in a file and filesystem path to it should be set under
etx.apiSecretPath
71
https://www.etorox.com//
72
https://etorox.github.io/docs/#/
73
https://gist.github.com/etorox/094eb6d22cf83d72218d2d28ff304bc4//
311
CONFIDENTIAL eToroX Account Management
FunctionalitySupported Features
Withdrawals Supported
Deposit Supported
Addresses
Account Supported
Balance
Retrieval
23.44. Gemini
74
Gemini is a crypto-currency exchange providing trading on spot crypto pairs.
Gemini adapter supports trading, market data and account data functionality. Reference data is not available
on Gemini's APIs and is implemented in AlgoTrader's sample data. Trading and market data functionality is
implemented using Gemini's FIX API. Account data functionality using Gemini's Rest API. Please see the
75
Gemini API reference page for technical details.
76
Gemini provides Sandbox environment replicating the full exchange functionality (market data is restricted
to BTCUSD).
The use of FIX API by the adapter allows requesting low latency cross-connect with Gemini. Note that FIX
API access requires an on-boarding procedure with Gemini, this includes FIX API access to their Sandbox
77
environment. For details, please see Gemini's documentation .
74
https://gemini.com/
75
https://docs.gemini.com/
76
https://exchange.sandbox.gemini.com
77
https://docs.gemini.com/fix-api/#download
312
CONFIDENTIAL Gemini
[default]
ConnectionType=initiator
HeartBtInt=30
ReconnectInterval=5
FileStorePath=files/fix
FileLogPath=log
FileLogHeartbeats=N
FileIncludeMilliseconds=Y
FileIncludeTimeStampForMessages=Y
SLF4JLogHeartbeats=Y
ResetSeqNumFlag=N
[session]
SessionQualifier=GMN-T
BeginString=FIX.4.4
# UAT
SocketConnectHost=8.44.203.78
SocketConnectPort=1538
TargetCompID=???
SenderCompID=???
SocketUseSSL=N
TimeZone=America/New_York
StartTime=17:00:00
EndTime=17:00:00
Inactive=Y
ResetOnLogon=N
DataDictionary=gmn/gemini-fix-dictionary.xml
UseDataDictionary=Y
# pending orders are by default canceled by Gemini exchange after the client
disconnects
CancelOnDisconnect=N
[session]
SessionQualifier=GMN-MD
BeginString=FIX.4.4
# UAT
SocketConnectHost=8.44.203.78
SocketConnectPort=1539
TargetCompID=???
SenderCompID=???
SocketUseSSL=N
TimeZone=America/New_York
StartTime=17:00:00
EndTime=17:00:00
Inactive=Y
313
CONFIDENTIAL Gemini
ResetOnLogon=Y
DataDictionary=gmn/gemini-fix-dictionary.xml
UseDataDictionary=Y
Relevant properties of the Gemini adapter including connection credentials are defined inside the file conf-
gmn.properties where they can be adjusted. Alternatively these properties can be changed via Section 2.4,
“VM Options”:
#{"type":"String","label":"API Key"}
gmn.apiKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"String","label":"API Secret"}
gmn.apiSecret = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Order reconciliation works automatically using standard FIX API messages. Note that Gemini verify there is
no gap in sequence numbers on login. Under some special circumstances, e.g. network timeouts, the latest
sent sequence number on the AlgoTrader side may become outdated. In case the trading adapter is unable
to connect, you may try changing the fix.cfg setting ResetOnLogon to value Y and restart AlgoTrader. Note
314
CONFIDENTIAL Gemini Order Constraints
that this setting in effect also disables order reconciliation and should be changed to the default value of N
afterwards.
• Contract sizes, quantity and price increments are specific to different securities and are set in sample data
(mysql-data.sql) in the Security table.
• Subscribed market data can not be unsubscribed in the FIX API. In case the unsubscribe is requested, the
Gemini adapter stops creating market data related events, but the physical delivery of market data from the
exchange to the adapter continues.
• Pending orders are by default automatically cancelled by the exchange after the client disconnects. This
functionality can be turned off by setting CancelOnDisconnect=N in trading session settings in fix.cfg.
Buy market orders sized in base currency are not supported by the exchange. An example is BTCUSD, when
buying or selling using a market order in it, the API expects the quantity to be specified in USD, not in BTC.
The adapter by default works around this by placing a buy limit order above the current best ask price in
order to immediately execute the buy order in specified BTC quantity. A disadvantage of this workaround is
that account balance requirement on order placement is slightly higher than it would be with market order.
Another option is to execute market orders with quantity defined in the secondary currency by converting
the requested base currency amount using the current best ask price. The disadvantage of this approach
is the quantity executed by the exchange may be slightly smaller than originally requested due to rounding,
move of the price or when the order quantity crosses more levels in the sell part of the order book. In case a
smaller amount is executed, the adapter still creates an EXECUTED (full fill) order status. In case you want
to configure this functionality, see configuration properties gmn.executeBuyMarketOrdersUsingLimitOrders
and gmn.executeBuyMarketOrdersUsingLimitOrdersPercentage.
FunctionalitySupported Features
Withdrawals Supported.
Deposit Supported.
Addresses
315
CONFIDENTIAL Huobi Spot
FunctionalitySupported Features
Account Supported.
Balance
Retrieval
Huobi Spot adapter supports order execution, market data, reference data and account data functionality. All
adapter functionality is implemented using the exchange's Rest and Websocket APIs. Please see the Huobi
80
Spot API reference page for technical details.
Relevant properties of the Huobi Spot adapter are defined inside the file conf-hbi.properties where they
can be adjusted. Alternatively these properties can be changed via Section 2.4, “VM Options”:
# note that urls below can use their non-AWS versions when not running on AWS.
#{"type":"String","label":"REST Url"}
hbi.restUrl = https://api-aws.huobi.pro
# hbi.restUrl = https://api.huobi.pro
#{"type":"String","label":"API Key"}
hbi.apiKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"String","label":"API Secret"}
hbi.apiSecret = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
78
https://www.huobi.com/en-us/
79
https://www.huobi.com/en-us/exchange/
80
https://huobiapi.github.io/docs/spot/v1/en/#introduction
316
CONFIDENTIAL Huobi Spot constraints
Buy market orders sized in base currency are not supported by the exchange. An example is BTCUSDT,
when buying or selling using a market order in it, the API expects the quantity to be specified in USDT,
not in BTC. The adapter by default works around this by placing a buy limit order above the current
best ask price in order to immediately execute the buy order. A disadvantage of this workaround is
that account balance requirement on order placement is slightly higher than it would be with market
order. Another option is to execute market orders with quantity defined in the secondary currency by
converting the requested base currency amount using the current bid/ask prices. The disadvantage of
this approach is the quantity executed by the exchange is subtracted with fees and the price might
change during execution or on orders with quantity bigger that the relevant order book top level size.
Which makes it difficult to execute an exact amount defined in the primary currency. In case you want to
configure this functionality, see configuration properties hbi.executeBuyMarketOrdersUsingLimitOrders
and hbi.executeBuyMarketOrdersUsingLimitOrdersPercentage.
Quantities, increments and other constraints are security specific. They can be looked up in the Security table
after running the reference data starter with Huobi Spot adapter configured: Chapter 20, Reference Data.
FunctionalitySupported Features
81
Withdrawals Supported with all crypto-currencies with exceptions, for details see the Huobi webpage .
82
Wallet Supported with all crypto-currencies with exceptions, for details see the Huobi webpage .
History
81
https://www.huobi.com/en-us/finance/
82
https://www.huobi.com/en-us/finance/
317
CONFIDENTIAL Kraken Spot
FunctionalitySupported Features
83
Deposit Supported with all crypto-currencies with exceptions, for details see the Huobi webpage .
Addresses
Account Supported.
Events
Account Supported.
Balance
Retrieval
Automatic order reconciliation (on market data WebSocket reconnect) is implemented for Huobi Spot.
Kraken Spot adapter supports order execution, market data, reference data and account data functionality.
85
Please see the Kraken API reference page for technical details.
The relevant properties of the Kraken Spot adapter are defined inside the file conf-kks.properties where
they can be changed. Alternatively the properties can be changed via Section 2.4, “VM Options”:
#{"type":"String","label":"REST Url"}
kks.restUrl = https://api.kraken.com
#{"type":"String","label":"API Key"}
kks.apiKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"String","label":"API Secret"}
kks.apiSecret = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
83
https://www.huobi.com/en-us/finance/
84
https://www.kraken.com/
85
https://www.kraken.com/features/api
318
CONFIDENTIAL Kraken Spot Order Constraints
Kraken Spot exchange supports margin trading at leverage levels defined per security. Each margin order
can have one of several leverage options specified. Availability of leverage level options is different between
different securities and is not available with some securities. Margin orders from AlgoTrader are set to use
leverage of size 2 by default. This value can be changed using kks.leverageToUseWithMarginOrders
configuration option. Individual orders can override the default setting by having leverage integer order
property specified. Note that if you submit an order with a leverage not available with the security in Kraken,
your order will be rejected by the exchange. The availability of leverage options can be verified using Kraken
86
website .
Note
Kraken Spot adapter currently supports market, limit and stop orders. Stop Limit orders have
been implemented but are currently not available in Kraken.
Note that pending orders placed from AlgoTrader only appear at Kraken website after you fully refresh it.
87
German residents (users with German address) need to agree with Kraken's trading agreement for
legal reasons. Confirming the agreement is done on AlgoTrader side by setting the configuration property
kks.tradingAgreementApproved to true. It defaults to false.
Time In Force values supported: Good-till-cancel (GTC), PO (Post-Only), Day Order (DAY), Good-till-Day
(GTD)
86
https://trade.kraken.com
87
https://support.kraken.com/hc/en-us/articles/360036157952
319
CONFIDENTIAL Kraken Spot Account Management
Rest calls rate limits in Kraken have complicated rules and it is recommended by Kraken to make just 1
order placement per second in general. The overall rate limit is set to 60 calls per 1 minute by default in
kks.rateLimits configuration property.
FunctionalitySupported Features
Withdrawals Supported with all crypto-currencies.
Wallet Supported with all crypto-currencies. Loads history of deposits and withdrawals.
History
Deposit Supported with the following currencies: Bitcoin, Litecoin, Ether (Hex), Zcash (Transparent),
Addresses ADA, Monero, Ripple XRP, Stellar XLM, Bitcoin Cash, REP, SynapsePay (US Wire), Dogecoin,
MLN, GNO, QTUM, XTZ, Cosmos, EOS, Dash.
Account Not supported.
Events
Account Supported.
Balance
Retrieval
Automatic order reconciliation (on WebSocket reconnect) is implemented for Kraken Spot.
• Supports DAY, GTC, IOC and FOK time-in-force parameters for market and limit orders.
• Supports only DAY and GTC time-in-force parameters for stop orders (stop and stop-limit).
• supports trading status signaling temporary suspension and resumption in trading of individual securities.
320
CONFIDENTIAL OKEx and OKCoin
• Market and limit orders: DAY, GTC, IOC and FOK time-in-force supported.
• Order modification changes the time-in-force from its original value to DAY.
OKEx and OKCoin adapters supports order execution, market data, reference data and account data
90 91
functionality. Please see the OKEx API reference and OKCoin API reference pages for technical details.
The properties of the OKEx and OKCoin adapters are defined inside the files conf-okex.properties and
conf-okcoin.properties. Alternatively the properties can be changed via Section 2.4, “VM Options” For
OKCoin the properties are the same as below with suffix okcoin:
#{"type":"String","label":"API Key"}
okex.apiKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"String","label":"API Secret"}
okex.apiSecret = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#{"type":"String","label":"API passphrase"}
okex.passPhrase = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
88
https://www.okex.com/
89
https://www.okcoin.com/
90
https://www.okex.com/docs/en/
91
https://www.okcoin.com/docs/en/
321
CONFIDENTIAL OKEx and OKCoin
Note that some futures and perpetual swaps in OKEx are defined using contracts valued in the base currency
instead of the quote currency. They are also referred to as inverse contracts instruments. An example is
the perpetual swap BTCUSD, with its contract valued in BTC. This is an equivalent of BTCUSD (XBTUSD)
perpetual swap in BitMex, note that the instrument is not defined exactly the same way and its price may differ
from the BitMex one. Inverse contract instruments are called 'Coin Margined' on the OKEx website. Regular
non-inverse contract instruments are 'USDT margined' swaps/futures.
Valuation of inverse contracts changes PnL calculation, but is handled by AlgoTrader automatically. For details
92 93
see OKEx's documentation at Perpetual Swaps information and Futures information
92
https://www.okex.com/en/futureTrade/beforePerpetualFuture
322
CONFIDENTIAL OKEx/OKCoin Order Constraints
As of January 2020, OKEx provides options priced based on their BTC-USD index. All options are priced and
settled in BTC.
Note
OKEx and OKCoin support market and limit orders only.
Buy market orders sized in base currency are not supported for non-derivative instruments by the exchange.
An example is BTCUSDT, when buying or selling using a market order in it, the API expects the quantity
to be specified in USDT, not in BTC. The adapter by default works around this by placing a buy limit
order above the current best ask price in order to immediately execute the buy order. A disadvantage of
this workaround is that account balance requirement on order placement is slightly higher than it would
be with market order. Another option is to execute market orders with quantity defined in the secondary
currency by converting the requested base currency amount using the current bid/ask prices. The disadvantage
of this approach is the quantity executed by the exchange is subtracted with fees and the price might
change during execution or on orders with quantity bigger that the relevant order book top level size.
Which makes it difficult to execute an exact amount defined in the primary currency. In case you want to
configure this functionality, see configuration properties okex.executeBuyMarketOrdersUsingLimitOrders
and okex.executeBuyMarketOrdersUsingLimitOrdersPercentage.
Non-derivative instruments' Websocket status changes messages do not include fees that were
applied to fills. These are by default loaded by AlgoTrader using a Rest call after a message
with a full fill is received. This functionality can be turned off using the configuration property
okex.loadFilledOrderFeesViaRestIfNecessary
Quantities, increments and other constraints are security specific. They can be looked up in the Security table
after running the reference data starters with OKEx and OKCoin adapters configured: Chapter 20, Reference
Data.
93
https://www.okex.com/en/futureTrade/beforePerpetualFuture
94
https://www.okex.com/spot/marginTrade
95
https://www.okcoin.com/spot/trade?type=2
323
CONFIDENTIAL OKEx/OKCoin Account Management
FunctionalitySupported Features
accounts, each asset type has a specific account and funds need to be moved to the funding
account before the withdrawal.
Wallet Supported with all crypto-currencies. Loads history of deposits and withdrawals in the funding
History account.
Deposit Supported with all crypto-currencies
Addresses
Account Supported. Account events deliver balance on a non-funding account after a transfer. Transfers
Events to and from the funding account with external accounts are not supported by the API and the
adapter. If the transfer is executed between 2 non-funding accounts, 2 account events are
created, one for each.
Account Supported.
Balance
Retrieval
Automatic order reconciliation (on WebSocket reconnect) is implemented for OKEx and OKCoin.
324
Chapter 24. CONFIDENTIAL
Execution Algos
24.1. Existing Execution Algos
AlgoTrader provides several built-in Execution Algos.
SlicingOrder
The Slicing Algo is only recommended for traditional assets like Equities and derivatives. It is disabled for
cryptocurrencies, consider the TWAP or VWAP algos for similar functionality which will be compatible with
assets traded on crypto exchanges.
Splits an order into several child orders. child order quantities and time in the market are randomized. The
SlicingOrder has the following order properties:
The quantity of each child order is randomized between minVolPct and maxVolPct of the current
volume offered at the exchange. In addition minQuantity and maxQuantity restriction can be imposed.
If maxVolPct is zero or 100%, then the current market volume will not be considered when sizing the
order. If maxQuantity is zero, then no maximum quantity will be enforced on top of the market volume
restriction. The SlicingOrder will make sure that the remainingQty for the next child order is greater than
minQuantity. Maximum quantity rules have precedence over minimum quantity rules.
Example:
minVolPct: 25%, minQuantity: 20, maxVolPct: 90%, maxQuantity: 100, BUY order, quantity: 40, vol
ask: 10
325
CONFIDENTIAL Existing Execution Algos
Each order will stay in the market for minDuration to maxDuration seconds (if it is not filled before that).
Between each child order there will be a random delay of minDelay to maxDelay seconds. In addition, the
SlicingOrder has a sophisticated pricing logic. For a BUY order the first child order will be place 1 tick
below the Ask. For a SELL order the first tick will be placed one tick above the Bid. Depending on whether
a child order gets filled, the price of the next child order is adjusted. If a child order gets filled, the price of
the next child order will be reduced by one tick (for BUY orders) but it will always be at least one tick above
the Bid. If the child order does not get filled, the price of the next child order is increased by one tick (for
BUY orders) but it will never be higher than the ask. A SlicingOrder can be created and sent as follows:
getOrderService().sendOrder(order);
Alternatively Section 17.2.1, “Order Preferences” can be used to create a SlicingOrder. The AlgoTrader
sample data contains an OrderPreference named SLICING (with the default values shown in the table
above) which allows placing a SlicingOrder as follows:
getOrderService().sendOrder(order);
VWAPOrder
1
The VWAPOrder seeks to achieve the Volume-Weighted Average price (VWAP) . VWAP is a trading
benchmark used by many institutional investors. VWAP is calculated by adding up the market value
1
https://en.wikipedia.org/wiki/Volume-weighted_average_price
326
CONFIDENTIAL Existing Execution Algos
traded for every transaction (price multiplied by number of contracts traded) and then dividing by the total
contract traded. The VWAPOrder is based on the AdaptiveOrder (see) below and uses its pricing logic.
The VWAPOrder has the following order properties in addition to the ones defined by the AdaptiveOrder.
The VWAPOrder retrieves historical prices for the number of days specified in the lookbackPeriod
parameter and splits the trading day into buckets with a length in minutes according to the bucketSize
parameter.
When a VWAPOrder is either fully-executed or cancelled a message containing the average price, the
benchmark price as well as the execution duration and number of executions is logged to the console.
For the VWAPOrder to work a historical data adapter will need to be enabled, see Section 7.2.7, “Historical
Data Service”.
getOrderService().sendOrder(order);
Alternatively Section 17.2.1, “Order Preferences” can be used to create a VWAPOrder. The AlgoTrader
sample data contains an OrderPreference named VWAP (with the default values shown in the table above)
which allows placing a VWAPOrder as follows:
327
CONFIDENTIAL Existing Execution Algos
getOrderService().sendOrder(order);
TWAPOrder
2
The TWAPOrder seeks to achieve the Time-Weighted Average price (TWAP) . TWAP is a trading
benchmark used by many institutional investors. TWAP is derived by calculating the average execution
price over a certain time period irrespective of the executed quantity.
The TWAPOrder is based on the AdaptiveOrder (see) below and uses its pricing logic. The TWAPOrder has
no additional order properties in addition to the ones defined by the AdaptiveOrder.
When a TWAPOrder is either fully-executed or cancelled a message containing the average price, the
benchmark price as well as the execution duration and number of executions is logged to the console.
As the reporting functionality needs historical data a historical data adapter will need to be enabled, see
Section 7.2.7, “Historical Data Service”. The TWAPOrder can still be used without historical data but not
report will be logged to the console.
getOrderService().sendOrder(order);
2
https://en.wikipedia.org/wiki/Time-weighted_average_price
328
CONFIDENTIAL Existing Execution Algos
Alternatively Section 17.2.1, “Order Preferences” can be used to create a TWAPOrder. The AlgoTrader
sample data contains an OrderPreference named TWAP (with the default values shown in the table above)
which allows placing a TWAPOrder as follows:
getOrderService().sendOrder(order);
AdaptiveOrder
The AdaptiveOrder is the parent class of the VWAPOrder and TWAPOrder and defines the pricing logic for
those. However it is not possible to send an AdaptiveOrder directly. The AdaptiveOrder has the following
order properties
The AdaptiveOrder uses a pricing logic similar to the Slicing Execution Algo.
The first child order will be placed at the initialOffset between the Bid and the Ask (e.g. at 80%).
Depending on whether a child order gets filled, the price of the next child order is adjusted. If the previous
child order got fully or partially filled, the price of the next child order will be reduced by increment % of
the spread. If the previous child order did not get filled, the price of the next child order is increased by
increment % of the spread. The limit price will always be adjusted within the following price range:
329
CONFIDENTIAL Existing Execution Algos
The AdaptiveOrder will execute over a predefined time period which can be set by two of the following
arguments: startTime, endTime or duration.
In case a child order is not fully executed it will get cancelled after the following period of time:
Calculated child order quantities respect the optional minSliceQty. In addition, the AdaptiveOrder also
respects the optional property maxVolPct which will cause to algo not to place child orders larger than the
current VolAsk (for Buy orders) or VolBid (for Sell orders).
As the Algo needs to be executed within a predefined time period, the child order quantities are adjusted
throughout the order execution. Quantity adjustments take into consideration previously executed quantity
in order to fully executed the algo within its time constraints. No further quantity adjustments take place
once 90% of the order execution time has passed.
TargetPositionOrder
The TargetPositionOrder seeks to bring the actual position to an intended target quantity. The
TargetPositionOrder starts off by looking up the actual position quantity, calculating the delta between
the actual and target quantity and issuing a market order to fill the difference. In many cases the
TargetPositionOrder differs little from sending a simple market order. Orders can take some time to fully
execute. In the meantime the target position may change. The target quantity of a TargetPositionOrder
can be altered at any point of time which will cause the order to re-evaluate its actual state and cancel or
modify currently pending order and issue a new order if necessary to match the expected target position.
The order also reacts intelligently to stray fills that can occur.
By default TargetPositionOrder is considered to be fully executed once its target position has been
reached. The order is then removed from the order book. Often however strategies might want to maintain
a particular position over a longer period of time. TargetPositionOrder can be issued with keepAlive
attribute set to true to make the order active until explicitly canceled. The order will transition into
Status#TARGET_REACHED state once fully executed and will stay there until the target is adjusted or the
order is canceled. A TargetPositionOrder can be created and sent as follows:
330
CONFIDENTIAL Execution Algos Retry and Back-off policies
order.setAccount(account);
order.setSecurity(security);
order.setQuantity(orderQuantity);
order.setSide(Side.BUY);
order.setKeepAlive(true);
order.setTarget(BigDecimal.valueOf(111.1));
getOrderService().sendOrder(order);
TrailingLimitOrder
A TrailingLimitOrder submits an order directly to the exchange with a limit price set a fixed distance
away from the current market price. The limit price is adjusted relative to the market price when the market
moves in favor of the order. The TrailingLimitOrder is typically used when entering a position on an
instrument with a Bullish view.
For a BUY order the limit price will be set a specific amount (defined by the trailingAmount parameter)
below the current market price. In case the market price rises, the limit price is increased once the specified
minimum amount (defined by the increment parameter) is exceeded. If the market price falls, the limit
price stays untouched. If the market price falls below the limit price the order will get filled by the exchange
(depending on adequate liquidity).
For a SELL order the limit price will be set a specific amount (defined by the trailingAmount parameter)
above the current market price. In case the market price falls, the limit price is decreased once the specified
minimum amount (defined by the increment parameter) is exceeded. If the market price rises, the limit
price stays untouched. If the market price rises above the limit price the order will get filled by the exchange
(depending on adequate liquidity).
331
CONFIDENTIAL Execution Algos Retry and Back-off policies
When the number of retries has exceeded the defined retry limit (default: 3 retries for each order), the entire
parent Order (all children Orders) will be cancelled.
332
CONFIDENTIAL Execution Algos Retry and Back-off policies
333
Chapter 25. CONFIDENTIAL
AlgoTrader supports Synthetic Securities & Derivative Spreads based on the two Entities Combination and
Component.
Combinations are handled like every other Security. A Combination consists of one or many Components.
Each component has a quantity.
For synthetic / non-tradable combinations the AlgoTrader Server generates Ticks based on the size of the
components of the combination and the current market values of the associated securities. This calculation is
handled by the module module-combination.epl which provides the Component Window.
Note
On executions AlgoTrader will create fills for each component and for the combination itself. As
a consequence there will be positions on all components as well as the combination itself.
334
CONFIDENTIAL Combination Example
A Combination is available to all strategies and can be subscribed/unsubscribed in the usual manner.
The example above shows a Combination based on 11 ES Mini September 2018 Futures and 3 ES Mini
December 2018 Futures. The example shows that the market price of the combination is based on the total
prices of both components, e.g. for the ask price:
getSubscriptionService().subscribeMarketDataEvent(strategyName, combination.getId());
getCombinationService().setComponentQuantity(
combinationSecurityId, componentSecurityId, quantity);
335
CONFIDENTIAL Remove a Component
getCombinationService().addComponentQuantity(
combinationSecurityId, componentSecurityId, quantity);
Important
If Components are modified directly in the database, it is necessary to clear the cache as
well as to call the method ServerManagementService.resetComponentWindow immediately
afterwards. If this is not done within a short period of time this might lead to miss-pricing of the
corresponding Combination. It is therefore preferable to modify Components via the AlgoTrader
Client or the CombinationService.
getCombinationService().removeComponent(combinationSecurityId, componentSecurityId);
336
Chapter 26. CONFIDENTIAL
Spring Services
26.1. Starter Classes
AlgoTrader provides the following starter classes to start up the system for the various operational modes
When downloading reference data (see Chapter 20, Reference Data) you need to have the following profiles
active: singleDataSource or pooledDataSource and the profile of the adapter you want to get reference
data from (see table below).
You can only have one adapter reference data profile enabled at a time.
When downloading historical data (see Section 19.3, “Historical Data Download”) you need to have the
following profiles active: singleDataSource or pooledDataSource, influxDB and the profile of the adapter
you want to get historical data from (see table below).
You can only have one adapter historical data profile enabled at a time.
• Simulation Starter
To run a back-test (see Chapter 5, Strategy Backtesting), you need to have the following profiles active: any
dataSource profile, simulation. If you are using InfluxDB for back testing, you also need to add influxDB.
When running strategy in embedded mode (see Section 3.2.1, “Embedded Mode”), you need to have the
following profiles activate: singleDataSource or pooledDataSource, live, embeddedBroker and html5 (if
you want to see/use the UI) and the market data, trading profiles.
If account data (see Chapter 21, Account Data) is required you also need the account profile (see table
below).
The system can be run with several market data, trading and account profiles in the same process.
If historical data (see Chapter 19, Historical Data) is required you also need one historicalData profile (see
table below) and influxDB. If you do not have a historical data provider but still want to store and retrieve
historical data using InfluxDB, you need to set noopHistoricalData in addition to influxDB.
• Server Starters
When running the AlgoTrader server in distributed mode (see Section 3.2.2, “Distributed Mode”), you need
to have the following profiles activate: singleDataSource or pooledDataSource, live, embeddedBroker
and html5 (if you want to see/use the UI) and the market data, trading profiles.
337
CONFIDENTIAL Spring Profiles
If account data (see Chapter 21, Account Data) is required you also need the account profile (see table
below).
The system can be run with several market data, trading and account profiles in the same process.
If historical data (see Chapter 19, Historical Data) is required you also need one historicalData profile (see
table below) and influxDB. If you do not have a historical data provider but still want to store and retrieve
historical data using InfluxDB, you need to set noopHistoricalData in addition to influxDB.
• Strategy Starters
For strategies running in distributed mode (see Section 3.2.2, “Distributed Mode”), it is sufficient to activate
the live Spring profile. In order for a strategy to use historical data, reference data or account related
information the profiles historicalData, referenceData and account have to be enabled in on the
strategy.
• Reset Starter
The ResetStarter can be used to reset the state of the database to a pre-defined state either before a
simulation or if a reset of live trading is required. For parameters and details, see Section 7.2.21, “Reset
Service”
The RestorePortfolioValueStarter can restore Portfolio Values for a specified strategy and time period
(see Section 7.2.12.2, “Portfolio Value Restoration Feature”)
General Profiles
• simulation: Contains Spring Beans that are used for Back Tests or when using the Exchange Simulator,
e.g. SimulationExecutor, SimulationOrderService and ResetService
• live (client side): Contains Spring Beans needed by Strategies in Live Trading: Esper Engine,
LifecycleManager, CacheManager & LookupService
• live (server-side) : Contains Spring Beans needed by the Server in Live Trading mode: e.g. Esper Engine
• noopHistoricalData: a no-operation HistoricalDataService. This profile is needed for cases where you
want to store/retrieve historical data in InfluxDB but no historical data adapter is active.
338
CONFIDENTIAL Spring Profiles
• embeddedBroker: embedded ActiveMQ broker, which is required for sending messages to the UI and to
strategies running in distributed mode
• inboundFix: Enables inbound FIX API, see Section 22.4, “Inbound FIX API”
• genericEventsService: means the strategy will require explicit subscription to generic events service
• pooledDataSource: c3p0 Pooled Data Source (typically used in live trading both in embedded and
distributed mode)
• singleDataSource: Spring Driver Manager Data Source (typically used by the Reference Data Starter and
Historical Data Starter)
• hybridDataSource: Data Source that propagates only reference data to the DB hybridDataSource (typically
used in backtesting)
Adapters
339
CONFIDENTIAL Spring Profiles
Bloomberg tDBFix
Tradebook
CoinAPI cNPMarketData cNPHistoricalData
cNPReferenceData
CoinMarketCap cMCHistoricalData
cMCReferenceData
EzeSoft / rTFix
RealTick
Fortex fTXFix fTXMarketData
JP Morgan jPMFix
Quandl qDLHistoricalData
340
CONFIDENTIAL Spring Profiles
SocGen sGFix
Note
All other services not mentioned above are active in all profiles.
-Dspring.profiles.active=iBMarketData,iBNative
341
Chapter 27. CONFIDENTIAL
• Dataset Configuration
• Simulation Settings
• Reporting Settings
• RMI Settings
• ActiveMQ Settings
• Jetty Settings
conf-core.properties contains settings that are only used by the core project:
• Esper Statements
• Hedging Settings
• ActiveMQ Settings
• Jetty Settings
• SSL Settings
• Mail Settings
• AlgoTrader UI Settings
In addition adapters may have their own settings file. e.g.conf-ib.properties for IB and conf-
bb.properties for BB.
342
CONFIDENTIAL Encrypting sensitive configuration values
Configuration parameters can be changed inside the .properties files. As an alternative configuration
parameters can be provided as VM Options in which case they will overwrite existing parameters inside
*.properties files.
-Dstatement.closePosition=false
Most configuration parameters are prefixed with a namespace (e.g. dataSource, simulation, statement, misc,
etc.)
In Docker based installations the recommended method for that is using Docker Secrets
1
For non-Docker installations it is possible to encrypt property value using Jasypt command line utility:
The encrypted value should be copied to relevant property file, e.g. to conf-bmx.properties. Alternatively
the properties can be changed via Section 2.4, “VM Options”:
#{"type":"String","label":"API Key"}
bmx.apiKey=ENC(Gv5bH18YmbavDnC3DExCMKTOh7wRq5VuKpeNo5tYmaALkpJw0ApEMA==)
The steps above should be done for each sensitive value (e.g. apiKey, apiSecret) of each adapter.
-Dconfig.encryption=true
Each time the system starts, the user will be prompted to enter the password.
1
http://www.jasypt.org/cli.html
343
CONFIDENTIAL Esper Variables
Note
344
Chapter 28. CONFIDENTIAL
SSL security can be activated through the following property in conf.properties. Alternatively the properties
can be changed via Section 2.4, “VM Options”:
By default AlgoTrader ships with a self-signed certificate which can be import into the browser. Please note
that modern browsers will show a warning when using self-signed certificates due to your domain name being
different from AlgoTrader's own domain.
It is therefore strongly recommended to procure a certificate from a major CA (certification authority) trusted
by common browsers. Alternatively you can create your own self-signed certificate for testing purposes, the
following command will created a certificate for the domain xxx.algotrader.com
To use SSL security please update the following properties in conf.properties. Alternatively the properties
can be changed via Section 2.4, “VM Options”:
# Keystore password
ssl.keystorePassword = password
When running with TLS transport security turned on AlgoTrader also enforces BASIC user authentication
with a user name and a password when logging into the HTML5 UI. User credentials can be provided in
conf.properties. Alternatively the properties can be changed via Section 2.4, “VM Options”:
345
CONFIDENTIAL Importing Certificate into Chrome Browser
# Web UI password
jetty.password = secret
1. On the page with the untrusted certificate, click Ctrl-Shift-I to open Developer Tools and go to Security
2. Click View Certificate / Details tab > Copy to File. Choose DER encoded binary (.CER)
3. Open up Chrome Settings > Show advanced settings > HTTPS/SSL > Manage Certificates.
4. Import the exported .CER file, save into "Trusted Root Certificate Authorities"
346
Chapter 29. CONFIDENTIAL
Metrics
In Simulation Mode the performance objective of the system is high-throughput, whereas in Live Trading Mode
the objective is low latency. To pinpoint potential performance bottlenecks, AlgoTrader has a built-in metrics
functionality.
Enabling this flag will cause additional metrics module to be deployed on SERVER strategy.
Note
If your strategy is using Esper modules you want to collect metrics from, you should deploy
metrics module to your strategy engine:
By default only resource-heavy statements will be logged - filtered by mean statement execution time.
Statements with mean execution time below the threshold will not be logged. The threshold can be configured
by metrics.engine.logging.thresholdMs parameter in conf.properties
Note
Subscriber time consumption is not included in statement metrics, whereas static method
invocation is included.
347
Chapter 30. CONFIDENTIAL
Logging
1
AlgoTrader logging is provided by Apache Log4j 2 framework. The Logging system is configured by means
of log4j2.xml file.
-DlogLevel=ERROR
30.1. log4j2.xml
Table 30.1. Default Log4j Appenders
Appender Description
StdOut Logs to Standard Out
StdErr Logs to Standard Error
LogEvent Custom UI appender. Sends log messages to UI
Appender Description
File Logs to an appending file
Mail Sends Email Messages on Errors
Note
• Problems with the Email Appender go to System.err (on server see nohup.log)
• To prevent saturation of the logs several loggers have been defined with a logging level higher
than the root log level
2
Detailed description of Log4j2 appenders and advanced configuration can be found at the Apache Logging
site.
1
http://logging.apache.org/log4j/2.x/
2
http://logging.apache.org/log4j/2.x/manual/configuration.html
348
Chapter 31. CONFIDENTIAL
Reporting
AlgoTrader provides a convenient way to create custom CSV reports for strategy specific reporting. All relevant
classes are available inside the package ch.algotrader.report.
public OrderReport() {
String[] header = new String[] { "Date", "Symbol", "Quantity", "Signal" };
this.reporter = new ListReporter(Report.generateFile("OrderReport"), header);
}
public void write(Date date, String symbol, int quantity, String signal) {
this.reporter.write(date, symbol, quantity, signal);
}
}
This will create a .csv report named OrderReport.csv inside the directory /files/report/ which contains
the columns Date, Symbol, Quantity, Signal.
Some Reports are available out-of-the-box, for further details please see Section 5.5, “Performance Statistics”
349
Chapter 32. CONFIDENTIAL
Monitoring
32.1. Technical monitoring
1
Available under our the /monitoring endpoint, users can find a comprehensive monitoring tool that exposes
various important metrics both real-time and historical. It allows you review:
• Memory consumption
• CPU usage
• etc
1
localhost:9090/monitoring
350
CONFIDENTIAL Technical monitoring
You can also find detailed information on response time of your operations for example order requests:
On top of these there are also a set of admin functionalities exposed. You would typically need to install different
tools to perform tasks such as reviewing OS processes or taking a snapshot of the heap memory.
351
CONFIDENTIAL Health check
This information is exposed via Rest API and as a web page. Example of the health check page:
{
"JVM": {
"msg": "HeapMemoryUsage: init = 327155712(319488K) used = 497207792(485554K)
committed = 838336512(818688K) max = 4632608768(4524032K), NonHeapMemoryUsage: init =
2555904(2496K) used = 229961040(224571K) committed = 238157824(232576K) max = -1(-1K),
ThreadCount: 128, Uptime: 9640403ms, GcCollectionTime: 24082ms, GcCollectionCount: 659",
"status": "ALIVE"
},
"ComboPooledDataSource": {
"msg": "Connection is valid",
"status": "ALIVE"
},
"HazelcastInstance": {
"msg": "HazelcastInstance is running",
352
CONFIDENTIAL Health check
"status": "ALIVE"
},
"CNB-session": {
"msg": "loggedOn",
"status": "ALIVE"
},
"CNB-adapter": {
"msg": "status(es): 404 Not Found",
"status": "DEAD"
},
"CNB-rest-session": {
"msg": "404 Not Found",
"status": "DEAD"
},
"System": {
"msg": "all Alive",
"status": "ALIVE"
}
}
Rest endpoints:
• /util/health: returns JSON map with service name mapped to its health state
UI which automatically refresh health status of all components and provides the same information, URL: http://
localhost:9090/health.html
Health state is published via ActiveMQ and STOMP, message topics are (for different status levels - alive,
unhealthy, dead):
Note: all health statuses are propagated to the strategy via method described below:
353
CONFIDENTIAL Health check
354
CONFIDENTIAL
Warning
The purpose of this Strategy is to demonstrate capabilities of AlgoTrader. Do not use it with
a Live Trading Account and real Money! The strategy might lead to large losses. Even when
modifying or extending the Strategy use caution before trading it Live.
The Strategy trades the EUR.USD FX Market and is based on a simple Breakout Indicator.
The Strategy opens a long (short) position when the current price exceeds (falls below) the maximum
(minimum) of the last n bars. After a new position is opened, a profit target price is set as well as a stop loss.
If either profit target or stop is reached, the position is closed. If neither stop nor profit target is reached until
the end of n-bars, the position is closed.
Positions are sized based on a defined leverage and the current Net Liquidation Value. All Orders are placed
as Market Orders. The initial account size is EUR 1'000'000.
A.2. Example
The following 5-min bar chart gives an example of the BreakOut strategy. At 10:20 an aggregation of the last
5 bars between 09:55 and 10:20 is created, based on which the upper limit at 1113.85 and the lower limit at
1110.53 are calculated. At 10:22:37 the upper limit is crossed for the first time and a long position is entered
and both a profit target at 1116.40 and a stop loss at 1111.49 are set automatically. At 10:31:52 the profit target
is reached and the position is automatically closed.
Note
This example strategy is a good example of combining a bar based strategy with tick-by-tick
based actions. The creation of the upper and lower limits are based on the five 5-min bars but the
opening and closing of the position takes place as soon as the limits are reached without waiting
for the current bar to finish. This is one of the unique features of AlgoTrader that distinguishes
it form other trading platforms that operate exclusively based on bars.
355
CONFIDENTIAL Implementation
A.3. Implementation
The main artifacts needed for the Implementation of a new Strategy are described in Chapter 4, Strategy
Development.
The following list will give an overview of the specific artifacts implemented by the BreakOut Strategy (Note:
Most of the functionality is documented via Javadoc or Esper comments):
/src/main/java/ch/algotrader/strategy/breakOut/BreakOutService.java
The strategy service class providing the main entry method invoked by the Esper ENTRY_LONG and
ENTRY_SHORT statements:
/src/main/java/ch/algotrader/strategy/breakOut/BreakOutConfig.java
Contains all strategy configuration items
/src/main/resources/module-breakOut.epl
Esper Module containing all statements for this strategy:
• ON_BOUND_SET_TRIGGERS: sets the upperTrigger and lowerTrigger based on the minimum and
maximum of the last n bars
356
CONFIDENTIAL Installation & Startup
• ENTRY_LONG / ENTRY_SHORT: open position if last tick is higher (lower) than previous n bars.
• CLOSE_LONG_POSITION / CLOSE_SHORT_POSITION: Close position if last tick is higher (lower) than target
or lower (lower) than stop
• CLOSE_OPEN_POSITION: Close position if neither target nor stop are reached before the end of n-bars
/src/main/resources/breakOut-default.properties
Contains default parameters used by the strategy (e.g. lengthOfBar and numberOfBars)
/src/main/resources/META-INF/esper-breakOut.cfg.xml
Contains event-types definitions (i.e. CurrentValue), variables (e.g. lengthOfBar and numberOfBars) .
/src/main/resources/META-INF/applicationContext-client-breakOut.xml
Contains the Spring Bean definitions for breakOutConfigParams, breakOutConfig, breakOutEngine,
breakOutService.
/src/main/resources/db/mysql/mysql-breakout.sql
Contains the MySQL database records. Needs to be imported into the database before running the strategy
with the MySQL database.
To start the Strategy please see the explanations in Chapter 3, Starting AlgoTrader.
Download the Examples project zip file and unpack it in a directory of your choosing: https://
www.algotrader.com/downloads/latest-examples
Note
user name and password will be provided when signing up for an AlgoTrader license
If you need an older AlgoTrader version, login to our maven repository (https://repo.algotrader.com/nexus)
and click on Browse on the left and select code-general.
357
CONFIDENTIAL Installation & Startup
You can also import this tick data csv file into InfluxDB through the historical data manager (see
Section 11.3, “Historical Data Manager” Historical Data Import) and run simulations based on the Influx
data.
To start the strategy in live trading mode on a development workstation please execute the following steps:
358
CONFIDENTIAL Installation & Startup
load the strategy specific script into the MySQL database: breakOut/src/main/resources/db/mysql/
mysql-data.sql
To start the strategy in live trading mode on a productive server please execute the following steps:
https://gitlab.algotrader.com/general/examples/blob/master/breakOut/docker-compose.yml
docker-compose up -d
Note
Prior to starting the strategy for the very first time please start the AlgoTrader server by itself by
executing the following command inside /bootstrap/launch. this will load the MySQL sample
data
359
CONFIDENTIAL
Warning
The purpose of this Strategy is to demonstrate the capabilities of AlgoTrader. Do not use it with
a Live Trading Account and real Money! Due to frequent Draw Downs, it might lead to large
losses. Even when modifying or extending the Strategy use caution before trading it Live.
The Strategy trades the EUR.USD FX Market and is based on the Stairstep Breakouts (SSBO) Indicator
1 2
that is presented on www.forexfactory.com by forexhard .
The Trading Idea behind the Strategy is the following: Markets will often stay within a trading range for
a considerable amount of time before they break-out in either direction. The following Chart shows some
examples of trading ranges.
After a break-out markets might return back into the trading range but will eventually make a major move in
one direction.
According to the defined settings, the Strategy looks for a trading range with a minimum length in Minutes (e.g.
90 Minutes) and a maximum width in Pips (e.g. 30 Pips). The chart below displays a typical trading range in
dark blue color.
1
https://www.forexfactory.com/showthread.php?t=302007
2
https://www.forexfactory.com/forexhard
360
CONFIDENTIAL Trading Idea
As soon as trading range has been built according to these parameters, the Strategy waits for the first break-
out to happen. The strategy enters the market in the direction of the breakout as soon as a small margin called
buffer (dashed red line, e.g. 5 Pips) has been crossed. In the example above, this happened at 10:48.
The Strategy will set a stop at the opposite side of the box (e.g. 1.3618 = 39 Pips) and a target with the same
distance (e.g. 1.3544 = 39 Pips).
If the target is reached, the Strategy resets itself and waits for a new Box to build itself.
If the Position gets stopped out (at the opposite side of the Box), The Strategy waits for the next break-out to
happen (on the same Box) and enters the market again after the buffer-line has been crossed. This time the
size of the position is doubled in order to cover the losses of the first entry, in case the target is reached this
time around. Position size is doubled up to a defined maximum. Because of this doubling the system can be
3
categorized as a Martingale Strategy (see Martingale Betting System ).
The following State Chart Diagram depicts the different states the Strategy will pass through:
3
https://en.wikipedia.org/wiki/Martingale_%28betting_system%29
361
CONFIDENTIAL Trading Idea
The default setting of the Strategy will go up to level 5 which will result in a position size of 16 times the original
size. So the individual sizes on the different levels will be: 1, 2, 4, 8 & 16. Each successful series will therefor
present a profit of 1 unit. Very often series will be successful on a level that is below the maximum level (e.g.
below level 5). However if the Strategy has a loosing set, which will be terminated at the maximum level (e.g.
at level 5), there will be a loss of 16 times the original position size.
The Strategy will often have multiple successful series in a row before having one major draw down. A typical
performance chart will therefore look like this:
To prevent having open positions over the weekend the Strategy does not create any new boxes after a defined
time on Friday (e.g. 4PM). Also, it will terminate a potential ongoing series at a defined time on Friday (e.g.
10PM)
362
CONFIDENTIAL Implementation
B.2. Implementation
The main artifacts needed for the Implementation of a new Strategy are described in Chapter 4, Strategy
Development.
The following list will give an overview of the specific artifacts implemented by the Box Strategy. Most of the
functionality is documented via Javadoc or Esper comments:
/src/main/java/ch/algotrader/strategy/box/BoxService.java
The strategy service class providing the main methods invoked by different Esper statements.
/src/main/java/ch/algotrader/strategy/box/BoxConfig.java
Contains all strategy configuration items
/src/main/java/ch/algotrader/strategy/box/Box.java
A POJO class representing all properties of a Box (e.g. top, bottom, startDateTime and endDateTime)
/src/main/java/ch/algotrader/strategy/box/State.java
A Java Enum representing the different States the Strategy can pass through (INIT, CREATED, LONG, SHORT,
FLAT)
/src/main/resources/module-box-init.epl
Esper Module containing statements for capturing market data, creating variables and creating Boxes. In
Live Trading, these statements will be deployed before the pre feeding.
/src/main/resources/module-box-run.epl
Esper Module containing statements that invoke the business actions on the BoxService (entry,
takeProfit, closePosition, reverse and terminateSeries). In Live Trading these statements will be
deployed after pre-feeding is finished.
/src/main/resources/box-default.properties
Contains parameters used by the strategy (e.g. boxLength and boxRange)
/src/main/resources/META-INF/esper-box.cfg.xml
Contains event-types definitions (i.e. CurrentValue), imports (i.e. Box and State), variables (e.g.
boxLength and boxRange)
/src/main/resources/META-INF/applicationContext-client-box.xml
Contains the Spring Bean definitions for boxConfigParams, boxConfig,boxEngine, boxService.
/src/main/resources/db/mysql/mysql-box.sql
Contains the MySQL database records. Needs to be imported into the database before running the strategy
with the MySQL database.
/src/main/resources/html5
HTML5 and JavaScript files needed for the strategy custom web UI
363
CONFIDENTIAL Strategy Monitoring
To start the Strategy please see the explanations in Chapter 3, Starting AlgoTrader.
Note
It might be necessary to fully reload the browser on first startup to show the custom widget using
Ctrl + Shift + R.
364
CONFIDENTIAL Installation & Startup
Download the Examples project zip file and unpack it in a directory of your choosing: https://
www.algotrader.com/downloads/latest-examples
Note
user name and password will be provided when signing up for an AlgoTrader license
If you need an older AlgoTrader version, login to our maven repository (https://repo.algotrader.com/nexus)
and click on Browse on the left and select code-general.
365
CONFIDENTIAL Installation & Startup
You can also import this bar data csv file into InfluxDB through the historical data manager (see
Section 11.3, “Historical Data Manager” Historical Data Import) and run simulations based on the Influx
data.
To start the strategy in live trading mode on a development workstation please execute the following steps:
load the strategy specific script into the MySQL database: /box/src/main/resources/db/mysql/mysql-
data.sql
To start the strategy in live trading mode on a productive server please execute the following steps:
https://gitlab.algotrader.com/general/examples/blob/master/box/docker-compose.yml
366
CONFIDENTIAL Installation & Startup
docker-compose up -d
Note
Prior to starting the strategy for the very first time please start the AlgoTrader server by itself by
executing the following command inside /bootstrap/launch. this will load the MySQL sample
data
367
CONFIDENTIAL
Warning
The purpose of this Strategy is to demonstrate capabilities of AlgoTrader. Do not use it with
a Live Trading Account and real Money! The strategy might lead to large losses. Even when
modifying or extending the Strategy use caution before trading it Live.
1
The Pairs Trading strategy uses the web service www.pairtradinglab.com to trade pairs of US equities
The strategy works by monitoring the performance of two historically correlated securities. When the correlation
between those two securities demonstrate a temporary weakness, a pairs trade can be conducted by shorting
the outperforming stock and going long on the under performing stock. Basically, one is betting that the spread
between the two will converge eventually.
1
https://www.pairtradinglab.com/
368
CONFIDENTIAL Implementation
• Verify a pair trading idea and inspect the behavior and robustness of pairs
• Search the PTL database of more than 10 million pre-analyzed U.S. market pairs using complex filters
• Create and maintain lists of interesting pairs, rate them, and tag them
Then the AlgoTrader - Pair Trading Lab integration can be used to download selected pairs and/or portfolio of
pairs from Pair Trading Lab into AlgoTrader where they can then be traded automatically
2
The AlgoTrader based pairs trading strategy implementation is based on the Ratio Model
C.2. Implementation
The main artifacts needed for the Implementation of a new Strategy are described in Chapter 4, Strategy
Development.
The following list will give an overview of the specific artifacts implemented by the Pairs Trading Strategy (Note:
Most of the functionality is documented via Javadoc or Esper comments):
/src/main/java/ch/algotrader/strategy/pairstrading/service/PairsTradingService.java
The strategy service class providing the main trading logic
/src/main/java/ch/algotrader/strategy/pairstrading/csv/CsvImporter.java
Import utility to download pairs from Pair Trading Lab and configure them in AlgoTrader
/src/main/java/ch/algotrader/strategy/pairstrading/util/PairsTradingConfig.java
Contains all strategy configuration items
/src/main/java/ch/algotrader/strategy/pairstrading/util/PairsTradingCalc.java
Contains the logic of the ratio model
/src/main/resources/module-pairstrading.epl
Esper Module containing all statements for this strategy:
2
https://wiki.pairtradinglab.com/wiki/Pair_Trading_Models#Ratio_Model
369
CONFIDENTIAL Installation & Startup
• UPDATE_HISTORICAL_BARS & DAILY_RECALC: daily triggers for downloading historical data and updating
entry thresholds
/src/main/resources/conf-pairstrading.properties
Contains default parameters used by the strategy
/src/main/resources/META-INF/esper-pairstrading.cfg.xml
Contains event-types definitions (i.e. PairEvent and SignalEvent)
/src/main/resources/META-INF/applicationContext-client-pairstrading.xml
Contains pairsTradingParams, pairsTradingConfig, pairsTradingEngine, pairsTradingService
as well as the strategy specific beans csvImporter, orderSubmissionService and
pairsTradingLabNavigator.
/src/main/resources/db/mysql/mysql-pairstrading.sql
Contains the MySQL database records. Needs to be imported into the database before running the strategy
with the MySQL database.
/src/main/resources/html5
HTML5 and JavaScript files needed for the strategy custom web UI
To start the Strategy please see the explanations in Chapter 3, Starting AlgoTrader.
Extract Portfolio ID
csvImportPortfolio needs to be extracted from the URL when clicking on pair in the PTL Trader / Portfolio
Manager
3
https://www.pairtradinglab.com/index.php?command=register
4
https://www.pairtradinglab.com/portfolio-manager
370
CONFIDENTIAL Installation & Startup
To start the strategy in live trading mode on a development workstation please execute the following steps:
Download the Examples project zip file and unpack it in a directory of your choosing: https://
www.algotrader.com/downloads/latest-examples
Note
user name and password will be provided when signing up for an AlgoTrader license
If you need an older AlgoTrader version, login to our maven repository (https://repo.algotrader.com/nexus)
and click on Browse on the left and select code-general.
371
CONFIDENTIAL Installation & Startup
To start the strategy in live trading mode on a productive server please execute the following steps:
https://gitlab.algotrader.com/general/examples/blob/master/pairstrading/docker-compose.yml
372
CONFIDENTIAL Strategy Monitoring
docker-compose up -d
Note
Prior to starting the strategy for the very first time please start the AlgoTrader server by itself by
executing the following command inside /bootstrap/launch. this will load the MySQL sample
data
373
CONFIDENTIAL Strategy Monitoring
Note
It might be necessary to fully reload the browser on first startup to show the custom widget using
Ctrl + Shift + R.
• PairInfo & Pairs: current pair definitions as downloaded from Pair Trading Lab. movingAvg and
standardDev are calculated on a daily basis (by the Esper statement UPDATE_HISTORICAL_BARS) using
historical closing prices
• Signals: intraday pair values based on live data. ratio shows the current price ratio between individual
instruments of a pair. zScore shows the current ratio relative to the Bollinger band around the ratio time
series. When the zScore hits the zScoreEntry threshold a position is entered, and when the zScore hits
the zScoreExit threshold the position is closed. If the zScore happens to be above zScoreMax (e.g. after
a large overnight gap) no new position will be opened. The signal field shows the current state of a pair
(i.e. LONG, SHORT, EXIT & HOLD)
374
CONFIDENTIAL Strategy Monitoring
• The action Import Historical Bars is used to import historical closing prices of all instruments for the
relevant look back period. This action is automatically executed once a day. In addition it can be invoked
manually at any time.
• The action Re-Calc Entry Thresholds is used to update movingAvg and standardDev based on historical
data in the database. This action is automatically executed once a day. In addition it can be invoked manually
at any time.
• The action Import Pairs imports and/or update pairs from Pair Trading Lab.
375
CONFIDENTIAL
Warning
The purpose of this Strategy is to demonstrate capabilities of AlgoTrader. Do not use it with
a Live Trading Account and real Money! The strategy might lead to large losses. Even when
modifying or extending the Strategy use caution before trading it Live.
The strategy trades US equity IPOs (initial public offering). When a new stock is launched on the exchange
for the first time the strategy tries to realize trading profits of the first trading day. New IPOs are announced on
1
web pages like IPOScoop together with an indicative open price.
1
https://www.iposcoop.com/
376
CONFIDENTIAL Strategy Monitoring
Note
It might be necessary to fully reload the browser on first startup to show the custom widget using
Ctrl + Shift + R.
Inside the custom widget the user can enter a new IPO to be traded by populating the following fields:
• Symbol to be traded
• Multiplier to be applied to the opening price for secondary orders (see below)
377
CONFIDENTIAL Implementation
For each symbol entered, the strategy will place orders at a configurable time in the morning (e.g. 4:30am).
Note
Trading of IPOs usually starts within 2-3 hours after the official market open
Definitions:
The strategy will place a limit-at-the-open order at user-defined limit price for the entry quantity specified above.
Using a limit-at-the-open order will cause the order to participate in the opening auction of the IPO.
Immediately following the open of regular trading, the strategy will check to see if the entire cash commitment
for the given symbol has been exhausted.
2. If the cash commitment has not been exhausted and the stock opened above the LIMIT PRICE, the unfilled
quantity will be cancelled, and no further action will be taken by the strategy.
3. Otherwise, if the cash commitment for the name has NOT been exhausted a secondary limit order is placed
as per below:
If the secondary order is not filled by a configurable end time (e.g. 3:30pm), it will be cancelled by the system.
Immediately after executing any buy orders, the strategy will place a market-on-close order for the entire
position.
D.3. Implementation
The main artifacts needed for the Implementation of a new Strategy are described in Chapter 4, Strategy
Development.
The following list will give an overview of the specific artifacts implemented by the IPO Strategy (Note: Most of
the functionality is documented via Javadoc or Esper comments):
/src/main/java/ch/algotrader/strategy/ipo/IPOService.java
The strategy service class providing the main trading logic
378
CONFIDENTIAL Installation & Startup
/src/main/java/ch/algotrader/strategy/ipo/IPO.java
Java POJO class representing a single IPO
/src/main/resources/module-ipo.epl
Esper Module containing all statements for this strategy:
• SEND_LIMIT_ORDERS: triggers the secondary order service once the at-the-open order has been fully
executed and the official open price (via GenericTickVO) has been disseminated. An Esper Join is used
for this since either one of those events can arrive first
• DAILY_CLEAN_UP: unsubscribes all market data and resets the list of IPOs an initial capital
/src/main/resources/conf-ipo.properties
Contains default parameters used by the strategy
/src/main/resources/META-INF/esper-ipo.cfg.xml
Contains Esper variables for the strategy
/src/main/resources/META-INF/applicationContext-client-ipo.xml
Contains ipoConfigParams, ipoEngine & ipoService.
/src/main/resources/db/mysql/mysql-ipo.sql
Contains the MySQL database records. Needs to be imported into the database before running the strategy
with the MySQL database.
/src/main/resources/html5
HTML5 and JavaScript files needed for the strategy custom web UI
To start the Strategy please see the explanations in Chapter 3, Starting AlgoTrader.
Download the Examples project zip file and unpack it in a directory of your choosing: https://
www.algotrader.com/downloads/latest-examples
Note
user name and password will be provided when signing up for an AlgoTrader license
379
CONFIDENTIAL Installation & Startup
If you need an older AlgoTrader version, login to our maven repository (https://repo.algotrader.com/nexus)
and click on Browse on the left and select code-general.
To start the strategy in live trading mode on a productive server please execute the following steps:
https://gitlab.algotrader.com/general/examples/blob/master/ipo/docker-compose.yml
380
CONFIDENTIAL Installation & Startup
docker-compose up -d
Note
Prior to starting the strategy for the very first time please start the AlgoTrader server by itself by
executing the following command inside /bootstrap/launch. this will load the MySQL sample
data
381
CONFIDENTIAL
Warning
The purpose of this Strategy is to demonstrate capabilities of AlgoTrader. Do not use it with
a Live Trading Account and real Money! The strategy might lead to large losses. Even when
modifying or extending the Strategy use caution before trading it Live.
The Strategy is a simple example without Esper that trades the EUR.USD FX Market and is based on two
exponential moving averages.
The Strategy sends a BUY order when shorter moving average (e.g. 10-days) crosses above the longer moving
average (e.g. 20-days) and it sends a SELL order when shorter moving average crosses below the longer
moving average.
E.2. Implementation
The main artifacts needed for the Implementation of a new Strategy are described in Chapter 4, Strategy
Development.
382
CONFIDENTIAL Installation & Startup
1
The strategy uses the TA4J library which provides over 100 technical indicator that are computed on a
continuous basis.
/src/main/java/ch/algotrader/strategy/ema/EMAService.java
The strategy service class providing onStart and onBar method containing the trading logic
To start the Strategy please see the explanations in Chapter 3, Starting AlgoTrader.
Download the Examples project zip file and unpack it in a directory of your choosing: https://
www.algotrader.com/downloads/latest-examples
Note
user name and password will be provided when signing up for an AlgoTrader license
If you need an older AlgoTrader version, login to our maven repository (https://repo.algotrader.com/nexus)
and click on Browse on the left and select code-general.
1
https://github.com/mdeverdelhan/ta4j-origins
383
CONFIDENTIAL Installation & Startup
You can also import this tick data csv file into InfluxDB through the historical data manager (see
Section 11.3, “Historical Data Manager” Historical Data Import) and run simulations based on the Influx
data.
To start the strategy in live trading mode on a development workstation please execute the following steps:
load the strategy specific script into the MySQL database: /ema/src/main/resources/db/mysql/mysql-
data.sql
To start the strategy in live trading mode on a productive server please execute the following steps:
https://gitlab.algotrader.com/general/examples/blob/master/ema/docker-compose.yml
384
CONFIDENTIAL Installation & Startup
docker-compose up -d
Note
Prior to starting the strategy for the very first time please start the AlgoTrader server by itself by
executing the following command inside /bootstrap/launch. this will load the MySQL sample
data
385
CONFIDENTIAL
Warning
The purpose of this Strategy is to demonstrate capabilities of AlgoTrader. Do not use it with
a Live Trading Account and real Money! The strategy might lead to large losses. Even when
modifying or extending the Strategy use caution before trading it Live.
The Strategy is a simple example that places random orders at regular intervals. The Random strategy is used
1
for the AlgoTrader Demo .
F.2. Implementation
The main artifacts needed for the Implementation of a new Strategy are described in Chapter 4, Strategy
Development.
/src/main/java/ch/algotrader/strategy/random/RandomService.java
The strategy service class providing the main methods invoked by different Esper statements.
/src/main/java/ch/algotrader/strategy/random/RandomConfig.java
Contains all strategy configuration items
/src/main/resources/module-random.epl
Esper Module containing statements to place and cancel orders as well as update subscriptions once a day.
/src/main/resources/conf-random.properties
Contains parameters used by the strategy (e.g. positionMax and orderMax)
/src/main/resources/META-INF/esper-random.cfg.xml
Contains variables (i.e. placeOrderInterval and cancelOrderInterval)
/src/main/resources/META-INF/applicationContext-client-random.xml
Contains the Spring Bean definitions for randomConfigParams, randomConfig, randomEngine,
randomService.
/src/main/resources/db/mysql/mysql-data.sql
Contains the MySQL database records. Needs to be imported into the database before running the strategy
with the MySQL database.
1
http://html5.algotrader.com/
386
CONFIDENTIAL Installation & Startup
To start the Strategy please see the explanations in Chapter 3, Starting AlgoTrader.
Download the Examples project zip file and unpack it in a directory of your choosing: https://
www.algotrader.com/downloads/latest-examples
Note
user name and password will be provided when signing up for an AlgoTrader license
If you need an older AlgoTrader version, login to our maven repository (https://repo.algotrader.com/nexus)
and click on Browse on the left and select code-general.
387
CONFIDENTIAL Installation & Startup
To start the strategy in live trading mode on a development workstation please execute the following steps:
load the strategy specific scrip into the MySQL database: /random/src/main/resources/db/mysql/
mysql-data.sql
To start the strategy in live trading mode on a productive server please execute the following steps:
https://gitlab.algotrader.com/general/examples/blob/master/random/docker-compose.yml
docker-compose up -d
Note
Prior to starting the strategy for the very first time please start the AlgoTrader server by itself by
executing the following command inside /bootstrap/launch. this will load the MySQL sample
data
388
CONFIDENTIAL Installation & Startup
389
CONFIDENTIAL
Warning
The purpose of this Strategy is to demonstrate capabilities of AlgoTrader. Do not use it with
a Live Trading Account and real Money! The strategy might lead to large losses. Even when
modifying or extending the Strategy use caution before trading it Live.
The spreader is a pair trading strategy that seeks to either short or buy the spread between EURUSD@IB and
GBPUSD@IB when the value of the spread between the price of both instruments breaches a certain threshold.
The Strategy enters a LONG/SHORT position if the spread goes below the "go long" threshold and enters a
SHORT/LONG position if the spread goes over the "go short" threshold.
Positions are closed either with profit (spread moves favourably by the take profit offset) or with loss (spread
moves unfavourably by the stop loss offset).
G.2. Implementation
The main artifacts needed for the Implementation of a new Strategy are described in Chapter 4, Strategy
Development.
/src/main/java/ch/algotrader/strategy/SpreaderService.java
The strategy service class providing the main methods invoked by different Esper statements.
/src/main/java/ch/algotrader/strategy/SpreaderConfig.java
Contains all strategy configuration items
/src/main/java/ch/algotrader/strategy/State.java
Defines the state the strategy can be in. (LONG, SHORT, FLAT, PENDING_LONG, PENDING_SHORT,
PENDING_FLAT)
/src/main/resources/conf-spreader.properties
Contains parameters used by the strategy (e.g. firstSecurityId and secondSecurityId and
firstSecurityFeedType and secondSecurityFeedType)
/src/main/resources/META-INF/applicationContext-client-spreader.xml
Contains the Spring Bean definitions for spreaderConfig, spreaderConfigParams, spreaderEngine,
spreaderService.
390
CONFIDENTIAL Installation & Startup
/src/main/resources/db/mysql/mysql-data.sql
Contains the MySQL database records. Needs to be imported into the database before running the strategy
with the MySQL database.
To start the Strategy please see the explanations in Chapter 3, Starting AlgoTrader.
Download the Examples project zip file and unpack it in a directory of your choosing: https://
www.algotrader.com/downloads/latest-examples
Note
user name and password will be provided when signing up for an AlgoTrader license
If you need an older AlgoTrader version, login to our maven repository (https://repo.algotrader.com/nexus)
and click on Browse on the left and select code-general.
391
CONFIDENTIAL Installation & Startup
To start the strategy in live trading mode on a development workstation please execute the following steps:
load the strategy specific scrip into the MySQL database: /spreader/src/main/resources/db/mysql/
mysql-data.sql
To start the strategy in live trading mode on a productive server please execute the following steps:
https://gitlab.algotrader.com/general/examples/blob/master/spreader/docker-compose.yml
docker-compose up -d
Note
Prior to starting the strategy for the very first time please start the AlgoTrader server by itself by
executing the following command inside /bootstrap/launch. this will load the MySQL sample
data
392
CONFIDENTIAL Installation & Startup
393
CONFIDENTIAL
Warning
The purpose of this Strategy is to demonstrate capabilities of AlgoTrader. Do not use it with
a Live Trading Account and real Money! The strategy might lead to large losses. Even when
modifying or extending the Strategy use caution before trading it Live.
Delta hedging is an options strategy that aims to reduce or hedge, the risk associated with price movements
in the underlying asset. The approach uses Futures to offset the risk to an entire portfolio of holdings. The
investor tries to reach a delta neutral state and not have a directional bias on the hedge.
Since delta hedging attempts to neutralize or reduce the extent of the move in an option's price relative to the
asset's price, it requires a constant rebalancing of the hedge.
The Strategy tracks all position changes and calculates deltas for each position every 10 seconds. Every 30
seconds it calculates portfolio average deltas and adjusted market values.
Depending on the results - strategy hedges positions using Futures until it reaches a delta neutral state.
H.2. Implementation
The following list will give an overview of the specific artifacts implemented by the Delta Strategy. Most of the
functionality is documented via comments:
/src/main/java/ch/algotrader/strategy/delta/DeltaService.java
The strategy service class providing the all the logic.
/src/main/java/ch/algotrader/strategy/delta/DeltaConfig.java
Contains all strategy configuration items
/src/main/java/ch/algotrader/strategy/delta/DeltaSnapshotVO.java
A POJO class representing current state of security
/src/main/java/ch/algotrader/strategy/delta/DeltaEventVO.java
A POJO class representing the collection of DeltaSnapshotVO containting current state of entire portfolio
/src/main/resources/delta-default.properties
Contains parameters used by the strategy
394
CONFIDENTIAL Strategy Monitoring
/src/main/resources/META-INF/applicationContext-client-delta.xml
Contains the Spring Bean definitions for deltaConfigParams, deltaConfig, deltaEngine, deltaService
/src/main/resources/META-INF/esper-delta.cfg.xml
Contains event-types definitions
/src/main/resources/db.mysql/mysql-data.sql
Contains the MySQL database records. Needs to be imported into the database before running the strategy
with the MySQL database.
/src/main/resources/html5
HTML5 and JavaScript files needed for the strategy custom web UI
Download the Examples project zip file and unpack it in a directory of your choosing: https://
www.algotrader.com/downloads/latest-examples
395
CONFIDENTIAL Installation & Startup
Note
user name and password will be provided when signing up for an AlgoTrader license
If you need an older AlgoTrader version, login to our maven repository (https://repo.algotrader.com/nexus)
and click on Browse on the left and select code-general.
load the strategy specific script into the MySQL database: /delta/src/main/resources/db.mysql/
mysql-data.sql
396
CONFIDENTIAL Installation & Startup
To start the strategy in live trading mode on a productive server please execute the following steps:
https://gitlab.algotrader.com/general/examples/blob/master/delta/docker-compose.yml
docker-compose up -d
Note
Prior to starting the strategy for the very first time please start the AlgoTrader server by itself by
executing the following command inside /bootstrap/launch. this will load the MySQL sample
data
397
CONFIDENTIAL
Warning
The purpose of this Strategy is to demonstrate capabilities of AlgoTrader. Do not use it with
a Live Trading Account and real Money! The strategy might lead to large losses. Even when
modifying or extending the Strategy use caution before trading it Live.
A short strangle is an options strategy comprised of selling both a call option and a put option with the
same strike price and expiration date. It is used when the trader believes the underlying asset will not move
significantly higher or lower over the lives of the options contracts. The maximum profit is the amount of
premium collected by writing the options. The potential loss can be unlimited, so it is typically a strategy for
more advanced traders.
Short strangles allow traders to profit from the lack of movement in the underlying asset, rather than having to
place directional bets hoping for a big move either higher or lower. Premiums are collected when the trade is
opened with the goal to let both the put and call expire worthless. However, chances that the underlying asset
closes exactly at the strike price at the expiration is low, and that leaves the short strangle owner at risk for
assignment. However, as long as the difference between asset price and strike price is less than the premiums
collected, the trader will still make a profit.
Advanced traders might run this strategy to take advantage of a possible decrease in implied volatility. If implied
volatility is unusually high without an obvious reason for it being that way, the call and put may be overvalued.
In this case, the goal would be to wait for volatility to drop and then close the position for a profit without waiting
for expiration.
398
CONFIDENTIAL Implementation
This example strategy demonstrates a typical options trading strategy where the subscribed instruments
change throughout the simulation process (i.e. when options expire new options need to be subscribed).
On startup the strategy will subscribe to the underlying S&P Index. Then on the first tick of the S&P
Index the strategy will determine Put and Call options with a minimum remaining time to expiration of
daysToExpirationOnOpen.
A standard Strangle strategy will use Put and Call options with the same strike (the current market price). By
setting the strategy parameter moneyness to a non-zero amount the Put Option will have a strike of moneyness
below the current market price and the Call option will have a strike of moneyness above the current market
price. By setting moneyness to a non-zero amount the strategy becomes a Short Strangle strategy.
After subscribing to the newly established Put and Call Option the strategy will wait for the first tick of each
options and then place corresponding SELL orders.
The strategy parameter daysToExpirationOnClose then defines the number of days prior to expiration of the
options the strategy will close open positions. Upon closing positions the strategy will unsubscribe the current
option market data subscriptions and establish a new set of options to enter positions into.
I.2. Implementation
The following list will give an overview of the specific artifacts implemented by the Short Strangle Strategy.
Most of the functionality is documented via comments:
399
CONFIDENTIAL Installation & Startup
/src/main/java/ch/algotrader/strategy/shortstrangle/ShortStrangleService.java
The strategy service class providing the all the logic.
/src/main/resources/conf-shortstrangle.properties
Contains parameters used by the strategy
/src/main/resources/META-INF/applicationContext-client-shortstrangle.xml
Contains the Spring Bean definitions for shortstrangleConfigParams, shortstrangleEngine,
shortstrangleService
/src/main/resources/META-INF/esper-shortstrangle.cfg.xml
Esper config file (no strategy specific config needed)
/src/main/resources/db/influx/influx-shortstrangle.gz
Contains the end-of-day historical data for all SPX Options for July 2011 to January 2013
Download the Examples project zip file and unpack it in a directory of your choosing: https://
www.algotrader.com/downloads/latest-examples
Note
user name and password will be provided when signing up for an AlgoTrader license
If you need an older AlgoTrader version, login to our maven repository (https://repo.algotrader.com/nexus)
and click on Browse on the left and select code-general.
400
CONFIDENTIAL Installation & Startup
401
CONFIDENTIAL
Warning
The purpose of this Strategy is to demonstrate capabilities of AlgoTrader. Do not use it with
a Live Trading Account and real Money! The strategy might lead to large losses. Even when
modifying or extending the Strategy use caution before trading it live.
The purpose of this strategy is to only illustrate the concept of capturing the dividend.
The idea is to receive a dividend from a company by holding its stock prior to ex-date.
The Strategy enters a LONG position as soon as dividend date is announced and closes the position on ex-
date thus obtaining the right to the dividend.
This strategy requires a dividend event feed, which the Intrinio adapter provides. You therefore need an Intrinio
API key to run it.
J.2. Implementation
The main artifacts needed for the Implementation of a new Strategy are described in Chapter 4, Strategy
Development.
/src/main/java/ch/algotrader/strategy/dividends/DividendCaptureService.java
The strategy service class providing the main methods invoked by the application on certain events.
/src/main/resources/conf-dividends.properties
Contains parameters used by the strategy (e.g. tradableSecurities and dividendAdapter and
orderQuantity and accountId)
/src/main/resources/db/mysql/mysql-data.sql
Contains the MySQL database records. Needs to be imported into the database before running the strategy
with the MySQL database.
To start the Strategy please see the explanations in Chapter 3, Starting AlgoTrader.
402
CONFIDENTIAL Installation & Startup
Download the Examples project zip file and unpack it in a directory of your choosing: https://
www.algotrader.com/downloads/latest-examples
Note
user name and password will be provided when signing up for an AlgoTrader license
If you need an older AlgoTrader version, login to our maven repository (https://repo.algotrader.com/nexus)
and click on Browse on the left and select code-general.
To start the strategy in live trading mode on a development workstation please execute the following steps:
403
CONFIDENTIAL Installation & Startup
load the strategy specific script into the MySQL database: /dividends/src/main/resources/db/mysql/
mysql-data.sql
To start the strategy in live trading mode on a productive server please execute the following steps:
https://gitlab.algotrader.com/general/examples/blob/master/dividend-capture/docker-compose.yml
docker-compose up -d
Note
Prior to starting the strategy for the very first time please start the AlgoTrader server by itself by
executing the following command inside /bootstrap/launch. this will load the MySQL sample
data
404
CONFIDENTIAL
Warning
The purpose of this Strategy is to demonstrate capabilities of AlgoTrader. Do not use it with
a Live Trading Account and real Money! The strategy might lead to large losses. Even when
modifying or extending the Strategy use caution before trading it live.
Natural Language Processing, shortened as NLP, is a branch of artificial intelligence that uses the natural
language to deal with the interaction between computers and humans.
The purpose of NLP is to read, understand and analyse the human languages to make is valuable.
The idea of the strategy is to receive tweets about the chosen instrument and basing on their average sentiment
enter long or short position.
K.2. Implementation
The main artifacts needed for the implementation of a new strategy are described in Chapter 4, Strategy
Development.
/src/main/java/ch/algotrader/strategy/nlp/NlpService.java
The strategy service class providing the main methods invoked by the application on certain events.
/src/main/java/ch/algotrader/strategy/nlp/TweetService.java
The service class connects to Twitter and provides tweets.
/src/main/java/ch/algotrader/strategy/nlp/ScoreService.java
The service class uses natural language processing to calculate the overall sentiment of a tweet.
/src/main/resources/conf-nlp.properties
Contains parameters used by the
strategy (e.g. accountId, securityId, orderQuantity,
windowTimeInMinutes, openPositionFactor, closePositionFactor, consumerKey and
consumerSecret)
/src/main/resources/db/mysql/mysql-data.sql
Contains the MySQL database records. Needs to be imported into the database before running the strategy
with the MySQL database.
405
CONFIDENTIAL Installation & Startup
To start the Strategy please see the explanations in Chapter 3, Starting AlgoTrader.
Download the Examples project zip file and unpack it in a directory of your choosing: https://
www.algotrader.com/downloads/latest-examples
Note
user name and password will be provided when signing up for an AlgoTrader license
If you need an older AlgoTrader version, login to our maven repository (https://repo.algotrader.com/nexus)
and click on Browse on the left and select code-general.
406
CONFIDENTIAL Installation & Startup
To start the strategy in live trading mode on a development workstation please execute the following steps:
load the strategy specific script into the MySQL database: /nlp/src/main/resources/mysql/mysql-
data.sql
407
CONFIDENTIAL
Warning
The purpose of this Strategy is to demonstrate capabilities of AlgoTrader. Do not use it with
a Live Trading Account and real Money! The strategy might lead to large losses. Even when
modifying or extending the Strategy use caution before trading it live.
One can express their vision how market would behave in the nearest future. Having this in mind bid/ask price
could be defined in the way that buying and selling at this price would be profitable. This example shows how
market making strategy could be implemented. The key difference with other strategies is that market maker
always ready to buy and sell instrument, thus providing liquidity to the market.
The main purpose of this strategy is to show how to use historical market data, live market data and do simple
order management. The strategy calculates moving average price for USDBTC (using coinApi Pro historical
data and coinbase Pro for live market data) and calculates mid price. The strategy uses assumption that current
market mid price would reverse to the mean value (moving average in this example). During trading some
position can accumulate, in such a case the strategy would place a hedge order which would square the
position. Some statically configured spread will apply, also there is a threshold based on which current open
orders would be adjusted (i.e. replaced according to the current market conditions).
L.2. Implementation
The main artifacts needed for the implementation of a new strategy are described in Chapter 4, Strategy
Development.
/src/main/java/ch/algotrader/strategy/marketmaker/MarketmakerService.java
The strategy service class providing the main methods invoked by the application on certain events.
/src/main/java/ch/algotrader/strategy/marketmaker/algo/Metrics.java
The metrics class is responsible for calculating order parameters (i.e. buy/sell/hedge) according to the
current market conditions.
/conf/settings.csv
Config where the following parameters are specified:
408
CONFIDENTIAL Installation & Startup
maxUnits - max amount strategy can trade on each side for market making orders,
repricingThreshold - threshold after which orders will be resubmitted with updated prices - it prevents
resubmitting orders with small price changes.
/src/main/resources/db/mysql/mysql-data.sql
Contains the MySQL database records. Needs to be imported into the database before running the strategy
with the MySQL database.
Download the Examples project zip file and unpack it in a directory of your choosing: https://
www.algotrader.com/downloads/latest-examples
Note
user name and password will be provided when signing up for an AlgoTrader license
If you need an older AlgoTrader version, login to our maven repository (https://repo.algotrader.com/nexus)
and click on Browse on the left and select code-general.
409
CONFIDENTIAL Installation & Startup
To start the strategy in live trading mode on a development workstation please execute the following steps:
load the strategy specific script into the MySQL database: /marketmaker/src/main/resources/db/
mysql/mysql-data.sql
To start the Strategy please see the explanations in Chapter 3, Starting AlgoTrader. Please note: first reference
data should be loaded. The following run configurations should be used:
Strategy
/runConfigurations/EmbeddedStrategyStarter-marketmaker.run.xml
410
CONFIDENTIAL
Warning
Do not use it with a Live Trading Account and real Money! The strategy might lead to large
losses. Even when modifying or extending the Strategy use caution before trading it live.
This example strategy shows how market indicator (Relative Strength Index in this case) can be used to
generate buy or sell signals and act accordingly. There is no much focus on qualitative side, i.e. RSI signal is
used in a simple, trivial way. However one can see how indicator is constructed, feed with market events and
how trades can be sent based on the indicator's values.
There is a simple rule for position accumulation - it is allowed to sell only when there is no position or there is
only long position, and it is allowed to buy only when being flat or short.
M.2. Implementation
The main artifacts needed for the implementation of a new strategy are described in Chapter 4, Strategy
Development.
/src/main/java/ch/algotrader/strategy/rsi/RSIService.java
The strategy service class providing the main methods invoked by the application on certain events.
/src/main/resources/conf-rsi.properties
Config where the following parameters are specified:
buyThreshold - index value, once value becomes below - treated as a buy signal,
411
CONFIDENTIAL Installation & Startup
Download the Examples project zip file and unpack it in a directory of your choosing: https://
www.algotrader.com/downloads/latest-examples
Note
user name and password will be provided when signing up for an AlgoTrader license
If you need an older AlgoTrader version, login to our maven repository (https://repo.algotrader.com/nexus)
and click on Browse on the left and select code-general.
To start the strategy in live trading mode on a development workstation please execute the following steps:
412
CONFIDENTIAL Installation & Startup
load the strategy specific script into the MySQL database: /rsi/src/main/resources/db/mysql/mysql-
data.sql
To start the Strategy please see the explanations in Chapter 3, Starting AlgoTrader.
413
CONFIDENTIAL
For installation instructions see the original strategy description: Section E.3, “Installation & Startup”. You may
use only a subset of historical data from the EURUSD csv file (by e.g. only keeping say 500 first rows) to be
able to run backtests during development faster.
The strategy can be written and run in both Python 2 and 3. The AlgoTrader Python Interface works with
both Python versions and has been tested with Python 2.7 and 3.7. Both Python versions and the AlgoTrader
Python Interface should already be installed in your environment if you are using an AWS instance running an
AlgoTrader trial image. If you have a different set up, you need to install the Python package (Section 2.2.3,
“Python installation”).
AlgoTrader (running in Java) can be started using the EmbeddedStrategyStarter (for live trading,
or live trading against an exchange simulator, Section 5.1, “Exchange Simulator”) or using the
SimulationStarter for strategy backtesting on historical data (see Section 3.1, “Simulation Mode”). The
spring profile pythonIntegration needs to be activated with those. You can use the Run Configurations
EmbeddedStrategyStarter-ema-python and SimulationStarter-simulate-ema-python in /ema-python
folder for that.
N.1.1. Implementation
Detailed information on implementing strategies in Python can be found in Section 4.5, “Strategy Development
in Python”.
EMAStrategyService
The strategy implementation extends the StrategyService class from the AlgoTrader Python Interface
(algotrader_com package). Overridden methods (on_bar, on_init, etc.) contain the same logic as the
overridden methods (onBar, onInit, etc.) in the Java version of the EMAService (Appendix E, Example
Strategy "EMA"). For example the overridden on_bar method implements the EMA indicator calculation
and the evaluation of strategy rules based on the crossover of 2 EMA indicators with different lengths.
414
CONFIDENTIAL Implementation
connect_to_algotrader
This function is used to pass a strategy implementation (a class extending StrategyService) to the
AlgoTrader Python Interface.
wait_for_algotrader_to_disconnect
This function is used to prevent the Python script from finishing.
_numpy_ewma_vectorized_v2
This function calculates the exponential moving averages. Note that using the popular Pandas library
functionality would have a negative impact on performance.
415
CONFIDENTIAL
For installation instructions, see the original strategy description: Section A.4, “Installation & Startup”. You may
use only a subset of historical data from the EURUSD csv file (by e.g. only keeping say 500 first rows) to be
able to run backtests during development faster.
The strategy can be written and run in both Python 2 and 3. The AlgoTrader Python Interface works with
both Python versions and has been tested with Python 2.7 and 3.7. Both Python versions and the AlgoTrader
Python Interface should already be installed in your environment if you are using an AWS instance running an
AlgoTrader trial image. If you have a different set up, you need to install the Python package (Section 2.2.3,
“Python installation”).
AlgoTrader (running in Java) can be started using the EmbeddedStrategyStarter (for live trading,
or live trading against an exchange simulator, Section 5.1, “Exchange Simulator”) or using the
SimulationStarter for strategy backtesting on historical data (see Section 3.1, “Simulation Mode”). The
spring profile pythonIntegration needs to be activated with those. You can use the Run Configurations
EmbeddedStrategyStarter-breakOut-python and SimulationStarter-simulate-breakOut-python in
the /breakOut-python folder for that.
O.1.1. Implementation
Detailed information on implementing strategies in Python can be found in Section 4.5, “Strategy Development
in Python”.
BreakoutStrategyService
The strategy implementation extends the StrategyService class from the AlgoTrader Python Interface
(algotrader_com package). The method _entry contains the same logic as the entry method in Java
version of the BreakOutService (Appendix A, Example Strategy "BreakOut").
module-breakOut.epl
The business logic is written in Esper statements that are identical to the original Java based strategy.
The only changes are in the ENTRY_LONG, ENTRY_SHORT statements that invoke not a subscriber on a
416
CONFIDENTIAL Implementation
Java based Spring bean, but pass the values to the Python strategy's on_esper_subscriber_invocation
method using @Subscriber(className='pythonStrategyService#onEsperSubscriberInvocation')
connect_to_algotrader
This function is used to pass a strategy implementation (a class extending StrategyService) to the
AlgoTrader Python Interface.
wait_for_algotrader_to_disconnect
This function is used to prevent the Python script from finishing.
417
CONFIDENTIAL
This is a demonstration of the concept that by utilizing AlgoTrader API it is possible to write strategies in
languages other than Java. In order to run this strategy, AlgoTrader server must be started. Running ema-
python-via-api/ema-api.py in Python afterwards starts the strategy execution. The strategy subscribes to
market data on an ActiveMQ topic and submits orders via REST API.
Note that even though this approach allows one to access all AlgoTrader functionality and run a strategy
against a running AlgoTrader server, a strategy written this way can't be used for backtesting (Section 3.1,
“Simulation Mode”). You can however run this strategy in live trading mode against Section 5.1, “Exchange
Simulator”. Backtesting Python strategies works if you write your strategy using AlgoTrader Python Interface,
see Appendix N, Example strategy "EMA" in Python.
All the configurations settings for the example strategy are located inside ema-api.py file. Only an installed
Python interpreter is required (the example ema-api.py script was tested with Python version 3.6.3)
418