Suppose you need to execute a large order. Sending it to the market all at once can reveal your trading intent and lead to poor execution.
That's why institutional traders use Iceberg algorithms, which split a large parent order into smaller child orders and expose only a fraction of the total volume to the market.
The real challenge, however, begins after each child order is submitted.
It may be fully filled, partially filled, canceled, or require repricing as market conditions change. Each outcome determines what should happen next.
An Iceberg strategy is therefore not just about splitting orders—it's about continuously reacting to market feedback.
That's exactly the focus of this article: How can we build an execution system that makes those decisions in real time?
Why Traditional Backtesting Falls Short
Traditional backtesting frameworks often simplify order execution by:
Assuming every order is filled immediately at the expected price.
Polling order status at fixed intervals instead of reacting to events.
Ignoring real execution feedback, such as partial fills, cancellations, and changing market depth.
While these assumptions make simulations easier, they also create a significant gap between backtesting and live trading.
For execution algorithms like Iceberg, performance depends not only on how orders are split, but also on how quickly the system detects market events and adapts its behavior.
A more realistic execution framework requires two key capabilities.
First, it should reproduce how orders are actually matched based on real market data, order book dynamics, and exchange matching rules.
Second, it should process execution events as they occur, rather than relying on inefficient polling.
DolphinDB addresses these requirements with two complementary components: an Order Matching Simulator and a Complex Event Processing (CEP) engine.
The matching engine simulator reproduces the complete execution lifecycle using real market data and exchange rules, while the CEP engine converts fills, cancellations, timeouts, and other trading feedback into real-time events that drive subsequent execution decisions.
The following shows how the CEP engine drives an Iceberg execution workflow in real time.
Why Does Trade Execution Need to Be Event-Driven
The question is no longer what the algorithm should do, but how the execution system should do it.
An execution engine must maintain the state of every parent order, react to execution feedback, and determine the next action as market conditions evolve.
Traditional systems typically solve this by polling order status at fixed intervals. As the number of active orders grows, however, polling becomes increasingly inefficient while execution logic becomes harder to manage.
A more natural approach is to let execution events drive the workflow. Instead of repeatedly checking every order, the system reacts only when something meaningful happens, such as a fill, a cancellation, or a price update.
This is exactly the problem that Complex Event Processing (CEP) is designed to solve.
In an execution system, typical events include:
A parent order enters the system.
A child order is filled or partially filled.
A cancellation confirmation is received.
The market price changes.
CEP provides a natural way to build this type of system. It continuously consumes business events, detects patterns and relationships between them, and triggers the appropriate actions based on predefined rules.
For an Iceberg strategy, the CEP engine continuously monitors execution events such as fills, partial fills, cancellations, and price changes, enabling real-time execution decisions.
The result is an execution workflow that more closely resembles how real trading systems operate, while keeping the strategy logic clear, responsive, and easy to extend.
What Components Does an Event-Driven Execution System Need
If we view trade execution as a continuous stream of events, the system must answer four questions:
Where does market data come from?
Where is the current order state stored?
Who simulates exchange matching and generates execution reports?
Who decides what to do after an execution event?
The CEP engine orchestrates the execution workflow, but it is only one part of the system. A complete event-driven execution architecture also requires market data, order matching, and state management working together.
The overall architecture:

The system forms a continuous feedback loop. When a parent order enters the system, the CEP engine applies the Iceberg algorithm to split it into child orders.
These child orders are then sent to the Order Matching Simulator, where they are matched against replayed market data. As orders are filled, partially filled, or canceled, the matching engine immediately generates the corresponding execution reports and sends them back to the CEP engine.
Based on this feedback, the CEP engine determines the next action, such as submitting another child order, adjusting the execution strategy, or completing the parent order.
This cycle repeats until the entire parent order has been executed, with every step driven by real-time market feedback.
Order Matching Simulator
An execution system can continuously generate child orders, but without execution feedback from an exchange, the workflow comes to a halt. To close the loop, we need a matching environment that behaves like a real exchange.
In this example, we use DolphinDB's Order Matching Simulator plugin.
It accepts two inputs:
Replayed market data
User-submitted orders
The simulator then applies exchange matching rules to process order queuing, fills, partial fills, and cancellations, ultimately producing execution reports for the CEP engine.

