Skip to content
Get Started

Boa Spreader

Boa Spreader trades synthetic spreads of 1 to 4 legs on CME futures:

Algo What it does
Spreader (SPRD) Buys or sells a quantity of the spread at a target spread price. Rests orders on the legs you choose to quote and hedges the other legs as soon as a quoted leg fills.
Market Maker (MM) Quotes both sides of the spread around the implied market, with levels, skew, stops, position limits and adverse-selection protection, and hedges every fill. With one leg it is a single-instrument market maker.

Boa Spreader has two parts: the application, which runs next to the trading session and does all trading, and the Boa Spreader window in the Real-Time GUI, which controls it. The application keeps trading when the GUI is closed. Up to 32 algos run at once, on the same or different spreads. The protocol between the two is open: see Boa Spreader Protocol to build your own application or front end.

Note

Test every configuration on the simulator before trading live.


Concepts

Term Meaning
Spread price The sum over the legs of sign x multiplier x leg price, where the sign is + for BUY legs and - for SELL legs. Example: +ESZ6 -NQZ6 with multipliers 1 and 1 is ES minus NQ.
Ratio Lots of a leg per spread (2:1 = 2 lots of leg 1 per lot of leg 2). Ratios do not enter the price.
One spread ratio lots of every leg. All quantities and positions in Boa Spreader are in spreads.
Spread tick (step) The smallest multiplier x tick size across the legs. All market maker "ticks", DOM rows and +/- buttons use it.
Implied bid / ask What the spread can be sold / bought at now: legs you would buy at their ask, legs you would sell at their bid. Implied size: the smallest leg size / ratio.
Quoted leg Rests a passive order at the leg price that achieves the spread price with the other legs at their current market. Rounded to the leg tick in your favour, never at or through the leg's opposite side. With several quoted legs, all rest; the first to fill makes the others hedge legs.
Hedge leg Sent only after another leg fills.
Hedging A fill on any leg hedges the other legs to the same proportion, in whole lots, with a limit order at the market plus the leg's Payup. The hedge follows the market up to the leg's Slip; after Hedge ms the rest goes as a market order. Hedges above the clip size are split.
Algo P&L Realized plus unrealized at the leg bid/ask, in account currency, from the algo's own fills.

Running the Application

The application is in src/BoaSpreader of the package. Build it there (or make boaspreader) and start it as a standalone program or as a plugin:

standalone
g++ -std=c++20 -O2 boaspreader.cpp -I nanocondaroot/include -L nanocondaroot/lib -lnanoconda -o boaspreader
./boaspreader -e XCME -s <symbol1>,<symbol2>,... -u <username> -p <password> -a <account> [-c cpu]
plugin (.so or .wasm)
nanoconda-cli -a pluginloader -i boaspreader.so -- plugin -e XCME -s <symbols> -u <username> -p <password> -a <account>
Argument Description
-e Exchange.
-s Comma-separated symbols, up to 32. Only these symbols can be used as legs.
-u / -p Username / password.
-a Trading account.
-c CPU to pin to (optional).

The application logs to boaspreader.log (see Log).

Source Files

File Contents
src/BoaSpreader/boaspreader.cpp The application: entry points (main, init_nanoconda_plugin, plugin_stop), the list of algos, spread positions and the spread trade log, requests from the window (start, control, trade log), the state sent to the window, account Max Loss.
src/BoaSpreader/ncboaalgo.h One algo, spreader or market maker: settings check, quoting, hedging, protection, exit, and the algo row shown in the window.
src/BoaSpreader/ncboaengine.h Definitions shared by boaspreader.cpp and ncboaalgo.h.
src/BoaSpreader/Makefile Builds boaspreader (native) and boaspreader.wasm (WebAssembly plugin).
include/nanoconda_boa_protocol.h Messages between the application and the Boa Spreader window (Boa Spreader Protocol).
src/algos/ Shared trading logic: orders (ordercore.h), application core (hostcore.h), market maker (marketmaker.h) and spread pricing and hedging (spreader.h). See Algo Framework: Files.

