Robot examples

The examples are ordered as a course, and every one of them is the same twelve declarations in the same order: what differs between a moving-average crossover and a book-imbalance market maker is the body of one callable and the parameters on the rules. Each example is a directory holding a C++ and a Python version of the same strategy.

All examples on GitHub

Hello world

Brings a robot up from nothing: the process-wide configuration, the full assembly, a parameter sweep, several feeds, the saved recipe, and the swap that takes it live.

01 — Initial parameters

No robot — process-wide configuration only; each account captures the data folder at construction.

Sets the data folder, the log folder and the log level before the first account exists. An account resolves its data folder when it is built, so the example builds one account, switches the folder, builds a second, and each blotter file sits in the folder configured at its own construction time.

Source on GitHub

02 — MACD

Input: MACD of the close → Patterns: thresholds against zero → Rules: market entry and exit.

The Input computes a MACD, the distance between a twelve-day and a twenty-six-day exponential average of the close, and returns readiness only once the slow average has seen enough days. Threshold Patterns compare that distance against zero, and the Rules bound to them enter and leave.

Source on GitHub

03 — Grid search

One robot built four times by the grid runner — a fresh account per lookback, the same history.

The same robot built four times, over lookbacks of 10, 20, 50 and 100 days against a 200-day trend. The grid runner takes a builder callback that assembles a fresh account for every parameter value and feeds it the same history, and the independent grid points run side by side on a pool of worker threads.

Source on GitHub

04 — Multiple contracts

Inputs: average AAPL close, average BTC mid → Patterns: threshold and peak → Rules: market entry and limit exit on WTI.

Three feeds of three different shapes on three adapters: daily AAPL bars, BTC/USDT quotes and WTI trade prints. Two Inputs average the Apple close and the Bitcoin mid, a threshold Pattern and a peak Pattern watch them, and the Rules trade a third contract, WTI, which no Input watches at all.

Source on GitHub

05 — Multiple adapters

Inputs: 50-day and 200-day AAPL averages → Pattern: crossover → Rules: entry and exit; BTC/USDT is subscribed for marking only.

One account, two market-data adapters: daily bars for the equity and a quote stream for the crypto pair. AAPL is traded off the golden cross of its fifty-day and two-hundred-day average Inputs, while BTC/USDT carries no Input and no Rule and is subscribed to the quote adapter only so the portfolio can mark it.

Source on GitHub

06 — Save / Load — Research → Production

One graph, two processes: Python saves the recipe, C++ loads it, binds each Input to a fresh adapter and starts.

The Python leg registers its two processors under keys, builds a WTI crossover from Inputs declared by those keys, runs the backtest and saves the recipe: contracts, inputs, patterns, rules and the robot travel, adapters and execution do not. The C++ leg registers the same processor keys, loads the robot, binds each restored Input to today's adapter, and starts.

Source on GitHub

07 — Live trading

Input: traded volume → Pattern: threshold → Rule: market entry; the execution is swapped from the Simulator to a broker callback.

A backtested robot goes live by swapping only its two ends: the IN end is an ordinary market adapter that a live feed pushes into, the OUT end is a custom execution whose transmit callback receives every order the engine emits and reports fills back. The strategy body is trivial on purpose — any trade print carrying volume is a buy signal and the order size is that volume — because the subject is the seam.

Source on GitHub

Robots

Builds strategies with that assembly, changing the code inside one callable and the parameters on the rules and nothing else.

08 — Gradient-boosted model

Input: model forecast from mid, spread and quote imbalance → Patterns: thresholds at zero → Rules: market entry and exit.

The MACD robot with the processor replaced. A gradient-boosted model trained before the run lives inside a bid/ask Input that derives mid price, spread and quote imbalance from every tick and pushes the model's forecast as the Input's value, and two thresholds at zero put the robot long while the forecast is positive and flat once it turns.

Source on GitHub

09 — Rebalance

Patterns: two timestamps → Rules: one market entry and one rebalance that adds to the open position.

Two timestamp Patterns drive an entry Rule and a rebalance Rule: the entry Pattern fires once, the rebalance Pattern rearms one second after firing and fires twice. The rebalance maintains an existing position instead of opening or closing one — it chains an adjustment order onto the open position, additively, and does not bring the position to a target size.

Source on GitHub

10 — Market maker

Inputs: two book feeds splitting client flow → Patterns: four formulas reading the live position → Rules: four orders sized from the signal.

Two book Inputs split client order flow — one keeps the client sells the maker buys against, the other the client buys it sells against — and four formula Patterns whose closures read the live position through get_position_state decide which side to quote: below the upper inventory band the maker quotes both sides, at the band it stops adding and trades only the side that unwinds, until the inventory is back to zero. The four Rules use a from-signal quantity, so every order the maker sends is exactly the size of the client order it absorbs.

