Questions about Trading in Ember
Can I Execute a “Fake” Order using a Fixed Price?
Yes. To execute a "fake" order using a fixed price, send a LIMIT order to a SIM destination, where SIM is configured as follows:
connectors {
SIM: ${sim}
}
Can I Simulate Order Execution using Market Prices?
Yes. Ember includes a trading simulator, sometimes called the QuoteFlow simulator.
algorithms {
SIMULATOR : {template.algorithm.SIMULATOR} {
subscription {
streams = [ COINBASE ]
}
}
}
Order Rejected Due To Unknown Destination
The system is rejecting an order because it doesn't know how to route the order to the specified destination.
Check ember.conf. Make sure the destination specified in your order matches the name of one of the trading connectors or execution algorithms deployed in your system.
Can a FILL Event Arrive After an Order Was Reported as Cancelled?
For IOC orders, could a cancel come before all partial fill trade events come in? Or, is it safe to assume that a cancel message will be processed last, and use this cancel to determine whether the order is fully processed?
For the majority of exchanges, in the case of a partially filled then cancelled order, the cancel message comes last. Yet there are some exchanges for which the cancel message can outrun trades on their way to our Order Management System (OMS). For example, these include an early version of Eurex and the CoinList and Bitstamp crypto exchanges.
Is There a Limit on the Number of Replace Requests per Order?
Yes, but the limits apply to concurrent (in-flight) replacements, not to the total number of times an order can be replaced.
No Limit on Total Replacements
An order's cancel-replace chain can be arbitrarily long. An order may be repriced thousands or even millions of times over its lifetime without hitting any cap and without growing memory usage. Each time the exchange acknowledges a replacement, the superseded request is immediately retired from the active set, so the OMS never accumulates the full chain history.
Limits on In-Flight Replacements
Two OMS validation settings under engine.validation.settings control in-flight replacements:
allowFastReplace(defaultfalse). When disabled, an order may have at most one unacknowledged replacement at a time. A second concurrent replace request is rejected withCANT_MODIFY_UNACKNOWLEDGED_ORDER. An attempt to replace an order that has not been acknowledged yet is rejected as well. With the default configuration, this is the limit that applies.maxPendingReplaceCount(default10). Caps the number of pending replacements in the chain. A request that exceeds it is rejected with "Pending replace chain for this order is too long". A negative value disables the check. BecauseallowFastReplace = falsealready restricts an order to one in-flight replacement, this setting only matters onceallowFastReplaceis enabled.
engine {
validation {
settings {
allowFastReplace = false
maxPendingReplaceCount = 10
}
}
}
Optional Rate Limit
The MaxReplaceFrequency risk limit caps how many replace requests an order may issue within a time interval. It bounds the replace rate rather than the chain depth and is configured per risk limit definition.
Practical Implication
With default settings, an active order chain occupies a small, constant amount of memory regardless of how many times it has been replaced. It holds at most three entries:
- the original request, retained to preserve the correlation order ID;
- the current working request;
- at most one in-flight replacement.
Retired requests move into a fixed-size cache of recently completed entries (maxInactiveOrdersCacheSize, default 4096 per order source) and are eventually recycled.
Market Maker Algorithm
The Market Maker (MM) algorithm has its own limit on chain length, so MM clients will not reach the 4096-entry OMS cache limit. The smartBreakChainReplace parameter (default 500) sets the maximum length of a cancel-replace chain for a live quote. When a quote reaches this length, the algorithm breaks the chain without leaving the book:
- It replaces the quote with half of its remaining quantity.
- It submits a new order at the same price for that half. The new order starts a fresh chain.
- It cancels the original order only after the new order has been acknowledged, so the quote stays on the book throughout the handoff.
Does Memory Usage Grow with the Length of an Order Replace Chain?
Does every replacement create and store a new order state, so that memory usage grows linearly with the chain length? Or does each replace store only a small amount of additional information, such as identifiers?
Each replace request does create a new entry, but the number of entries the OMS tracks per order is bounded by two factors:
- The maximum number of in-flight replacements. While an order is active, each replace request is expected to receive an exchange ACK or NACK. This keeps the number of pending replace requests low, especially given the request rate limits many crypto exchanges impose. For a typical market making algorithm, there is at most one in-flight replacement per order.
- The OMS cache configuration. The OMS caps the number of inactive order entries it keeps (4096 by default).
In other words, memory usage grows linearly with the chain length, but only up to a fixed ceiling.
Example. A market making algorithm continuously adjusts the prices of passive bid and offer orders on 5 instruments — 10 active order chains in total. The OMS cache is configured for 4096 inactive entries, and the exchange enforces a fairly conservative rate limit of 10 requests per second. At that rate, each order can be repriced only about once per second. With exchange latency in single-digit milliseconds, every replace request is acknowledged before the next one is sent, so there are no in-flight requests. Each active chain therefore holds just its original and current requests (plus at most one in-flight replacement, if one is pending) — about 10 + 10 + 10 entries in total — and all 10 chains share the same inactive entry cache. No matter how many times each order is replaced, the OMS never holds more than 4096 + 10 + 10 + 10 replace request entries.
Also note:
- The OMS does not store the entire replace request — only a few key fields such as price, quantity, and order identity.
- Similar caching may also take place in the algorithm and in the trade connector, since Ember uses a share-nothing multithreading model and each component keeps its own state.
Does Replace Processing Time Depend on the Length of the Replace Chain?
For example, does replacing an order at position 1,000 in the chain take longer than replacing one at position 100? In other words, is replace processing O(1), or does it depend on the chain length, O(N)?
For normal order flow, processing is O(1). Normal order flow means processing an ACK or NACK for one of the pending replace requests. The OMS locates the replace request by its order ID, and uses a linked list to add and remove entries, so the cost does not depend on how long the chain is.