The Boa Spreader Window

Log in to the GUI with a trader user and open the window from the window menu (=) with the Boa Spreader checkbox. It is available in every tab.

Boa Spreader window

# Area # Area
1 Status 7 Adverse-selection protection
2 Execution settings 8 Algos
3 Emergency buttons 9 Spread trades and positions
4 Legs 10 Order entry
5 Spread line 11 Spread DOM
6 Market maker
  • Move the window by its title bar. » in the title bar opens it in its own browser window.
  • Nothing is stored in the browser: inputs start at their defaults on every page load; algos, positions and trades come from the application.

1. Status

Item Meaning
Session Green dot: the trading session is up. Red: it is down.
Program Green dot: the application is connected, allowed to trade and sending data. Red: hover for the reason (Program Offline, Program Is Blocked From Trading, No Boa Spreader Data).
P&L Account session P&L.
Fill / Rej Fills / refused orders (exchange and pre-trade risk) since the application started.
all hedged / UNHDG n age n algos have legs being hedged; the oldest hedge is age seconds old.

2. Execution Settings

Hedge ms, Overfill and Msgs/s apply to algos started afterwards. Numbers are typed in.

Setting Default Range Description
Hedge ms 0 0-600000 If a leg is still unhedged after this time, its limit hedge is cancelled and the rest is sent as a market order. 0 = off.
Overfill checked checkbox Spreader only. When a leg fills beyond the target: checked hedges the other legs to keep the ratio (more spreads than Qty may complete); unchecked hedges only up to the target and keeps the extra lots as a leg position.
Msgs/s 150 0-1024 Order messages per second per algo; quotes may use 80%, hedges and exits 100%. 0 = no algo limit. When the account's request limit is hit, the application sends nothing new for 1 second (cancels still go out).
Max Loss + SET 0 0-100000000 Account max loss in currency, 0 = off. When the session P&L reaches -Max Loss, the application runs EXIT ALL and refuses new algos until SET is pressed again; the label shows LOSS HIT. SET turns blue while an edited value is not applied. Resets to 0 when the application starts.

3. Emergency Buttons

Button What it does
EXIT ALL EXIT on every algo: cancels their orders and closes their leg positions at market. Greyed out when there is nothing to exit.
Flatten Closes all positions of the account, also those not opened by Boa Spreader. Boa Spreader positions are not updated by it; use EXIT ALL to close them. Greyed out when the account is flat.
Block Algo / Allow Algo The account's algo kill switch: blocks all automated programs, Boa Spreader included, from sending new orders (asks for confirmation) / allows them again.
S Screenshot of the window.

Flatten and Block Algo are not shown to view-only users.

4. Legs

Up to 4 legs; empty rows are ignored. Numbers can be typed or stepped with ▲/▼ (hold to repeat).

Column Default Range Description
Symbol Leg instrument, from the application's -s symbols.
Side BUY BUY / SELL Sign of the leg in the spread; click to toggle.
Ratio 1 1-100 Lots per spread.
Mult 1 1-10000 Price multiplier.
Quote on on / off Rest passive orders on this leg; off = hedge only. At least one leg must be quoted; a 1-leg spread is always quoted.
Payup 1 0-100 Hedge price in leg ticks beyond the market: buy hedge at ask + payup, sell hedge at bid - payup.
In 0 0-100 Spreader only. Inside slop: ticks a resting quote may be more aggressive than its ideal price before it is moved.
Out 0 0-100 Spreader only. Outside slop: ticks a resting quote may be less aggressive than its ideal price before it is moved.
Lean 0 0-1000 Spreads (lean x ratio lots) that must rest on this leg at its hedge price before other legs quote against it. 0 = off.
Slip 0 0-1000 Max leg ticks a hedge may move beyond the market at the start of hedging. 0 = no limit.
Bid / Ask Leg best bid / ask.
Bid x Mult / Ask x Mult Leg bid and ask times the multiplier.
Net Pos Net lots of the symbol held by all Boa Spreader spreads.

