MarkupProfile
Markup and spread settings
1) Markup and spread units: Markups (markup_bid/markup_ask) and spread boundaries (spread_min/spread_max) can be specified as decimal values, in units based on symbol.price_unit, or in basis points (bps). Basis points represent 1/100th of 1%.
2) Bid markup sign: Positive values for markup_bid widen the client price, benefiting the broker (markup), while negative values narrow the client price, reducing the broker’s profit (markdown).
3) Precision settings: The precision settings include MINUS_3, MINUS_2, MINUS_1, DEFAULT, PLUS_1, PLUS_2 and PLUS_3 to control rounding adjustments.
4) Symbol markup limits: symbol.markup_min and symbol.markup_max constrain the combined profile markup and skew on each side, in absolute price amounts. They also limit minimum-spread widening. They are not a cap on every provider offset, final spread or execution slippage.
Warning: configure symbol markup limits
Configure and verify realistic symbol.markup_min and symbol.markup_max values for each symbol. These are absolute price amounts, independent of the profile unit. Very generous limits provide little protection against oversized adjustments. Zero is an active bound. Enable only the markup and spread units your operation needs.

MarkupProfile contains markup and spread settings that are applied to price updates and execution on a per-symbol basis. These settings are defined in MarkupProfileSetting. MarkupProfile has the following attributes and can be accessed via pending config or real-time config:
| attributes | required | default setting | attribute type | description |
|---|---|---|---|---|
| id | Y | – | INT | Uniquely identifies each markup profile by a numerical value. |
| name | Y | – | VARCHAR | The name of the markup profile. |
| description | N | – | VARCHAR | The description of the markup profile. |
MarkupProfileSetting

