AlgoTraderAlgoTrader Documentation

Development Guide


Version 5.2.0

1. Document Conventions
1.1. Typographic Conventions
1.2. Pull-quote Conventions
1.3. Notes and Warnings
1. Introduction
2. Building AlgoTrader
2.1. Command Line
2.1.1. Git Checkout
2.1.2. Maven Build
2.1.3. Docker Build
2.2. Eclipse
2.2.1. Git Checkout
2.2.2. Maven Build
2.2.3. Docker Build
2.3. AlgoTrader UI
2.3.1. Git Checkout
2.3.2. Maven Build
2.3.3. Docker Build
3. Domain Model
3.1. Security Visitors
3.2. Data access objects (DAOs)
3.3. Services
3.3.1. Private Services
3.3.2. Order Services
3.3.3. Market Data Services
3.3.4. Historical Data Services
3.3.5. Reference Data Services
4. Java Environment
4.1. AlgoTrader Project Structure
4.1.1. common project
4.1.2. core project
4.1.3. conf project
4.1.4. launch project
4.1.5. strategy projects
4.2. Java Packages & Classes
4.3. Maven Environment
4.3.1. Maven assemblies
4.3.2. Packaging strategies
4.3.3. Maven profiles
5. Code Generation
6. Database
6.1. Database scripts
6.2. Transaction Handling
7. Market Data
8. Adapters
8.1. Bloomberg
8.2. Currenex
8.3. DukasCopy
8.4. Exante
8.5. EzeSoft/RealTick
8.6. Fix Interface
8.7. Fortex
8.8. FXCM
8.9. IB Native Interface
8.10. JP Morgan
8.11. LMAX
8.12. Nexus Prime
8.13. PrimeXM
8.14. Quandl
8.15. QuantHouse
8.16. SocGen
8.17. Trading Technologies
8.18. UBS
8.19. Binance
8.20. Bitfinex
8.21. Bitflyer
8.22. BitMEX
8.23. Bitstamp
8.24. CoinAPI
8.25. Coinbase
8.26. Coinigy
8.27. CoinMarketCap
9. Execution Algos
9.1. Development of Execution Algos
9.2. Execution Algos entry form generation
10. Spring Services
10.1. Wiring Factories
10.2. Application Context
10.3. Abstract Services
10.4. Service initialization order
11. Events and Messaging
11.1. Embedded ActiveMQ message broker
11.2. Embedded Jetty HTTP server
11.3. RESTful interface
11.4. Event Dispatcher
11.5. Event Listeners
11.6. JMS Destinations
12. Configuration and Preferences API
12.1. Config Providers
12.2. Config Beans
12.3. Config Locator
13. Processes and Networking
13.1. Processes
13.2. Sockets
13.3. RMI
14. Hibernate Sessions and Caching
14.1. Hibernate Caching
14.1.1. Level-Zero Cache
15. Logging
15.1. Custom UI Log Event Appender

This manual uses several conventions to highlight certain words and phrases and draw attention to specific pieces of information.

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.

The following typographic conventions are used to call attention to specific words and phrases. These conventions, and the circumstances they apply to, are as follows.

System input, including shell commands, file names and paths, and key caps and key-combinations are presented as follows.

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:

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.

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.

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.

Note the words in italics above — username,, 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.

This document provides additional information on the internal implementation of AlgoTrader for cases when clients wish to make changes to the platform or extends its functionality.

AlgoTrader can be built from its source either via command line or via Eclipse


AlgoTrader based trading strategies can be developed and started without building AlgoTrader first

To build AlgoTrader from within Eclipse please follow this process.

This will result in the following Eclipse projects:

  • algotrader-common

  • algotrader-core

  • algotrader-conf

  • algotrader-launch


The compilation will show errors, which should go away after the next section has been completed.

The Visitor Pattern is a way of separating an algorithm from an object structure on which it operates. Using this pattern it is possible to implement custom Logic per Entity without polluting the Entity code itself.

AlgoTrader provides the interface ch.algotrader.visitor.EntityVisitor which must be implemented by all Entity Visitors. Each Entity Visitor has two generic type parameters R and P. R is the return type (or java.lang.Void) returned by all visit methods and P is an arbitrary parameter object that can be added to the visit methods.