5. Spread Line

SPREAD 3 @ 1414.75 / 1416.50 @ 1 step 0.25: implied bid size @ implied bid, implied ask @ size, spread step. "waiting for leg quotes": a leg has no bid or ask. "select 1 to 4 different legs": the legs are not a valid spread.

6. Market Maker

Click START MM to start a market maker on the current legs with these settings. Ticks are spread ticks; quantities are spreads.

Setting Default Range Description
Qty 1 1-10000 Spreads per quote level.
Sides Both Both / Buy / Sell Sides to quote.
Ticks Away 1 0-1000 Buy at implied bid - ticks, sell at implied ask + ticks. 0 = join.
Levels 1 1-5 Quote levels per side.
Level Step 1 1-100 Ticks between levels.
Sticky 0 0-100 Quotes stay in place while the target moves toward the market by up to this many ticks. 0 = off.
Skew/Fill 0 0-100 Both quotes move (position / Qty) x Skew/Fill ticks against the position (lower when long, higher when short). 0 = off.
Min Edge 0 0-1000 With a position, the exit quote is at least this many ticks beyond the average entry. 0 = off.
Reprice checked checkbox Unchecked: working quotes are not moved, and a new quote on the side that adds to the position is placed at least Ticks Away (minimum 1) beyond the last fill on that side; with Min Edge the exit quote sits exactly at Min Edge.
Max Pos 5 1-100000 Maximum spread position long or short, including spreads still being hedged.
Max Loss 0 0-100000000 Exit at market when this algo's P&L reaches -Max Loss (currency). 0 = off.
Stop Ticks 0 0-10000 Exit at market when the implied market is this many ticks against the average entry. 0 = off.

The protection settings (header line and the two right columns) are described in Adverse-Selection Protection.

How it quotes

  1. Buy top = implied bid - Ticks Away - skew; sell top = implied ask + Ticks Away - skew (skew includes S+/S-).
  2. Reprice and Min Edge are applied, then prices are kept at least one tick inside the implied market; then Sticky (not on the closing side while Min Edge is on).
  3. Each side quotes min(Levels, room / Qty) levels, Level Step apart. Room is Max Pos minus the position on the buy side and Max Pos plus the position on the sell side, minus spreads being hedged. MAX POS shows when no side can quote.
  4. When prices move, orders already at a needed price are kept and as few orders as possible are moved.
  5. After a fill the filled side waits for the next market update before quoting again.
  6. A quote that cannot be moved within Msgs/s and is now better than the new top price is cancelled and re-quoted after 2 seconds.
  7. Every fill is hedged with the leg and execution settings.

STOP cancels the quotes and finishes hedges, keeping the position; EXIT also closes the position.

7. Adverse-Selection Protection

Protection Setting Cancels Back
Pull After Fill Pull After Fill checked the filled spread side after Pause ms without the implied price moving against the fill
Book imbalance Imbalance % > 0 the thin spread side when no quoted leg is thin
Sweep Sweep Lots > 0 the swept spread side after Pause ms
Queue depletion Depletion % > 0 the spread side whose leg queue is consumed after Pause ms without a new depletion
Pull On Limit Pull On Limit checked both sides after the 1-second request-limit pause
Setting Default Range Description
Pause ms 500 0-60000 How long a side stays cancelled after Pull After Fill, a sweep or a queue depletion.
Keep Closing checked checkbox Keep orders that close the position (see below).
Pull After Fill unchecked checkbox Cancel the filled side after a fill.
Pull On Limit unchecked checkbox Cancel all quotes when the account's request limit is hit.
Imbalance % 0 0-50 Thin side threshold. 0 = off.
Sweep Lots 0 0-32767 Aggressive leg lots against a side within Sweep ms. 0 = off.
Sweep ms 100 0-60000 Time window for Sweep Lots.
Depletion % 0 0-10000 Consumption speed of the queue ahead, in % of its normal speed (200 = twice as fast). 0 = off.
ETA ms 300 0-60000 Time in which the queue ahead would be gone at that speed.