Source on GitHub

11 — Market maker with amendments

Input: recorded prints → Patterns: outsized trade, same-side run, quiet gap → Rules: cancel, replace and modify on the one resting quote.

One measurement pass over each recorded print produces the three facts the maker reacts to, each of them a Pattern: an outsized trade relative to the running average size, a third trade in a row on one side, and a silence longer than ten seconds. One quote rests at a time and one amendment Rule acts on it per fact — a cancel pulls it, a replace steps it away and shrinks it, a modify restores it to full size.

Source on GitHub

12 — Voting group

Input: signed sum of three robots' fills on an executed-trade adapter → Patterns: two thresholds → Rules: entry and exit for a fourth robot.

Four robots on one account: three vote by a seeded coin flip on every WTI bar, and the fourth trades their behaviour. The voter's Input over an executed-trade adapter keeps the signed sum of the traders' fills, and two thresholds over that net put the voter long while the group is net long and flat when the net returns to zero.

Source on GitHub

13 — Order-book imbalance

Input: built-in book imbalance over an L3 book → Patterns: thresholds at +0.2 and −0.2 → Rules: entry and exit on each side.

The account owns a real L3 book replayed from recorded quote snapshots, and the built-in imbalance Input reads it: whose resting size is bigger, the buyers' or the sellers', +1 when only bids rest and -1 when only offers do. Two thresholds at plus and minus a fifth drive the robot both ways, with four Rules covering entry and exit on each side.

Source on GitHub

14 — The same signal on L1, L2 and L3

The graph of 13 unchanged; the only line that differs is the book's construction — L1, L2 or L3.

The imbalance robot of the previous example, run unchanged on all three book depths a venue may publish: the only line that differs between the three variants is the book's construction as L1, L2 or L3. The feed adds at each step exactly the size that drags the book onto the next target imbalance, so the sequence of signals is known before the run starts and the three variants can be compared field by field.

Source on GitHub

15 — Cross-venue book arbitrage

Inputs: imbalance on an L2 book and on an L3 book → Patterns: formulas comparing the two → Rules: entry and exit in a third contract.

The same asset is quoted on two venues: an L2 book tracks the first, an L3 book tracks the second, and each feeds its own imbalance Input. Each formula Pattern remembers the last value seen from each Input, refuses to answer until both books have spoken, and fires when the two disagree by more than 0.3; the Rules take the position in a third, liquid contract that neither book observes.

Source on GitHub

16 — Multileg butterfly

Patterns: two timestamps → Rule: one multileg transaction of three option legs, filled together or not at all.

Two timestamp Patterns supply the two moments, and the Rules submit a SPY call butterfly — long one 440 call, short two 450 calls, long one 460 call — as a single multileg transaction, each leg a descriptor carrying its own contract, side, quantity, limit price and transaction kind. No leg fills until every leg's market has reached its price, and the exit reverses every leg in one all-or-nothing transaction.

Source on GitHub

17 — Multileg strangle hedge

Patterns: two timestamps → Rule: one multileg transaction of a future and three option legs.

The same atomic mechanics, now mixing instrument types inside one transaction: a long CLF26 future carries the directional view, two long out-of-the-money puts at 45 and 44 insure it against a fall, and a far out-of-the-money 60 call buys the upside back. Four legs, one hedged position, filled together or not at all, so the hedge never exists half built.

Source on GitHub

Risk

Adds risk control, in the form the engine computes inside itself and in the form that rests at the venue.

18 — Internal risk calculation

Risk policies gate the order before it is sent; risk rules watch the position and fire on the unrealized-P&L ratio. Neither takes a Pattern.

Risk the engine computes inside itself, measured against a baseline run of the same strategy. Risk policies are pre-trade gates tested against the position an order would leave you holding — five thousand on the market value of the whole book, a hundred shares on one name, a repeating window of local time in a named zone — while stop-loss and take-profit rules, each in a fixed and a trailing variant, watch the position tick by tick.

Source on GitHub

19 — Fixed bracket

Pattern: three-over-ten crossover → Rule: one bracket — an entry leg plus a fixed stop and a fixed target resting at the venue.

The Pattern is a WTI three-over-ten crossover and one bracket Rule submits the entry leg together with a venue risk specification holding a fixed stop-loss leg and a fixed take-profit leg, both resting at the venue good-till-cancelled. The entry is a 580-lot market order guarded two percent below the fill and three percent above it, and whichever side the market touches first closes the position and cancels its sibling.

Source on GitHub

20 — Trailing bracket