For an Iceberg strategy,what really matters is the execution feedback it produces.
As orders are matched, the Order Matching Simulator continuously generates execution reports, including events such as partial fills and full fills. These reports are then subscribed to, converted into trading events, and published to the event stream monitored by the CEP engine.
Whenever a new execution event arrives, the CEP engine immediately updates the state of the parent order and determines the next action—whether to submit another child order, adjust the order price, or complete the execution.
How CEP Drives the Order Lifecycle
Market data continuously flows into the system, and the matching engine continuously produces execution reports. Neither component, however, makes execution decisions.
Their job is simply to describe what is happening in the market. The logic that decides when to submit an order, cancel an order, or complete the execution is handled by the CEP Monitor.
One Monitor per Parent Order
In a traditional execution engine, the system is responsible for tracking every active parent order. As the number of orders grows, the execution engine must maintain an increasingly complex state machine while repeatedly scanning active orders to determine which ones require further processing.
The CEP engine takes a different approach.
Whenever a new parent order enters the system, it creates a dedicated Monitor for that order.
The Monitor acts as the order's execution controller, managing its entire lifecycle—from the moment the parent order is received until the final child order is executed.
Multiple execution workflows can run independently and in parallel without interfering with one another.
`class IceBergSplitMonitor : SplitMonitor {
def startPlaceOrder(parentOrder){...}
def placeOrder(){...}
def cancelOrder(){...}
def updateSubOrder(){...}
def forkParentOrderMonitor(parentOrder){...}
def onload(){
addEventListener(forkParentOrderMonitor,
"ParentOrder",
,
"all")
}
}`
The complete implementation includes several supporting functions:
onload() continuously listens for new parent orders.
forkParentOrderMonitor() creates a dedicated Monitor for each parent order.
startPlaceOrder() initializes the execution state and determines whether execution should start immediately.
placeOrder() generates the next child order based on the current execution state.
Once these steps are complete, the Monitor enters the execution phase.
Why Is placeOrder() the Core of the System
Although its name suggests otherwise, placeOrder() does much more than submit an order—it starts a new execution cycle.
Each time placeOrder() is called, three things happen:
A new child order is generated based on the current state of the parent order.
The child order is sent to the Order Matching Simulator.
An event listener is registered for that child order.
The key is not the order submission itself, but telling the CEP engine: From this point on, notify me whenever something happens to this order.
This is the fundamental difference between an event-driven system and a traditional execution workflow.
A Monitor Runs Only When Events Arrive
A Monitor does not run continuously.
After submitting a child order, it immediately suspends execution and consumes no computing resources while waiting for the next event.
When an execution event—such as a fill, partial fill, or timeout—arrives, the CEP engine wakes the corresponding Monitor, which resumes execution exactly where it left off.
In other words, each Monitor repeatedly follows the same pattern:
Event arrives → Execute for a few milliseconds → Suspend → Wait for the next event
From the strategy's perspective, only three types of events matter:
Child order fully filled: Submit the next child order.
Child order partially filled: Update the execution state and continue waiting.
Child order timed out: Cancel the current order and submit a new quote based on the latest market conditions.
As fills, partial fills, and timeouts continue to occur, the Monitor keeps updating the execution state and advancing the next round of order splitting until the parent order is fully executed.
At that point, the lifecycle of the Iceberg strategy comes to an end.
Walk Through the Complete Execution Flow
Next, we'll walk through a complete Iceberg execution example to see how the CEP engine drives the lifecycle of a parent order while the Dashboard visualizes the execution state in real time.
To reproduce the example, we prepared historical market data, a simulated matching environment, and a Dashboard configuration.
Once the system is started, submitting a single parent order to the CEP engine is enough to trigger the entire execution workflow automatically.

For the complete implementation, click CEP Engine Applications: Advanced Tutorial on Implementing an Algorithmic Order-Splitting System.
Conclusion
We used the Iceberg algorithm as an example to build an event-driven order execution system with the DolphinDB CEP engine. From shared state management and real-time market data to the matching engine simulator and CEP Monitors, each component plays a role in forming a complete execution workflow.
The gap between backtesting and live trading is often not caused by the strategy itself, but by how the strategy reacts to market feedback during execution. Iceberg is just one execution algorithm. The broader value of CEP lies in providing a more natural way to manage the entire order lifecycle. Instead of relying on continuous polling, the system reacts to fills, market updates, timeouts, and other execution events as they occur, allowing the execution workflow to progress efficiently and naturally.
Thanks for reading! Stay connected with DolphinDB by following us on X and LinkedIn for the latest updates, technical articles, and product news. For more information, visit our website.
Top comments (0)