All protections cancel the side's quotes on every quoted leg (they never move them), quote the side again with new orders when they end, never cancel hedges, and leave the position and the other side unchanged (Pull On Limit cancels both sides). While a side is out the algo stays RUNNING and its quotes disappear from the spread DOM. A pause can end up to about 100 ms later than set when the legs are quiet.

Pull After Fill. When any leg of a spread side fills (fully or partly), all quotes of that side are cancelled; hedging continues. The side stays out for Pause ms; the pause starts again each time the implied price on that side moves further against the fill (implied bid lower after buying the spread, implied ask higher after selling it).

Imbalance %. For each quoted leg, the leg's book side where the spread side's leg order rests is checked (buying the spread with a - leg sells that leg, so its offers are checked): share = that side's top-of-book size / (bid size + ask size). The spread side is cancelled while any quoted leg's share is below Imbalance % and quotes again at Imbalance % + 10. Example, 30: bid 2 / ask 18 (10%): the side bidding that leg is cancelled; 7 / 13 (35%): still cancelled; 9 / 11 (45%): quoted again.

Sweep. Only trades on quoted legs count, at any price, including your own fills. A trade counts against the spread side whose leg order it would hit (sellers hitting bids against the side bidding the leg, buyers lifting offers against the side offering it). Counting starts at the first such trade and lasts Sweep ms; reaching Sweep Lots cancels the side for Pause ms, on the trade itself, before the book update. Sweep ms 0: only a single trade of Sweep Lots or more counts.

Queue depletion. Queue ahead of a leg quote at price P = the leg's book size at better prices (10 levels) plus the size that was at P when the quote joined, reduced by trades at P; orders joining P later are not counted. While the side has no quote, the price of its would-be top quote is used. Consumption = trades at or better than P (counted when they arrive) plus book decreases (cancels, levels removed); each trade counts once. The side is cancelled when the consumption speed over about 200 ms is at least Depletion % of the speed over about 30 s and the queue ahead would be gone within ETA ms at that speed. Cancelled for Pause ms, extended while this holds. Not active in the first 5 seconds of the algo.

Preset Depletion % ETA ms Result
Aggressive 150 500 Cancels early and often; more cancels and lost queue position.
Moderate 200 300 Cancels on clear bursts close to the quote.
Relaxed 600 150 Cancels only on extreme bursts right in front of the quote.

Pull On Limit. When the platform refuses an order or replace with REQUEST_LIMIT, the application sends nothing new for 1 second. Every market maker with Pull On Limit checked cancels all its quotes (the one whose request was refused at once, the others at their next market update) and quotes again when the second has passed. Hedges and exits are not cancelled. Msgs/s pacing does not trigger it.

Keep Closing. When a protection cancels the spread side that closes the position (sell side when long, buy side when short), each quoted leg keeps its orders on that side, best price first, while they fit within the spread position x the leg ratio; the first that does not fit and all behind it are cancelled. No new orders or price changes on that side until the protection ends. When flat, or unchecked, the side is cancelled completely. Example: long 2 spreads with 3 sell levels of 1 spread, request limit hit: buy quotes cancelled, the 2 best sell levels kept, the third cancelled.

8. Algos

One row per algo; the list scrolls.