Pattern: fifty-over-two-hundred crossover → Rule: one bracket with a trailing stop and a fixed target.

The fixed bracket with one leg changed: a fifty-over-two-hundred golden cross on AAPL daily bars, protected by a five percent trailing stop and a fixed ten percent target. The kind field of the risk leg selects the behaviour — a fixed stop is priced once off the entry, a trailing stop is re-priced off the best price the position has seen.

Source on GitHub

21 — OCO and amendments

Patterns: timestamps → Rules: cancel, modify and replace on a resting limit order, and one OCO pair on an open position.

Four scenarios, each on its own rig and each fired by a timestamp Pattern so the moment of the action is exact. Three act on a limit entry already resting at the venue — a cancel Rule withdraws it and releases its reservation, a modify Rule shrinks it in place from ten to four, a replace Rule pulls it and posts a fresh one at a different price and size — and the fourth arms a stop and a target on an open position as one pair.

Source on GitHub

Statistics

Reads the statistics back: the blotter of retained fills, the per-period scores, and a model that ranks candidates on them.

22 — Transaction and robot statistics

One crossover robot; the statistics are read back off the account afterwards, not declared in the graph.

One WTI crossover run, read back at two levels. The transaction level is the blotter: one row per retained fill, with symbol, price, quantity, booked profit and loss and side; the duration level cuts the same run into day buckets and scores each one, and the example asks for the parameter count and the bucket count, then saves the scores and loads them back.

Source on GitHub

23 — Candidate selection

Five robots from the grid runner, each scored through ex_post; a booster ranks the score rows and picks one.

Five candidates differing only in their fast lookback are swept with the grid runner, and each builder opens an ex_post object on its own finished account and extracts the score matrix. The feature vector is the last bucket's row, a booster is trained on every candidate but the one held back, and the pick is the highest predicted profit rather than the highest realized one.

Source on GitHub

Everything else

Collects the facilities that surround a running engine: cores, currency, storage, manual booking, bulk controls and the data toolkit.

24 — Core affinity

The same graph twice — once unpinned, once with the core id set on each Input and Pattern.

Every worker in the export surface takes a core identifier as its trailing argument — the account, each execution, each Input and each Pattern — where a non-negative value pins that worker to the named core and -1 leaves the choice to the operating system. One AAPL trend follower runs twice, unpinned and with its two Inputs and two Patterns nailed to two cores, and the two results agree.

Source on GitHub

25 — Multicurrency

Patterns: two timestamps → Rules: one entry and one exit; the only variable is the account's currency.

An account denominated in euro: the currency is the third argument of account construction, and prices, cash, booked profit and loss, the summary and the portfolio mark all inherit it. The strategy is a single round trip driven by two timestamp Patterns, ten units bought at 100 and sold at 110, because the subject is the unit and not the edge; the engine never converts between currencies. Note what this example is: the engine is validated on a single currency, the US dollar — the euro value and cross-currency portfolios are a feature in the process of shipping, so the interface here runs ahead of its cross-currency arithmetic.

Source on GitHub

26 — Storage regimes

The same crossover graph twice; the only variable is the account's storage regime.

The same WTI crossover backtest run twice, with the blotter in memory and with the blotter on disk in the configured data folder. The regime is the second argument of account construction and decides where the statistics live, never what the strategy does, and both runs agree on net profit and trade count.

Source on GitHub

27 — Manual booking

No graph at all — a contract registered straight with the portfolio, and fills booked by hand.

The portfolio without an adapter and without an execution: a contract is registered directly with the portfolio and fills the engine never placed are booked by hand. The plain mode runs the average-cost engine and computes the profit and loss while the caller only reports what traded; the exposure-parameterized mode prices the fill against exposure snapshots the caller supplies and leaves the live position exactly as it was.

Source on GitHub

28 — Bulk actions

Rules: one market entry and one resting limit exit, then the bulk actions addressed by robot label.

One rig — an entry that fills at the market and an exit that rests as a limit far above it — acted on by robot label, so there is always both a position and a resting order. Cancelling the resting orders and flattening the position cleans the desk without stopping the robot; halting plus a cancel keeps the position open; halting plus a market close leaves a flat desk; the composite of halt, cancel and flatten is the kill switch.

Source on GitHub

29 — Timeserie tools

No robot — the CSV reader, the slicing transforms and the writer run as one pipeline.

A CSV of daily Apple closes is read with an explicit date format, separator and header setting, and the index and one named column come back as a timestamp series and a value series. The series is cut to calendar year 2010 by nanosecond bounds taken as midnight UTC, written back out with formatted timestamps, read again, and windowed with head and tail, which hand back a begin-and-length view rather than a copy.

Source on GitHub