MarkupProfileSetting defines the settings of a given MarkupProfile. MarkupProfileSetting has the following attributes and can be accessed via pending config or real-time config:
| attributes | required | default setting | attribute type | description |
|---|---|---|---|---|
| id | Y | – | INT | Uniquely identifies each markup profile setting by a numerical value. |
| profile | Y | – | INT | The markup profile, stored as its numeric ID; the portal displays the profile name. |
| by | Y | – | VARCHAR | Specified as security ‘sec’ or symbol ‘sym’. |
| key | Y | – | VARCHAR | If ‘by’ is set to ‘sym’, the ‘key’ has to be a Symbol and cannot be set to ‘*’. If ‘by’ is set to ‘sec’, the ‘key’ has to be either the security name or ‘*’, which acts as a wildcard. Note : More specific rules have priority over less specific. For example a setting for a ‘sym’ has priority over ‘sec’ with a defined security and which itself has priority over a ‘sec’ with ‘*’ specified. The matching rule selects a complete set of layers; fallback layer sets are not merged. |
| layer | N | 0 | TINYINT | The layer number within the profile and selector (by/key). Layers are ordered by this number and duplicate numbers are rejected; number them consecutively from 0. |
| quantity | N | -1 | DOUBLE | The quantity parameter defines the assignment of Markup profile layers to maker quotes in the LiquidityPool. We define q(n) as the quote in the n-th position, with q(0) being the first (ToB) quote. We further define qty(n) for the quote q(n) as the aggregated liquidity of quotes ranging from q(0) to q(n-1). A quote q(n) is assigned to the first layer whose quantity is greater than qty(n). If no layer with sufficient quantity exists, q(n) is assigned to the last layer. The top-of-book quote q(0) always uses the first layer. Quantities are expressed in the symbol’s internal quote/order quantity units, with no conversion to lots; allowed values are -1 or 0 and above. Give each layer a quantity greater than its preceding layer: XCore does not enforce this order, but the assignment described here assumes it. By setting the quantity of all layers to -1 for a specific profile and symbol, layer assignment based on aggregated liquidity is disabled. This does not pin every stream to its first markup layer: layer and layer_ioc streams can still advance markup rows with their output layers. Additionally, layer selection by quantity is bypassed for order execution if layers are explicitly defined in ConnectorAccountSetting.layers.Example: Consider 4 layers with the following configuration: Layer_0: quantity=100k -> applies for qty(n) ≥ 0 and < 100k Layer_1: quantity=200k -> applies for qty(n) ≥ 100k and < 200k Layer_2: quantity=300k -> applies for qty(n) ≥ 200k and < 300k Layer_3: quantity=400k -> applies for qty(n) ≥ 300k Given the below quotes and liquidity in the pool, we calculate qty(n) and assign the corresponding layer as follows: q(0): quote at position 0 with liquidity 50k ->qty(0) = 0. Layer_0 is applied. q(1): quote at position 1 with liquidity 120k -> qty(1) = 50k. Layer_0 is applied. q(2): quote at position 2 with liquidity 30k -> qty(2) = 170k. Layer_1 is applied. q(3): quote at position 3 with liquidity 110k -> qty(3) = 200k. Layer_2 is applied. q(4): quote at position 4 with liquidity 80k -> qty(4) = 310k. Layer_3 is applied. |
| markup_type | N | price_unit | STRING | The unit in which markup_bid, markup_ask and markup_skew are expressed:decimal: an absolute price amount. price_unit: multiples of symbol.price_unit. basis_point: basis points of the price, where one basis point is 0.01%. The unit must be allowed by the symbol flags of every symbol the rule applies to. |
| markup_bid | N | 0 | DOUBLE | The markup applied to the bid price, in the unit selected by markup_type:decimal: the value itself. price_unit: the value × symbol.price_unit. basis_point: price × value / 10,000. A positive value lowers the bid, worsening the client’s sell price; a negative value raises it. |
| markup_ask | N | 0 | DOUBLE | The markup applied to the ask price, in the unit selected by markup_type:decimal: the value itself. price_unit: the value × symbol.price_unit. basis_point: price × value / 10,000. A positive value raises the ask, worsening the client’s buy price; a negative value lowers it. |
| markup_skew | N | 0 | DOUBLE | A shift applied to both sides, in the unit selected by markup_type (decimal: the value itself; price_unit: the value × symbol.price_unit; basis_point: price × value / 10,000). Positive skew shifts bid and ask upward; negative skew shifts them downward. With decimal or price_unit, equal absolute offsets preserve the spread before other controls. With basis_point, each side uses its own price, so skew can change the spread. |
| spread_type | N | price_unit | STRING | Defines the unit used by spread_min and spread_max:decimal: An absolute price amount. price_unit: The configured value multiplied by symbol.price_unit. basis_point: A price-relative amount; one basis point is 0.01% of the applicable reference price. |
| spread_min | N | n/a | DOUBLE | Requested minimum spread, in the units selected by spread_type. Narrow or inverted pricing can be widened toward this bound using flexible adjustments (markup_flex). A usable reference midpoint is required; symbol markup limits, precision and tolerance can prevent the requested spread from being reached.n/a disables this bound (stored as a value of -1000000 or lower). Zero is an active bound. |
| spread_max | N | n/a | DOUBLE | Requested maximum spread boundary, in the units selected by spread_type. Published pricing is constrained or invalidated according to spread_exec. In SLIP mode, execution can exceed the published boundary.n/a disables this bound (stored as a value of 1000000 or higher). Zero is an active bound. Configure a coherent pair of bounds: XCore does not reject a minimum above the maximum. With such a pair, a quote narrower than the minimum is widened to the minimum and a wider quote is narrowed to the maximum. |
| spread_exec | N | SLIP | VARCHAR | Controls published pricing and execution when the maximum-spread condition is met: SLIP – pricing is constrained to the boundary, but execution can exceed it. Clients can therefore receive fills outside the advertised price. REJECT – constrained prices can still be published, but the maximum-spread condition blocks execution attempts. ACCEPT – constrained pricing applies to execution; the spread breach alone does not block execution. INVALIDATE – affected pricing is excluded and the maximum-spread condition blocks execution attempts. This can create gaps in the affected price stream. Other order conditions, such as TTL, determine whether a blocked attempt becomes a final rejection. Invalidation of affected pricing does not imply disconnection of the entire feed. WARNING: Using ACCEPT can result in slippage incurred by the XCore owner. Test this behavior before changing settings in a live environment. |
| precision | N | default | VARCHAR | Precision defines additional rounding applied to executable price streams, as well as to order and leg VWAP (Volume Weighted Average Price) fill-prices. The available options are: MINUS_3: Removes three digits from the default precision. MINUS_2: Removes two digits from the default precision. MINUS_1: Removes one digit from the default precision. DEFAULT: Retains the number of digits as implicitly defined by the symbol.price_unit. PLUS_1: Adds one digit to the default precision. PLUS_2: Adds two digits to the default precision. PLUS_3: Adds three digits to the default precision. Precision changes actual price rounding relative to symbol.price_unit. Bid prices and client sell fill prices are rounded down; ask prices and client buy fill prices are rounded up. The order fill price stored in the trade data ( order.fillprice) is the unrounded average of the leg prices. Streaming uses the first applicable markup layer’s precision. Instrument, adapter and execution-report requirements can impose additional rounding, so a finer profile precision does not guarantee the same precision in every output. Because provider prices are already rounded to symbol.price_unit when they are received (bids down, asks up), a finer precision applies to prices produced by markups, spread limits and averaging, not to extra digits sent by a provider. |
Note: symbol.markup_min and symbol.markup_max constrain the combined profile markup and skew on each side after conversion to absolute price. The upper bound also limits minimum-spread widening. These settings do not cap the sum of bid and ask adjustments or guarantee a final spread or slippage limit.
Examples
For EURUSD, where the price_unit is set to 0.00001 in the Symbol table:
-
A
markup_askof +5 (withmarkup_typeset toprice_unit) adds 5 points (0.00005) to the ask price, worsening it for the client. Amarkup_askof -5 subtracts 5 points (0.00005) from the ask price, improving the client’s price. -
A
markup_bidof 50 basis points (bps) (withmarkup_typeset tobasis_point) lowers the bid price by 0.50%. For example, a maker bid of 1.10000 is reduced by 0.00550 to 1.09450. Amarkup_bidof -50 bps raises it to 1.10550. These examples precede symbol limits, spread controls and rounding. -
Applying
symbol.markup_max: Withprice_unit = 0.00001, an 8-point bid markup is an absolute amount of 0.00008. Asymbol.markup_maxof 0.00010 does not clamp that contribution just because the ask also has a 5-point markup: the two sides are not added together for this check. Skew and minimum-spread widening can also affect the adjustment. These amounts illustrate the units; they are not recommended limits.