Column Description
ID Algo number. Click the row to filter the spread trades to this algo.
Type SPRD or MM.
Spread Legs, e.g. +4xESU6*4 -NQU6 (4x = ratio, *4 = multiplier, shown when not 1).
Side B, S or B/S.
Price Spreader: target price. MM: top buy / top sell.
Done Spreader: spreads done / quantity (FILLED when complete). MM: spreads traded.
Pos / P&L Spread position and P&L of the algo.
Status Detail below, or the state (RUNNING green; STOPPING, EXITING, DONE yellow; ERROR red). A red cell means a leg is unhedged; hover for leg, lots, age and MKT once sent to market.
Status detail Meaning
UNHEDGED A leg is being hedged.
NO MKT A leg has no valid market; quoting paused.
MAX POS MM cannot quote either side.
STOPPING STOP in progress.
FILLED / STOPPED / CANCELED / EXITED Why the algo is DONE.
MAXLOSS / STOP LS Exiting because of Max Loss / Stop Ticks.
LATE FILL A fill arrived after the algo finished; it is hedged and the algo finishes again.
STUCK ORD An order has had no exchange response for 10 seconds.
BLOCKED / NO PERM / SESS DN Algo kill switch on / no trading permission / session down.
Button Spreader Market maker
+ / - Price up / down one spread tick. Ticks Away +1 / -1 (- re-quotes both sides at once, ignoring Sticky).
S+ / S- Not shown. Both quotes one tick higher / lower.
EDIT Change price and quantity. Change Qty; shows Ticks Away and skew.
STOP Stop quoting, finish hedges, keep the position. Same.
EXIT Cancel quotes, close all leg positions at market (split by clip size); logged as an EXIT spread trade. Also for DONE / ERROR algos with a position. Same.
DEL Remove a DONE or ERROR algo without working orders. Same.

If one of an algo's orders is cancelled from outside Boa Spreader (for example from Live Orders), the algo stops (STOPPING).

9. Spread Trades and Positions

SPREAD TRADES: one row per completed spread, newest first: time (UTC), algo, type, spread, side, quantity, spread price and each leg's side, lots and average price. EXIT closes are one row each.

  • The third tab reads ALL ALGOS, or ALGO n while filtered: click an algo row to filter, click the tab to clear.
  • Download saves the trades as CSV.
  • » opens trades and positions in a separate, resizable browser window (the filter is shared).

SPREAD POSITIONS: one row per spread definition across all algos: Pos, Avg Px, Realized, Unrealized, Net, Spreads and Lots traded.

Both cover the current application run (last 32,768 spreads). When the application stops, the trade log stays visible until the next application sends data.

10. Order Entry

Control Description
Qty Spreads to fill, 1-10000 (qty x ratio per leg must fit the clip size). Also used by DOM clicks.
Price Target spread price; ▼/▲ = one spread tick. Set to the implied mid when the spread first has a market and whenever the legs change; afterwards only by you.
JOIN BID / JOIN ASK Start a BUY spreader at the implied bid / a SELL spreader at the implied ask.
BUY / SELL Start a BUY / SELL spreader at Price.

The buttons are greyed out without a valid spread or application data; JOIN BID / JOIN ASK also without an implied market; BUY / SELL also until Price has been set for the current spread. A spreader finishes (DONE, FILLED) when Qty spreads are complete.

11. Spread DOM

A price ladder of the current spread, one row per spread tick.

  • Follow Market (on by default) keeps the market centered; scrolling turns it off; changing a leg turns it on.
  • Under the header: spread name, open position of this spread (Pos +5 @ 1252.95, Pos 0 when flat) and its net P&L, for all algos on this spread (as in SPREAD POSITIONS).
Element Meaning
Blue bars (left) / orange bars (right) Implied depth, bid / ask, with the size in spreads.
Solid blue / orange price Best implied bid / ask.
Gold badges Your orders: quantity, M for market maker levels.
Green / red line with +n / -n Open position at its average entry price (an arrow at the edge when off screen).

Depth (up to 10 levels per side) is built from the leg books: each level is the number of spreads tradable at that spread price by trading all legs together, using up leg size level by level. It thins out when any leg's book is thin.

Hover a level for what-if prices: each quoted leg's price, each hedge leg's side and market, and "lean not met" when a lean would stop the quote.

Where Click Drag
Left / right, empty level Start a BUY / SELL spreader at that price with Qty.
Your spreader's badge Stop that spreader. Drag to another level: move the spreader there.
Price column Copy the price into Price.

