Algorithm Lifecycle
Algorithm States
Each algorithm follows a simple lifecycle, shown below:
There are four states in the lifecycle:
- Bootstrap state: When the server is started, it restores the state by replaying the journal of historical trading transactions.
- Follower state: In High Availability mode, a server instance can act as a Follower In this state, algorithms are on stand by. They receive a carbon copy of trading requests and events emitted on Leader node but cannot emit their own messages. It is similar to the Bootstrap state, but the received messages happen in real time. Trading is not allowed in this state either.
- Leader: This is the normal run time state in which the algorithm receives real-time messages and sends trade requests.
- Aborted: The algorithm has failed for some reason.
An algorithm can only trade in the Leader state. In Bootstrap and Follower states, the algorithm is responsible for maintaining an accurate trading state (i.e., the state of parent and child orders).
The following table shows how trading messages are routed in different modes:
Mode | Inbound Order Requests | Inbound Order Events | Outbound Order Requests | Outbound Order Events |
---|---|---|---|---|
Bootstrap | OMS→Algorithm | OMS→Algorithm | OMS→Algorithm | OMS→Algorithm |
Follower | OMS→Algorithm | OMS→Algorithm | OMS→Algorithm | OMS→Algorithm |
Leader | OMS→Algorithm | OMS←Algorithm | OMS←Algorithm | OMS←Algorithm |
Replaying historical trading messages back to the algorithm can be used to restore the trading state. For example, trades received during the bootstrap phase can be used to restore the current position in each instrument.
Special care must be taken when processing time-sensitive order fields (such as expiration time, for example). We suggest suppressing these checks in Bootstrap mode.
The following API methods available in AbstractAlgorithm
can be used to check the current mode:
/** @return true if current node (execution server) is a leader in a cluster or working live standalone */
protected final boolean isLeader();
/** @return true if current node is restoring trading state after restart (processing journal messages) */
protected final boolean isBootstrap();
You can also override the following callback to react to mode changes:
/** Informs that cluster-related state of this node changed.
Also used to mark transition from initial BOOTSTRAP to LEADER state for single-node installations */
@Override
public void onNodeStatusEvent(NodeStatusEvent event) {
super.onNodeStatusEvent (event);
final NodeStatus next = event.getNodeStatus();
final NodeStatus previous = nodeStatus;
LOGGER.info("Algorithm %s switched from %s to %s role")
.with(name)
.with(previous)
.with(next);
}
These methods and callback allow you to determine the current mode of the algorithm and perform specific actions based on the mode transition.
Shutdown Behavior
When the system detects a shutdown request, such as a SIGINT signal, it notifies all algorithms using the onShutdownRequest
callback of the ShutdownRequestHandler
interface that algorithms implement. The default handler from AbstractAlgorithm
(shown below) acknowledges the shutdown immediately by sending a ShutdownResponse
message:
@Override
public void onShutdownRequest(final ShutdownRequest request) {
final MutableShutdownResponse response = new MutableShutdownResponse();
response.setServiceId(id);
context.getShutdownResponseHandler().onShutdownResponse(response);
}
In some cases, an algorithm may need to perform additional actions before acknowledging the shutdown. For example, active orders may need to be cancelled. Try to avoid performing time-consuming actions during the shutdown process. Each algorithm has about 15 seconds to respond to the shutdown request before the system proceeds with process termination.
Once all services have acknowledged their shutdown, the Ember process terminates. The default acknowledgement timeout is set to 15 seconds.
Algorithms are not allowed to send any messages to the OMS (Order Management System) after they have acknowledged the shutdown.
Trading Halt
When a Trading Halt is activated, it acts as a kill switch. Any attempts to send a new order or replace an existing order will be rejected by the OMS. However, order cancellations are still allowed.
Trading may be halted for the following reasons:
- The system operator manually halts trading using the emergency kill switch in the ES Monitor. This action is also available via the Server API. See KillSwitchSample.
- Trading can be halted due to a risk limit violation. For example, if the number of rejected orders in the last second exceeds a pre-configured limit.
- Trading can be halted due to abnormal situations. For example, if, by default, Ember halts trading when the connection to TimeBase is lost.
The algorithm uses the following callback to implement the KillSwitchHandler
interface and get notified about any trading halt/resume events:
@Override
public void onKillSwitchEvent(KillSwitchEvent event) {
if (isLeader()) {
.. your action here
}
}
Note the check for the isLeader()
state. This ensures that the algorithm reacts only to trading halt events during the current Leader state and avoids reacting to historical kill switch events that may be replayed during the algorithm's bootstrap state.