In addition there is the ch.algotrader.visitor.PolymorphicEntityVisitor which reflects the entire inheritance tree of all Securities. For example if there is no visitFuture method the PolymorphicEntityVisitor will automatically invoke the visitSecurity method.

The accept method of each Entity can be used to process an arbitrary Visitor like this:


In AlgoTrader there are two Visitors available which are used by the AlgoTrader Server


Is used to make sure certain Hibernate Entity References are initialized / loaded.


is used to scale quantities and prices


Is used to determine if a particular Security is supposed to report volumes


Used to validate a Tick by rules defined per Security

The AlgoTrader DAO framework of consists of several main components

It is possible to add custom DAOs to the platform. To accomplish this one needs to create a DAO interface extending either ReadOnlyDao or ReadWriteDao, add custom operations such as entity specific finders and then create a custom DAO class extending AbstractDao and implementing the custom DAO interface.

public class MyEntity implements BaseEntityI {

    private long id;
    private String name;
    public long getId() {
    protected void setId(final long id) { = id;
    public boolean isInitialized() {
        return true;
    public String getName() {
    public void setName(final String name) { = name;
public interface MyEntityDao extends ReadWriteDao<MyEntity> {

    public MyEntity findByName(String name);

public class MyEntityDaoImpl extends AbstractDao<MyEntity> implements MyEntityDao {
    public MyEntityDaoImpl(final SessionFactory sessionFactory) {
        super(MyEntity.class, sessionFactory);
    public Strategy findByName(final String name) {
        return findUniqueCaching(
            "from MyEntity where name = :name", QueryType.HQL, new NamedParam("name", name));

HQL and SQL queries used by AlgoTrader DAO components are externalized and stored in Hibernate.hbm.xml file. This allows for better management and for easier re-use of queries.

<query name='Strategy.findByName'>
    from StrategyImpl
    where name = :name

Queries can be accessed from DAO classes or custom components by their names

public class StrategyDaoImpl extends AbstractDao<Strategy> implements StrategyDao {

    public Strategy findByName(final String name) {
        return findUniqueCaching(
            "Strategy.findByName", QueryType.BY_NAME, new NamedParam("name", name));

Table 3.1. Private Services

AlgoOrderService Order Services responsible for handling of AlgoOrders (delegates to AlgoOrderExecServices)
AlgoOrderExecService Abstract Base Class for all Algo Execution Order Services
ExternalAccountService Abstract Base Class for all external Account Interfaces
ExternalMarketDataService Abstract Base Class for all external Market Data Interfaces
FixSessionService Exposes properties of FIX sessions
ForexService Responsible for the FX Hedging functionality
GenericOrderService Parent Class for all Order Services
MarketDataPersistenceService Responsible for persisting Market Data to the database
OrderExecutionService Responsible for handling of persistence and propagation various trading events such as order status update and order fills as well as maintaining order execution status in the order book.
OrderPersistenceService Responsible for persisting Orders and OrderStatus to the database
ReconciliationService Responsible for reconciliation of reports provided by the broker
ResetService Responsible for resetting the DB state (e.g. before the start of a simulation)
ServerLookupService Provides internal data lookup operations to other server side services
SimpleOrderService Order Service responsible for handling of Simple Orders (delegates to SimpleOrderExecServices)
SimpleOrderExecService Abstract Base Class for all Simple Order Execution Services
StrategyPersistenceService Handles persistence of Strategy Entities
TransactionPersistenceService Responsible for the persistence of Transactions, Positions updates and Cash Balance updates to the database
TransactionService Responsible for handling of incoming Fills

The Framework AlgoTrader consists of the following Sub-Projects:

AlgoTrader uses Maven as its build management framework. Every project/module therefore has it's own pom.xml (Project Object Model) defining its structure and dependencies.

In addition to standard maven profile, there are Maven profiles provided to perform various side-tasks.

To enable one or more profiles one should add its names prepended by -P to maven command. If there is more than one profile, they should be split by a comma.

The following example will run maven clean package goals with enunciate and swagger-ui profiles enabled.

mvn clean package -Penunciate,swagger-ui

Available profiles:


Enables Enunciate tool to generate HTML documentation and client-side libraries for multiple programming languages.

Libraries are generated into target/enunciate directory

Generated HTML documentation goes into target/site/apidocs/index.html.


Enables Swagger UI interactive REST API docs generation.


Enables code generation for AlgoTrader HTML5 UI.

The UI is written in Typescript and UI gets a lot of Algotrader's domain classes serialized in JSON. In order to have the domain of Algotrader defined in one place, the Java domain model is being transformed into Typescript types and used in UI.


Enables Historical Data Manager & Reference Data Manager styles compilation.

These tools are written in Vaadin Framework (Java) and its Sass styles need to be compiled using Vaadin Sass Compiler.


Enables all of the above profiles at once

Java Entities, Entity Interfaces and Value Objects are created by the means of the Hibernate Tools project using the hbm2java code exporter.

The Hibernate Tools project provides the code generator as an Eclipse plugin as well as a set of Ant tasks. AlgoTrader provides a custom maven plugin called maven-codegen-plugin which wraps the code generator.

<name>Model code generator plugin</name>

The maven-codegen-plugin has been added to the file /algotrader/common/pom.xml


The above configuration generates the following artifacts for each Java Entity defined in the Hibernate mapping files:

  • Entity

  • Entity interface

  • Value Object

  • Value Object Builder

The code generator uses Hibernate mapping files which are located in /algotrader/common/src/main/resources in combination with Freemarker templates which are located in /algotrader/common/pojo . These templates are based on the original version supplied with the Hibernate Tools project but have been augmented to produces Java code needed by AlgoTrader. For this purpose several custom attributes have been added to Hibernate mapping files:

Generated code is placed under the directory /algotrader/common//target/generated-sources/main/java.

All Market Data Interfaces have a set of unique artifacts:

Processing of Market Data is handled through the MarketDataService, which calls the market data provider specific ExternalMarketDataService implementations. Every market data service has to provide implementation of this interface e.g. (e.g. IBMarketDataServiceImpl or BBMarketDataServiceImpl).

The most important methods provided by the MarketDataService are subscribe and unsubscribe. Through the use of these methods new Market Data can be subscribed and unsubscribed. Subscribed securities are persisted within the DB-table subscription. The actual subscription of securities to the external broker is done through the market data provider specific MarketDataService.

Market data provider interfaces are responsible for receiving market data provider specific Market Data and sending them into the Esper Service Instance of the AlgoTrader Server. The Esper Service Instance will then convert these Events into generic MarketDataEvents (i.e. Ticks or Bars) which will be propagated to subscribed Strategies.

The Fix infrastructure consists of the following classes:

Table 8.6. Fix Infrastructure

Class / InterfaceDescription
Session A Session represents a connection to a broker / exchange / market data provider
Application For each Session an Application object is created. It will forward incoming messages to the corresponding MessageHandlers
FixApplicationFactory Is responsible for the creation of Applications

Creates a Session and Application using the specified FixApplicationFactory according to the following steps:

  • lookup the FixApplicationFactory by its name

  • create an Application

  • create a DefaultSessionFactory

  • create a Session

ExternalSessionStateHolder Represents the current state of a Session (i.e. DISCONNECTED, CONNECTED, LOGGED_ON and SUBSCRIBED)
MarketDataFixSessionStateHolder A ExternalSessionStateHolder for market data sessions that will subscribe to securities as soon as the session is logged on.
FixOrderIdGenerator Generator for Fix Order Ids. The default implementation reads the last Order Ids from the Fix log on start-up.
FixAdapter Management Adapter for the Fix environment. Allows the creation of dynamic sessions, sending Messages and managing Order Ids.
ManagedFixAdapter Manageable implementation of a FixAdapter (based on JMX)
FixEventScheduler QuickFix/J currently supports daily sessions (with a daily session 7 times a week) and weekly sessions (with one weekly session). However some brokers (e.g. JP Morgan) use daily sessions during workdays. To accomplish this scenario, AlgoTrader allows creation of a weekly logon/logoff event (e.g. Mo 08:00:00 and Fr 18:00:00) using Esper Statements
FixSocketInitiatorFactoryBean A Spring Factory Bean that creates the SocketInitiator necessary for all Fix Sessions.
Fix42MarketDataMessageHandler Message Handler for incoming Fix market data messages. These classes need to be sub classed by the corresponding market data interface. Messages are propagated into the Esper Engine.
Fix42OrderMessageHandler Message Handler for incoming Fix Execution Reports. These classes need to be sub classed by the corresponding order interface. Messages are propagated into the Esper Engine.

Additional Execution Algos can be added to the system with relatively minimal effort. Execution Algos consist of the following artifacts

The OrderService is aware of all AlgoOrderExecService instances declared in the Spring application context of the server process. Custom AlgoOrderExecService implementations also get automatically recognized as long as they are declared in the same application context. The OrderService delegates handling of individual orders to their respective algo service based on the order type. It is important for classes implementing AlgoOrderExecService to correctly implement its #getAlgoOrderType method.

The AlgoTrader UI can generate the entry form for Execution Algo automatically. To enable it one needs to register the AlgoOrderVO class in the MetaDataRestController and annotate it with @AlgoOrderMetaData. One needs to provide a mapping to the OrderType enum value there. These two steps will allow the UI to generate the entry form for that Execution Algo which will then be available in Advanced Order Form modal.

The Algo Order UI generation can be further tuned by annotating fields inside the AlgoOrderVO class with following annotations:

Below code snipped shows an example for a BigDecimal field named fieldA. This field controls the visibility of fieldB and fieldC. fieldB is only visible if the value of fieldA is true and fieldC is only visible if the value of fieldA is false.

@UIGeneration(toggle = @FieldToggle(visibleOnTrue = "fieldB", visibleOnFalse = "fieldC"))

private BigDecimal fieldA;
private BigDecimal fieldB;
private BigDecimal fieldC;

AlgoTrader is built on top of the Spring Framework, which uses BeanFactory and ApplicationContext to locate Spring Beans (= AlgoTrader-Services).

The Spring web site provides documentation such as 'The IoC container' as an introduction.

AlgoTrader provides the class ch.algotrader.ServiceLocator which will instantiate the adequate BeanFactories & ApplicationContexts for a given operational mode depending on the specified BEAN_REFERENCE_LOCATION.

In Simulation mode the AlgoTrader Server as well as the Strategy run inside the same JVM.

In Live-Trading mode the AlgoTrader Server and strategies can be run in different JVMs. Through the use of RmiServiceExporters and RmiProxyFactoryBean, Strategies can call Services from the AlgoTrader Server. Behind the scenes this is handled transparently through RMI.

Please see Remoting and web services using Spring for further details.

AlgoTrader provides the following Wiring Classes and Application Context XML-Files :

The following table shows which Wiring Classes and ApplicationContext is referenced by which Wiring Factory:

AlgoTrader provides a sophisticated event dispatching and messaging sub system. In Simulation Mode as well as Embedded Mode Event Propagation takes places within the JVM. In Distributed Live Trading Mode Event Propagation from the AlgoTrader Server to the strategies (and between strategies) happens via JMS & ActiveMQ

RESTful endpoints largely expose the same interface as Spring services exposed via RMI. REST controllers must follow RESTful semantic and also use immutable value objects for input / output representation.

AlgoTrader RESTful controllers serve several purposes:

The following RESTful controller provides a list of all accounts available in the system:


@RequestMapping(path = "/account", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public List<AccountVO> getAccounts() {
    return lookupService.getAllAccounts().stream()

In this example the @CrossOrigin annotation marks endpoint as permitting cross origin requests. The @RequestMapping annotation defines various aspects of request / response mapping: path attribute defines path element of the request URI, method attribute defines the request method (such as GET, POST, PUT or DELETE), produces attribute defines expected media type of response body. The endpoint method implementation performs conversion of Account Entity objects to AccountVO objects, which are then serialized to JSON data stream by the framework.

For more detailed explanation of REST controllers and Web annotations please refer to Spring documentation.

AlgoTrader uses SWAGGER to document the individual REST endpoints, see:

EventListener represents a generic communication interface to receive events from multiple event producers both in-process and remote. EventListenerRegistry interface represents a registry of event listeners used internally by the AlgoTrader Server process as well as individual strategy processes. One can register listeners for arbitrary event classes, which enables strategies to generate custom events either through Esper statements or in Java code and consume them internally or propagate them to other strategy processes.

The AlgoTrader platform provides a number of event listeners for common event types such as market data events, order events, external session events, life-cycle events, and a few others. Components that implement those event interfaces which are declared in the Spring application context get automatically registered with the platform upon initialization..

Table 11.2. Standard event listener classes

BarEventListener receives BarVO events generated from tick events by individual strategies or fed from an external source
EntityCacheEventListener receives EntityCacheEvictionEventVO generated by the cache manager
FillEventListener receives FillVO events generated by trading interface adapters
GenericEventListener receives GenericEventVO events generated by strategies or by the platform
GenericTickEventListener receives IBGenericTickVO events generated by IB market data interface adapter
LifecycleEventListener receives LifecycleEventVO generated by the life-cycle manager
OrderCompletionEventListener receives OrderCompletionVO events generated by the Server Engine
OrderEventListener receives OrderVO events generated by the order service
OrderStatusEventListener receives OrderStatusVO events generated by trading interface adapters
PositionEventListener receives PositionNutationVO events generated by the transaction service
QueryCacheEventListener receives QueryCacheEvictionEventVO generated by the cache manager
QuoteEventListener receives QuoteVO events (BidVO or AskVO) generated by market data interface adapters or fed from an external source
SessionEventListener receives SessionEventVO generated by market data and trading interface adapters
TickEventListener receives TickVO events generated by market data interface adapters or fed from an external source
TradeEventListener receives TradeVO events generated by market data interface adapters or fed from an external source
TransactionEventListener receives TransactionVO events generated by the transaction service
AccountEventListener receives AccountEventVO events generated by the account service

It is possible to change event listener priority, i.e. define the order in which the listeners are invoked when reacting to an event, by applying the following annotation to the listener method:


@EventHandlerPriority(value = EventHandlerType.EXECUTION, priority = 3)
public void onBar(BarVO bar) {

For EventHandlerType there are three options:

MARKET_DATA_CACHE receives events first, and EXECUTION last.

Events for the same EventHandlerType are prioritized according the to "priority" value

Again EVENT_HIGHEST_PRIORITY will receive events first, and EVENT_LOWEST_PRIORITY last.

Looking at a typical back test there are the following Bar consumers (in ascending order of event delivery):

So it is possible to change the order in which different listeners are invoked:

Events are delivered to strategies via JMS. The following JMS Destinations are defined by the system

Since market data events and generic events are pushed into two topics that are available to all strategies, strategies have to select appropriate messages on their own. This is the job of the SubscriptionService. It will modify the selectors on MessageListenerContainer accordingly and invoke the corresponding methods on the (server-side) MarketDataService (e.g. to request market data for additional securities).

AlgoTrader also provides commonly used parameters in a form of plain Java beans referred to as Config beans. Common configuration are represented by CommonConfig. Core platform parameters are represented by CoreConfig. Instances of these classes are immutable and can be shared by multiple components and multiple threads of execution.

ConfigBeanFactory class can be used to create instances of Config beans based on configuration parameters using @ConfigName constructor parameter annotations. This factory is used to build standard CommonConfig and CoreConfig but it can also be used to build arbitrary Config beans for a trading strategy using the following convention

public final class StratConfig {

    private final String textParam;
    private final boolean boolParam;
    private final BigDecimal decimalParam;

    public StratConfig(
        @ConfigName(value = "my.text") final String textParam,
        @ConfigName(value = "my.bool") final boolean boolParam,
        @ConfigName(value = "my.decimal", optional = true) final BigDecimal decimalParam) {

        this.textParam = textParam;
        this.boolParam = boolParam;
        this.decimalParam = decimalParam;

    public String getTextParam() {
        return textParam;

    public boolean isBoolParam() {
        return boolParam;

    public BigDecimal getDecimalParam() {
        return decimalParam;

Each constructor parameter of a Config bean must be annotated with @ConfigName containing the parameter name. The config parameter type will be inferred from the constructor argument type. If a parameter is null able and might be undefined in the config property files it can be marked as optional.

Standard platform Config beans such as CommonConfig and CoreConfig are declared in the Spring application context and get automatically injected into all beans that require configuration. One can also add strategy specific Config beans using the following bean definition:

<bean id="stratConfig" class="ch.algotrader.config.spring.ConfigBeanFactoryBean">
    <constructor-arg index="0" ref="configLocator"/>
    <constructor-arg index="1" value="my.strategy.StratConfig"/>

Standard as well as strategy specific Config beans can be conveniently accessed using Spring SPEL expressions to wire other beans in the same Spring application context.

<bean id="MyObject" class="...">
    <constructor-arg value="#{@stratConfig.requestUri}"/>

In addition it is possible to reference individual beans (e.g. config beans) directly within Spring wired classes

private @Value("#{@configParams.accountId}") long accountId;       

AlgoTrader uses Hibernate for accessing and persisting objects to the database.

In order to prevent having to access the database on every single request, Hibernate provides two types of caches:

Both First and Second Level Cache require a Hibernate Session. Creation of a Session is usually very quick (a few milliseconds). This mechanism is therefore fine for any request-response based system. However this approach is not feasible for a trading application. A trading application typically receives several thousand market data events per second. Ideally these market data events have to be matched to the latest data stored in the database (e.g. Security related information, current Positions, executed Trades, etc.). Opening a new Hibernate Session for every market data event, to synchronize related objects (like corresponding Security), is much too expensive!

For this purpose AlgoTrader introduces a Level-Zero Cache

AlgoTrader Level-Zero Cache is an additional Caching Level on top of Hibernate First and Second Level Cache which has the following features:

By using the Level-Zero Cache it is possible to work on fully up-to-date versions of Entities without introducing any latency penalties.

Access to the Level-Zero Cache is provided by the class ch.algotrader.cache.CacheManagerImpl which is exposed as a Spring Bean named cacheManager. The CacheManagerImpl provides these public methods to access the Level-Zero Cache:

Like Hibernate First and Second Level Cache the AlgoTrader Level-Zero Cache will first check if the requested object is available inside the Cache. If not, the object will be retrieved via the ch.algotrader.hibernate.GenericDao and stored in the Cache.

The class EntityCache is responsible for caching of Entities (handled by the EntityHandler) and Entity-Collections (handled by CollectionHandler). When adding a new Entity to the cache, the EntityHandler and CollectionHandler traverse the entire object graph of initialized Entities and Collections and store all of them in separate nodes of the internal Hash Map Cache. Java reflection is used for the object graph traversal (on new objects or object updates) .

The class QueryCache is responsible for caching of Hibernate Query Results. Query Results are cached in reference to all involved tables. So whenever one of those referenced tables is modified, the corresponding Query Cache Entry is removed (detached).

Through the class ch.algotrader.wiring.server.CacheWiring net.sf.ehcache.event.CacheEventListenerAdapter are registered with each Ehcache element. These are either EntityCacheEventListener for Entity caches or CollectionCacheEventListener for Collection Caches. These EventListeners emit CacheEvictionEvents via the AlgoTrader EventDispatcher to CacheManager of the Server and Strategies (running in remote JVMs) to get notified every time an Entity / Collection is updated or the UpdateTimestampsCache (related to the Hibernate StandardQueryCache) has been updated.

This is a special customized appender which allows to send log events to the UI. The log events are sent via JMS/STOMP and log levels and loggers are configurable. For example you could define a particular logger (e.g. some specific class) or use the Root logger configured for the desired log level, e.g. INFO or WARN. In order to have multiple loggers with multiple log levels, separate appenders must be created each with it's own filter. The sample configuration below will create two UI appenders - one with level WARN (and above), another with INFO. Loggers defined in "Loggers" section reference these appenders in such a way that INFO log entries from PortfolioServiceImpl as well as all the entries with level WARN and above will be sent to the UI

Log entries are wrapped inside JMS message and get propagated via WebSocket STOMP protocol to the UI. In order to consume the log message the client will have to be subscribed to specific JMS topic ("/topic/log-event."). See StompAPIUtils.js in the HTML client for the subscription logic example.

    <LogEvent name="LogEventWARN">
        <ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
    <LogEvent name="LogEventINFO">
        <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
    <Root level="debug">
        <AppenderRef ref="LogEventWARN"/>
    <Logger name="ch.algotrader.service.PortfolioServiceImpl">
        <AppenderRef ref="LogEventINFO" />