Market maker badges are display only. Badges show the algos of the current leg setup.

When the Window Is Disabled

The window works only with the Boa Spreader application. When it cannot be used, a bar appears under the top row and the window below it and the application settings are greyed out; Flatten, Block Algo / Allow Algo and S stay usable.

Bar When Clears
Grey: This window requires an application implementing the Boa Spreader protocol... No Boa Spreader application is connected to the account. When one connects and sends data.
Amber: Boa Spreader application not responding... No data from the application for 4 seconds (last data stays on screen). When data arrives again.
Red: Boa Spreader application protocol vX, this window vY... Application and GUI use different protocol versions. Update the application or the GUI.

Errors

Message Cause
BAD SPREAD DEFINITION No leg, a repeated symbol, legs with different price precision, ratio or multiplier below 1, or no quoted leg.
SYMBOL NOT TRADED BY THE APP Symbol not in the application's -s list.
BAD PARAMETERS A value out of range, or the action does not apply to the algo or its state.
QTY ABOVE CLIP SIZE qty x ratio above the account clip size for a leg.
ACCOUNT MAX LOSS REACHED Account Max Loss hit; SET a limit (or 0) to allow new algos.
NO FREE ALGO SLOT 32 algos, or 16 spread definitions with positions. Remove finished algos.
ALGO NOT FOUND / ALGO ACTIVE The algo was removed / cannot be removed or exited in its state.
TRADING SESSION DOWN Session not up, algos blocked, or the application is starting.
PROTOCOL VERSION MISMATCH Application and GUI use different protocol versions.

Typical Use

Task How
Buy / sell a spread at a price Set the legs, Qty and Price; click BUY / SELL, or click the left / right side of the DOM at that price.
Join the market JOIN BID / JOIN ASK.
Move a working spreader Drag its DOM badge, +/- in its row, or EDIT.
Make a market Set the legs and market maker settings, click START MM; adjust with +/- (width) and S+/S- (skew).
Get flat EXIT on the algo row; EXIT ALL for every algo.
Stop all automated trading Block Algo.
Close every account position Flatten (includes positions from outside Boa Spreader).

Restart

Every application start is fresh: no algos, positions or trades are kept, and algo numbers start at 1. Orders not sent by the running application (previous runs, other programs, manual orders) are never touched and do not affect algo positions; cancel them from the GUI. Use EXIT ALL before stopping the application. Several Boa Spreader applications can run on one account; each manages only its own orders.


Log

boaspreader.log records every order sent, replaced and cancelled, every ack, reject and fill, and every spread trade. Lines of an algo start with #<id>.

Tag Event
START / LEG / MM Algo settings at start (the second MM line lists the protection settings).
STATE / INFO State and status-detail changes.
NEW / REPLACE / CANCEL / ACK / REPLACED / CANCELED Order events.
FILL / PARTIAL / SPREAD / EXIT Fills, completed spreads, exits.
HEDGE / HEDGED A leg becomes unhedged (also hedge held at max slip, or an own order cancelled first) / hedged again.
RISK / REJECT Refused by pre-trade risk (including REQUEST_LIMIT) / by the exchange.
REQUEST ... refused Refused GUI request and the reason.
MAXLOSS, STOPLOSS, PACE, ADJUST Max loss / stop exits, paced re-quotes, button changes.
DUP ..., GAP FILL, LATE FILL, UNMATCHED, STUCK Duplicate, missed, late or unknown exchange responses; orders without a response.
TRADING, SESSION, MARKET, CLIP Session, market data and clip size changes.
BOOK All 16 spread definitions are in use; a flat, unused one is replaced.
SHUTDOWN The application is stopping and cancels its orders.

Limits

Item Limit
Legs per spread 4
Symbols per application 32
Algos 32 at a time
Spread definitions with positions 16 (flat, unused ones are reused)
Market maker levels 5 per side
Spread quantity 100,000
Spread trades kept 32,768