Skip to content

C API reference

#include "lrvx/capi/lrvx_capi.h"

All language bindings (Python, Node.js, Codon, embedded JS) call into this header. You can use it directly to integrate lrvx into any language with a C FFI, or embed it in a C/C++ project.

This page is a curated subset

The full surface is 729 functions, 58 handles, 59 structs, 43 callback typedefs, 3 enums across 72 groups. This page covers the commonly used core (roughly 150 functions) with prose. The complete, machine-generated reference — every function signature, in group order — is tools/codegen/golden/lrvx_capi.md, generated from include/lrvx/capi/lrvx_capi_spec.hpp. That file is the reference of record. When this page and the header disagree, the header wins.

Groups with no prose coverage here: Account, Amm Curve, Delta Book, Dex Amount, Execution Algos, Fee Schedule, Feed Clock, Lrvxrun/trace, Funding Schedule, Grid Search, Heatmap, Indicator Graph, Latency Models, Liquidation Engine, Live Queue Position, Logger, Merged Tape Reader, Metrics, Multi-TF Helpers, Order Group, Order Journey Tracer, Pool Tape, Portfolio Risk, Rate Limit, Recorder, Replay, Risk, Storage, Tape Aggregator, Tape Diff, Targets, Trace Attach, Validation, Venue Availability, Venue Stack, Walk Forward.


Opaque handles

All 58 handles are void*. Lifetime is managed by the matching _create / _destroy pair.

typedef void* LrvxStrategyHandle;
typedef void* LrvxRegistryHandle;
typedef void* LrvxBookHandle;
typedef void* LrvxSimulatedExecutorHandle;
typedef void* LrvxPositionTrackerHandle;
typedef void* LrvxPositionGroupHandle;
typedef void* LrvxOrderTrackerHandle;
typedef void* LrvxOrderJourneyTracerHandle;
typedef void* LrvxFootprintHandle;
typedef void* LrvxVolumeProfileHandle;
typedef void* LrvxMarketProfileHandle;
typedef void* LrvxCompositeBookHandle;
typedef void* LrvxCurveHandle;
typedef void* LrvxPoolTapeHandle;
typedef void* LrvxPoolReplayHandle;
typedef void* LrvxIndicatorGraphHandle;
typedef LrvxIndicatorGraphHandle LrvxStreamingGraphHandle;  // alias
typedef void* LrvxOrderGroupHandle;
typedef void* LrvxFeedClockHandle;
typedef void* LrvxL3BookHandle;
typedef void* LrvxDataWriterHandle;
typedef void* LrvxDataReaderHandle;
typedef void* LrvxLatencyDistributionHandle;
typedef void* LrvxRateLimitPolicyHandle;
typedef void* LrvxVenueAvailabilityHandle;
typedef void* LrvxBacktestResultHandle;
typedef void* LrvxMergedTapeReaderHandle;
typedef void* LrvxPartitionerHandle;
typedef void* LrvxRiskManagerHandle;
typedef void* LrvxKillSwitchHandle;
typedef void* LrvxOrderValidatorHandle;
typedef void* LrvxPnLTrackerHandle;
typedef void* LrvxStorageSinkHandle;
typedef void* LrvxMarketDataRecorderHandle;
typedef void* LrvxBinaryLogRecorderHookHandle;
typedef void* LrvxReplaySourceHandle;
typedef void* LrvxExecutionListenerHandle;
typedef void* LrvxExecutorHandle;
typedef void* LrvxLiveEngineHandle;
typedef void* LrvxRunnerHandle;
typedef void* LrvxBacktestRunnerHandle;
typedef void* LrvxGridSearchHandle;
typedef void* LrvxLatencyModelHandle;
typedef void* LrvxTapeDiffHandle;
typedef void* LrvxPortfolioRiskHandle;
typedef void* LrvxExecAlgoHandle;
typedef void* LrvxDeltaBookEncoderHandle;
typedef void* LrvxDeltaBookReplayerHandle;
typedef void* LrvxRunRecorderHandle;
typedef void* LrvxRunReaderHandle;
typedef void* LrvxBarDispatchRecorderHandle;
typedef void* LrvxAggregatorHandle;
typedef void* LrvxFeeScheduleHandle;
typedef void* LrvxFundingScheduleHandle;
typedef void* LrvxLiveQueuePositionHandle;
typedef void* LrvxLiquidationEngineHandle;
typedef void* LrvxAccountHandle;
typedef void* LrvxVenueStackHandle;

Structs

LrvxTradeData

Field Type Description
symbol uint32_t Symbol ID
price_raw int64_t Price × 1e8
quantity_raw int64_t Quantity × 1e8
is_buy uint8_t 1 = buy, 0 = sell
exchange_ts_ns int64_t Exchange timestamp (ns)

LrvxBookLevel

Field Type Description
price_raw int64_t Price × 1e8
quantity_raw int64_t Quantity × 1e8

LrvxBookSnapshot

Field Type Description
bid_price_raw int64_t Best bid price × 1e8; a price only when has_bid is 1, else 0
bid_qty_raw int64_t Size resting at the best bid × 1e8 (0 when the book cannot say)
ask_price_raw int64_t Best ask price × 1e8; a price only when has_ask is 1, else 0
ask_qty_raw int64_t Size resting at the best ask × 1e8 (0 when the book cannot say)
mid_raw int64_t Mid price × 1e8; a price only when both flags are 1, else 0
spread_raw int64_t Spread × 1e8; a price only when both flags are 1, else 0
has_bid uint8_t 1 when the bid side has a best level, at any price, 0 included
has_ask uint8_t 1 when the ask side has a best level, at any price, 0 included

A price field of 0 is not "no quote": a book can be quoted at or below zero (see lrvx_best_bid_raw_opt). Read the flag before the price. The flags arrived with ABI version 4.

LrvxBookData

Field Type Description
symbol uint32_t Symbol ID
exchange_ts_ns int64_t Exchange timestamp (ns)
snapshot LrvxBookSnapshot Top-of-book snapshot

LrvxSymbolContext

Field Type Description
symbol_id uint32_t Symbol ID
position_raw int64_t Position × 1e8
avg_entry_price_raw int64_t Average entry price × 1e8
last_trade_price_raw int64_t Last trade price × 1e8
last_update_ns int64_t Last update timestamp (ns)
book LrvxBookSnapshot Top-of-book snapshot

LrvxBarData

Passed to LrvxOnBarCallback when a bar closes.

Field Type Description
symbol uint32_t Symbol ID
bar_type uint8_t Bar type (Time, Tick, Volume, Range, Renko, Dollar, BpsRange)
close_reason uint8_t Why the bar closed
_pad uint8_t[2] Padding
bar_type_param uint64_t Type parameter. For Time bars this is nanoseconds (1-minute = 60000000000)
open_raw int64_t Open × 1e8
high_raw int64_t High × 1e8
low_raw int64_t Low × 1e8
close_raw int64_t Close × 1e8
volume_raw int64_t Volume × 1e8
buy_volume_raw int64_t Buy-side volume × 1e8
trade_count_raw int64_t Trade count × 1e8
start_time_ns int64_t Bar open time (ns)
end_time_ns int64_t Bar close time (ns)

LrvxBarData is distinct from LrvxBar (below). LrvxBar is the batch-aggregation output row; LrvxBarData is the live strategy callback payload.

LrvxStrategyCallbacks

10 members. Field order is load-bearing for FFI consumers — allocate the full struct (10 pointer-sized slots on a 64-bit target) and zero it before filling. A short allocation corrupts memory when the runtime writes past the end.

Field Type Description
on_trade LrvxOnTradeCallback Trade event callback
on_book LrvxOnBookCallback Book update callback
on_bar LrvxOnBarCallback Closed OHLC bar callback (LrvxBarData)
on_start LrvxOnStartCallback Strategy start callback
on_stop LrvxOnStopCallback Strategy stop callback
on_fill LrvxOnFillCallback Fill callback (LrvxOrderEventData)
on_order_update LrvxOnOrderUpdateCallback Order status change (LrvxOrderEventData)
on_queue_position_change LrvxOnQueuePositionChangeCallback Queue position moved
on_market_position_change LrvxOnMarketPositionChangeCallback Order's position vs best moved
user_data void* Passed to all callbacks

Any member may be NULL; an unset callback is a no-op.

LrvxOrderEventData

Payload for on_fill, on_order_update, on_queue_position_change, on_market_position_change.

Field Type Description
order_id uint64_t Order ID
symbol_id uint32_t Symbol ID
side uint8_t 0 = buy, 1 = sell
order_type uint8_t OrderType encoding — see order_type encodings
status uint8_t OrderEventStatus value
_pad uint8_t Padding
fill_qty_raw int64_t Fill quantity × 1e8
fill_price_raw int64_t Fill price × 1e8
exchange_ts_ns int64_t Exchange timestamp (ns)
reject_reason const char* Reject reason, or NULL. Borrowed; valid only for the callback's duration
queue_ahead_raw int64_t Queue volume ahead × 1e8
queue_total_raw int64_t Total queue volume at the level × 1e8
submitted_at_ns int64_t Submit timestamp (ns)
accepted_at_ns int64_t Accept timestamp (ns)
first_fill_at_ns int64_t First fill timestamp (ns)
last_fill_at_ns int64_t Last fill timestamp (ns)
canceled_at_ns int64_t Cancel timestamp (ns)
rejected_at_ns int64_t Reject timestamp (ns)
triggered_at_ns int64_t Trigger timestamp (ns)
expired_at_ns int64_t Expiry timestamp (ns)
is_maker uint8_t 1 if the fill was passive
market_position uint8_t MarketPosition value
distance_to_best_ticks int32_t Ticks from best price
_pad2 uint8_t[2] Padding

LrvxSignal

Emitted by strategies, received by the order backend.

Field Type Description
order_id uint64_t Order ID
symbol uint32_t Symbol ID
side uint8_t 0 = buy, 1 = sell
order_type uint8_t Encoding depends on the entry point — see order_type encodings
price double Limit price (0 for market orders)
quantity double Order quantity
trigger_price double Stop/take-profit trigger
trailing_offset double Trailing stop absolute offset
trailing_bps int32_t Trailing stop callback rate (basis points)
new_price double Modify: updated price
new_quantity double Modify: updated quantity
range_lower double Provide/withdraw liquidity: lower bound of the range
range_upper double Provide liquidity: upper bound of the range (0 on withdraw)
liquidity double Provide/withdraw liquidity: position size

LrvxBar

Field Type Description
start_time_ns int64_t Bar open time (ns)
end_time_ns int64_t Bar close time (ns)
open_raw int64_t Open × 1e8
high_raw int64_t High × 1e8
low_raw int64_t Low × 1e8
close_raw int64_t Close × 1e8
volume_raw int64_t Volume × 1e8
buy_volume_raw int64_t Buy-side volume × 1e8
trade_count uint32_t Number of trades

LrvxFill

Field Type Description
order_id uint64_t Order ID
symbol uint32_t Symbol ID
side uint8_t 0 = buy, 1 = sell
price_raw int64_t Fill price × 1e8
quantity_raw int64_t Fill quantity × 1e8
timestamp_ns int64_t Fill timestamp (ns)

LrvxBacktestStats

Field Type Description
totalTrades uint64_t Round-trip trade count
winningTrades uint64_t Winning trades
losingTrades uint64_t Losing trades
maxConsecutiveWins uint64_t Max consecutive wins
maxConsecutiveLosses uint64_t Max consecutive losses
initialCapital double Starting capital
finalCapital double Ending capital
totalPnl double Gross PnL
totalFees double Total fees paid
netPnl double Net PnL after fees
grossProfit double Sum of winning trades
grossLoss double Sum of losing trades
maxDrawdown double Max drawdown (absolute)
maxDrawdownPct double Max drawdown (%)
winRate double Winning trade ratio
profitFactor double Gross profit / gross loss
avgWin double Average winning trade
avgLoss double Average losing trade
avgWinLossRatio double avgWin / avgLoss
avgTradeDurationNs double Average trade duration (ns)
medianTradeDurationNs double Median trade duration (ns)
maxTradeDurationNs double Longest trade (ns)
sharpeRatio double Annualized Sharpe ratio
sortinoRatio double Sortino ratio
calmarRatio double Calmar ratio
timeWeightedReturn double Time-weighted return
returnPct double Net return (%)
startTimeNs int64_t Backtest start timestamp (ns)
endTimeNs int64_t Backtest end timestamp (ns)

LrvxEquityPoint

Field Type Description
timestamp_ns int64_t Timestamp (ns)
equity double Equity at this point
drawdown_pct double Drawdown (%) at this point

order_type encodings

There are two different uint8_t order-type encodings in this API. They disagree on the two most common values. Which one applies depends on the entry point, not on the struct.

Encoding A — SignalType (0 = market, 1 = limit)

Value Meaning
0 market
1 limit
2 stop_market
3 stop_limit
4 tp_market
5 tp_limit
6 trailing_stop
7 cancel
8 cancel_all
9 modify

Encoding B — C++ lrvx::OrderType (0 = LIMIT, 1 = MARKET)

Value Meaning
0 LIMIT
1 MARKET
2 STOP_MARKET
3 STOP_LIMIT
4 TAKE_PROFIT_MARKET
5 TAKE_PROFIT_LIMIT
6 TRAILING_STOP
7 ICEBERG

Values 2–6 coincide; 0, 1, 7 and above do not. Which entry point uses which:

Entry point Field Encoding Code path
LrvxOnSignalCallback from the runner / live engine LrvxSignal.order_type A (SignalType) src/capi/lrvx_capi.cpp — explicit switch (sig.type)
LrvxRiskManagerAllowFn LrvxSignal.order_type A (SignalType) orderToLrvxSignal() — signalTypeCodeFromOrderType(order.type)
LrvxKillSwitchCheckFn LrvxSignal.order_type A (SignalType) orderToLrvxSignal() — signalTypeCodeFromOrderType(order.type)
LrvxOrderValidatorValidateFn LrvxSignal.order_type A (SignalType) orderToLrvxSignal() — signalTypeCodeFromOrderType(order.type)
LrvxPnLTrackerOnSignalFn LrvxSignal.order_type A (SignalType) orderToLrvxSignal() — signalTypeCodeFromOrderType(order.type)
lrvx_simulated_executor_submit_order order_type argument B (OrderType) static_cast<OrderType>(order_type)
lrvx_simulated_executor_submit_order_ex order_type argument B (OrderType) static_cast<OrderType>(order_type)
LrvxOrderEventData.order_type struct field B (OrderType) carried from Order::type

The four pre-trade gate rows (risk manager, kill switch, order validator, PnL tracker) used to hand the gate a raw static_cast<uint8_t>(order.type), which is Encoding B, even though the field is LrvxSignal.order_type and every other producer on this page fills it with Encoding A. orderToLrvxSignal() now converts explicitly through signalTypeCodeFromOrderType() (see src/capi/lrvx_capi.cpp), so all four gates receive the same encoding as LrvxOnSignalCallback. A gate written against the old table would have read every LIMIT order it received as MARKET, and vice versa.

Consequence: passing 0 to lrvx_simulated_executor_submit_order submits a LIMIT order, not a market order. Pass 1 for market. The embedded QuickJS binding compensates for this mismatch by remapping in src/quickjs/js_strategy.cpp before it calls through; bindings you write yourself must do the same.


Callback types

The header declares 43 callback typedefs. The strategy, gate and progress callbacks are below; the listener, executor, recorder and replay-source function pointers are in the generated reference.

Strategy callbacks — the members of LrvxStrategyCallbacks:

typedef void (*LrvxOnTradeCallback)(void* user_data, const LrvxSymbolContext* ctx,
                                    const LrvxTradeData* trade);
typedef void (*LrvxOnBookCallback)(void* user_data, const LrvxSymbolContext* ctx,
                                   const LrvxBookData* book);
typedef void (*LrvxOnBarCallback)(void* user_data, const LrvxSymbolContext* ctx,
                                  const LrvxBarData* bar);
typedef void (*LrvxOnStartCallback)(void* user_data);
typedef void (*LrvxOnStopCallback)(void* user_data);
typedef void (*LrvxOnFillCallback)(void* user_data, const LrvxSymbolContext* ctx,
                                   const LrvxOrderEventData* ev);
typedef void (*LrvxOnOrderUpdateCallback)(void* user_data, const LrvxSymbolContext* ctx,
                                          const LrvxOrderEventData* ev);
typedef void (*LrvxOnQueuePositionChangeCallback)(void* user_data, const LrvxSymbolContext* ctx,
                                                  const LrvxOrderEventData* ev);
typedef void (*LrvxOnMarketPositionChangeCallback)(void* user_data, const LrvxSymbolContext* ctx,
                                                   const LrvxOrderEventData* ev);

Signal sink and pre-trade gates. The gates run in order KillSwitch, OrderValidator, RiskManager; returning 0 drops the signal and skips the remaining gates. Note the LrvxSignal.order_type in a gate callback uses encoding B, not the runner's encoding A:

typedef void    (*LrvxOnSignalCallback)(void* user_data, const LrvxSignal* signal);
typedef uint8_t (*LrvxRiskManagerAllowFn)(void* user_data, const LrvxSignal* signal);
typedef uint8_t (*LrvxKillSwitchCheckFn)(void* user_data, const LrvxSignal* signal);
typedef uint8_t (*LrvxOrderValidatorValidateFn)(void* user_data, const LrvxSignal* signal);
typedef void    (*LrvxPnLTrackerOnSignalFn)(void* user_data, const LrvxSignal* signal);
typedef void    (*LrvxStorageSinkStoreFn)(void* user_data, const LrvxSignal* signal);

Logging and long-running-operation progress. LrvxProgressCallback returns 0 to request cancellation:

typedef void    (*LrvxLogCallback)(void* user_data, int32_t level, const char* message);
typedef uint8_t (*LrvxProgressCallback)(void* user_data, double fraction, int64_t items_done);

Symbol registry

LrvxRegistryHandle lrvx_registry_create(void);
void               lrvx_registry_destroy(LrvxRegistryHandle registry);

uint32_t lrvx_registry_add_symbol(LrvxRegistryHandle registry,
                                  const char* exchange, const char* name,
                                  double tick_size);

uint8_t  lrvx_registry_get_symbol_id(LrvxRegistryHandle registry,
                                     const char* exchange, const char* name,
                                     uint32_t* id_out);
uint8_t  lrvx_registry_get_symbol_name(LrvxRegistryHandle registry,
                                       uint32_t symbol_id,
                                       char* exchange_out, size_t exchange_len,
                                       char* name_out, size_t name_len);
uint32_t lrvx_registry_symbol_count(LrvxRegistryHandle registry);

Strategy

LrvxStrategyHandle lrvx_strategy_create(uint32_t id,
                                        const uint32_t* symbols, uint32_t num_symbols,
                                        LrvxRegistryHandle registry,
                                        LrvxStrategyCallbacks callbacks);
void lrvx_strategy_destroy(LrvxStrategyHandle strategy);

StrategyRunner

Synchronous strategy host. Strategy callbacks fire in the caller's thread before the push call returns.

LrvxRunnerHandle lrvx_runner_create(LrvxRegistryHandle registry,
                                    LrvxOnSignalCallback on_signal,
                                    void* user_data);
void lrvx_runner_destroy(LrvxRunnerHandle runner);

void lrvx_runner_add_strategy(LrvxRunnerHandle runner, LrvxStrategyHandle strategy);
void lrvx_runner_start(LrvxRunnerHandle runner);
void lrvx_runner_stop(LrvxRunnerHandle runner);

void lrvx_runner_on_trade(LrvxRunnerHandle runner, uint32_t symbol,
                          double price, double qty, uint8_t is_buy,
                          int64_t exchange_ts_ns);
void lrvx_runner_on_book_snapshot(LrvxRunnerHandle runner, uint32_t symbol,
                                  const double* bid_prices, const double* bid_qtys,
                                  uint32_t n_bids,
                                  const double* ask_prices, const double* ask_qtys,
                                  uint32_t n_asks, int64_t exchange_ts_ns);

LiveEngine

Disruptor-based live trading engine. Each strategy runs in its own consumer thread. Publish calls are lock-free and return immediately.

LrvxLiveEngineHandle lrvx_live_engine_create(LrvxRegistryHandle registry);
void                 lrvx_live_engine_destroy(LrvxLiveEngineHandle engine);

void lrvx_live_engine_add_strategy(LrvxLiveEngineHandle engine,
                                   LrvxStrategyHandle strategy,
                                   LrvxOnSignalCallback on_signal,
                                   void* user_data);

void lrvx_live_engine_start(LrvxLiveEngineHandle engine);
void lrvx_live_engine_stop(LrvxLiveEngineHandle engine);

void lrvx_live_engine_publish_trade(LrvxLiveEngineHandle engine,
                                    uint32_t symbol,
                                    double price, double qty, uint8_t is_buy,
                                    int64_t exchange_ts_ns);
void lrvx_live_engine_publish_book_snapshot(LrvxLiveEngineHandle engine,
                                            uint32_t symbol,
                                            const double* bid_prices,
                                            const double* bid_qtys, uint32_t n_bids,
                                            const double* ask_prices,
                                            const double* ask_qtys, uint32_t n_asks,
                                            int64_t exchange_ts_ns);

BacktestRunner

Replays OHLCV data through a strategy and returns statistics.

LrvxBacktestRunnerHandle lrvx_backtest_runner_create(LrvxRegistryHandle registry,
                                                     double fee_rate,
                                                     double initial_capital);
void lrvx_backtest_runner_destroy(LrvxBacktestRunnerHandle runner);

void lrvx_backtest_runner_set_strategy(LrvxBacktestRunnerHandle runner,
                                       LrvxStrategyHandle strategy);

// Replay a CSV file (columns: timestamp, open, high, low, close, volume).
// Returns 1 on success, 0 on error.
int lrvx_backtest_runner_run_csv(LrvxBacktestRunnerHandle runner,
                                 const char* path, const char* symbol,
                                 LrvxBacktestStats* stats_out);

// Replay raw OHLCV arrays (timestamps in nanoseconds).
// Returns 1 on success, 0 on error.
int lrvx_backtest_runner_run_ohlcv(LrvxBacktestRunnerHandle runner,
                                   const int64_t* timestamps_ns,
                                   const double* close_prices, uint32_t n,
                                   const char* symbol,
                                   LrvxBacktestStats* stats_out);

Signal emission

All return OrderId (uint64_t), 0 on failure. cancel and modify return void.

Function Description
lrvx_emit_market_buy(s, sym, qty_raw) Market buy
lrvx_emit_market_sell(s, sym, qty_raw) Market sell
lrvx_emit_limit_buy(s, sym, px_raw, qty_raw) Limit buy
lrvx_emit_limit_sell(s, sym, px_raw, qty_raw) Limit sell
lrvx_emit_limit_buy_tif(s, sym, px_raw, qty_raw, tif) Limit buy with time-in-force
lrvx_emit_limit_sell_tif(s, sym, px_raw, qty_raw, tif) Limit sell with time-in-force
lrvx_emit_stop_market(s, sym, side, trigger_raw, qty_raw) Stop market
lrvx_emit_stop_limit(s, sym, side, trigger_raw, limit_raw, qty_raw) Stop limit
lrvx_emit_take_profit_market(s, sym, side, trigger_raw, qty_raw) Take-profit market
lrvx_emit_take_profit_limit(s, sym, side, trigger_raw, limit_raw, qty_raw) Take-profit limit
lrvx_emit_trailing_stop(s, sym, side, offset_raw, qty_raw) Trailing stop (absolute)
lrvx_emit_trailing_stop_percent(s, sym, side, bps, qty_raw) Trailing stop (basis points)
lrvx_emit_close_position(s, sym) Close position (reduce-only)
lrvx_emit_cancel(s, order_id) Cancel order
lrvx_emit_cancel_all(s, sym) Cancel all orders for symbol
lrvx_emit_modify(s, order_id, new_price_raw, new_qty_raw) Modify order

Context queries

Function Returns Description
lrvx_position_raw(s, sym) int64_t Position × 1e8
lrvx_last_trade_price_raw(s, sym) int64_t Last trade price × 1e8
lrvx_best_bid_raw(s, sym) int64_t Best bid × 1e8, 0 if none
lrvx_best_ask_raw(s, sym) int64_t Best ask × 1e8, 0 if none
lrvx_mid_price_raw(s, sym) int64_t Mid price × 1e8, 0 if none
lrvx_best_bid_raw_opt(s, sym, price_out) uint8_t 1 with the raw bid in price_out, 0 if none
lrvx_best_ask_raw_opt(s, sym, price_out) uint8_t 1 with the raw ask in price_out, 0 if none
lrvx_mid_price_raw_opt(s, sym, price_out) uint8_t 1 with the raw mid in price_out, 0 if none
lrvx_get_symbol_context(s, sym, out) void Fill LrvxSymbolContext
lrvx_get_order_status(s, order_id) int32_t Order status (-1 = not found)

No quote, and prices at or below zero

A price below zero is a quote: WTI settled at -37.63 in April 2020, day-ahead power clears below zero on a windy afternoon, and a calendar spread is negative in contango. A price of exactly 0.0 is a quote too. The book reports such a book the same way it reports any other, so a return value cannot double as a "no quote" marker.

The three int64_t accessors return 0 for an empty side and for a best quote of 0.0 alike; they are unchanged, for callers whose markets never reach zero. The _opt trio puts the answer in the return value instead -- 1 with the raw price written to price_out, 0 with price_out untouched -- so the two cases are distinct. price_out may be NULL when only the flag is wanted. A header carrying them defines LRVX_HAS_OPTIONAL_RAW_BEST_QUOTE, so a binding can compile against either.

LrvxSymbolContext.book has the same limitation as the int64_t accessors: bid_price_raw, ask_price_raw, mid_raw and spread_raw are 0 when the side is empty. Read the _opt accessors where that matters.

The book handle accessors -- lrvx_book_best_bid, lrvx_book_best_ask, lrvx_book_mid, lrvx_book_spread -- already return a presence flag with the price in an out parameter and need no variant; they report a negative best quote like any other.


Simulated executor

Used in backtesting to fill orders from simulated market data.

LrvxSimulatedExecutorHandle lrvx_simulated_executor_create(void);
void               lrvx_simulated_executor_destroy(LrvxSimulatedExecutorHandle executor);

void lrvx_simulated_executor_submit_order(LrvxSimulatedExecutorHandle executor,
                                uint64_t id, uint8_t side, double price,
                                double quantity, uint8_t order_type, uint32_t symbol);
void lrvx_simulated_executor_cancel_order(LrvxSimulatedExecutorHandle executor, uint64_t order_id);
void lrvx_simulated_executor_cancel_all(LrvxSimulatedExecutorHandle executor, uint32_t symbol);

// Feed market data
void lrvx_simulated_executor_on_bar(LrvxSimulatedExecutorHandle executor, uint32_t symbol, double close_price);
void lrvx_simulated_executor_on_trade(LrvxSimulatedExecutorHandle executor, uint32_t symbol,
                            double price, uint8_t is_buy);
void lrvx_simulated_executor_on_trade_qty(LrvxSimulatedExecutorHandle executor, uint32_t symbol,
                                double price, double quantity, uint8_t is_buy);
void lrvx_simulated_executor_on_best_levels(LrvxSimulatedExecutorHandle executor, uint32_t symbol,
                                  double bid_price, double bid_qty,
                                  double ask_price, double ask_qty);
void lrvx_simulated_executor_on_book_snapshot(LrvxSimulatedExecutorHandle executor, uint32_t symbol,
                                    const double* bid_prices, const double* bid_qtys,
                                    uint32_t n_bids,
                                    const double* ask_prices, const double* ask_qtys,
                                    uint32_t n_asks);
void lrvx_simulated_executor_advance_clock(LrvxSimulatedExecutorHandle executor, int64_t timestamp_ns);

// Fills
uint32_t lrvx_simulated_executor_fill_count(LrvxSimulatedExecutorHandle executor);
uint32_t lrvx_simulated_executor_get_fills(LrvxSimulatedExecutorHandle executor,
                                 LrvxFill* fills_out, uint32_t max_fills);

Slippage configuration

typedef enum {
    LRVX_SLIPPAGE_NONE         = 0,
    LRVX_SLIPPAGE_FIXED_TICKS  = 1,
    LRVX_SLIPPAGE_FIXED_BPS    = 2,
    LRVX_SLIPPAGE_VOLUME_IMPACT = 3
} LrvxSlippageModel;

void lrvx_simulated_executor_set_default_slippage(LrvxSimulatedExecutorHandle executor,
                                        int32_t model, int32_t ticks,
                                        double tick_size, double bps,
                                        double impact_coeff);
void lrvx_simulated_executor_set_symbol_slippage(LrvxSimulatedExecutorHandle executor, uint32_t symbol,
                                       int32_t model, int32_t ticks,
                                       double tick_size, double bps,
                                       double impact_coeff);

Queue simulation

typedef enum {
    LRVX_QUEUE_NONE                = 0,
    LRVX_QUEUE_TOB                 = 1,
    LRVX_QUEUE_FULL                = 2,
    LRVX_QUEUE_PRO_RATA            = 3,
    LRVX_QUEUE_PRO_RATA_WITH_FIFO  = 4
} LrvxQueueModel;

void lrvx_simulated_executor_set_queue_model(LrvxSimulatedExecutorHandle executor,
                                   int32_t model, uint32_t depth);

The C++ QueueModel enum has two further values (TOP_PRO_LMM, PRO_RATA_WITH_PRIORITY) with no C-API constant; see queue simulation.

Aggregator event filter

typedef enum {
    LRVX_AGG_FILTER_TRADES     = 1,
    LRVX_AGG_FILTER_BOOKS_ONLY = 2,
    LRVX_AGG_FILTER_BOTH       = 3
} LrvxAggregatorEventFilter;

Selects which tape events feed a LrvxAggregatorHandle. These three enums (LrvxSlippageModel, LrvxQueueModel, LrvxAggregatorEventFilter) are the only C enums in the header; every other discrete value crosses the boundary as a bare uint8_t or int32_t.


BacktestResult

Aggregates fills into trades, statistics, and equity curve.

LrvxBacktestResultHandle lrvx_backtest_result_create(double initial_capital,
                                                     double fee_rate,
                                                     uint8_t use_percentage_fee,
                                                     double fixed_fee_per_trade,
                                                     double risk_free_rate,
                                                     double annualization_factor);
void lrvx_backtest_result_destroy(LrvxBacktestResultHandle result);

void lrvx_backtest_result_record_fill(LrvxBacktestResultHandle result,
                                      uint64_t order_id, uint32_t symbol, uint8_t side,
                                      double price, double quantity, int64_t timestamp_ns);
void lrvx_backtest_result_ingest_executor(LrvxBacktestResultHandle result,
                                          LrvxSimulatedExecutorHandle executor);

void     lrvx_backtest_result_stats(LrvxBacktestResultHandle result, LrvxBacktestStats* out);
uint32_t lrvx_backtest_result_equity_curve(LrvxBacktestResultHandle result,
                                           LrvxEquityPoint* points_out, uint32_t max_points);
uint8_t  lrvx_backtest_result_write_equity_curve_csv(LrvxBacktestResultHandle result,
                                                     const char* path);

Indicators

Stateless, array-in / array-out.

Function Description
lrvx_indicator_ema(input, len, period, output) EMA
lrvx_indicator_sma(input, len, period, output) SMA
lrvx_indicator_rsi(input, len, period, output) RSI
lrvx_indicator_rma(input, len, period, output) Wilder's moving average
lrvx_indicator_dema(input, len, period, output) Double EMA
lrvx_indicator_tema(input, len, period, output) Triple EMA
lrvx_indicator_kama(input, len, period, fast, slow, output) Kaufman adaptive MA
lrvx_indicator_slope(input, len, length, output) Linear slope
lrvx_indicator_atr(high, low, close, len, period, output) ATR
lrvx_indicator_adx(high, low, close, len, period, adx, +di, -di) ADX
lrvx_indicator_macd(input, len, fast, slow, signal, macd, signal, hist) MACD
lrvx_indicator_bollinger(input, len, period, mult, upper, middle, lower) Bollinger Bands
lrvx_indicator_cci(high, low, close, len, period, output) CCI
lrvx_indicator_stochastic(high, low, close, len, k, d, k_out, d_out) Stochastic
lrvx_indicator_chop(high, low, close, len, period, output) Choppiness
lrvx_indicator_obv(close, volume, len, output) On-balance volume
lrvx_indicator_vwap(close, volume, len, window, output) Rolling VWAP
lrvx_indicator_cvd(open, high, low, close, volume, len, output) Cumulative volume delta
lrvx_indicator_skewness(input, len, period, output) Rolling skewness
lrvx_indicator_kurtosis(input, len, period, output) Rolling kurtosis
lrvx_indicator_parkinson_vol(high, low, len, period, output) Parkinson volatility
lrvx_indicator_rogers_satchell_vol(open, high, low, close, len, period, output) Rogers-Satchell volatility
lrvx_indicator_rolling_zscore(input, len, period, output) Rolling z-score
lrvx_indicator_shannon_entropy(input, len, period, bins, output) Shannon entropy
lrvx_indicator_correlation(x, y, len, period, output) Rolling correlation
lrvx_indicator_adf(input, len, max_lag, regression, test_stat_out, p_value_out, used_lag_out) Augmented Dickey-Fuller test
lrvx_indicator_autocorrelation(input, len, window, lag, output) Rolling autocorrelation

That is all 27 functions in the indicator_functions group. lrvx_indicator_adf is the only one that is not array-in / array-out: it writes three scalars through out-pointers and takes a const char* regression selector. The lrvx_indicator_graph_* functions are a separate group and are not listed here.

Streaming (stateful) indicator objects are not part of the C API; they are exposed by the Codon, QuickJS and Node bindings.


Bar aggregation

All functions return the total number of bars the input produced, and write as many of them as fit into bars_out (capacity max). Time, Tick, Volume, Range, and Heikin-Ashi close at most one bar per input trade, so sizing bars_out to len is always enough for them. Renko is the exception: a single trade that gaps past more than one brick width closes the brick that was forming and also synthesizes the bricks in between (see bar types), so it can return more bars than there were input trades. If the return value is greater than max, only the first max bars were written -- call again with a buffer sized to the return value to get the rest.

Function Description
lrvx_aggregate_time_bars(..., interval_seconds, bars_out, max) Time bars
lrvx_aggregate_tick_bars(..., tick_count, bars_out, max) Tick bars
lrvx_aggregate_volume_bars(..., volume_threshold, bars_out, max) Volume bars
lrvx_aggregate_range_bars(..., range_size, bars_out, max) Range bars
lrvx_aggregate_renko_bars(..., brick_size, bars_out, max) Renko bars
lrvx_aggregate_heikin_ashi_bars(..., interval_seconds, bars_out, max) Heikin-Ashi

All take the same input signature: (timestamps, prices, quantities, is_buy, len, ...).


L2 Order book

LrvxBookHandle lrvx_book_create(double tick_size);
void           lrvx_book_destroy(LrvxBookHandle book);

void    lrvx_book_apply_snapshot(LrvxBookHandle book,
                                 const double* bid_prices, const double* bid_qtys, size_t bid_len,
                                 const double* ask_prices, const double* ask_qtys, size_t ask_len);
void    lrvx_book_apply_delta(LrvxBookHandle book,
                              const double* bid_prices, const double* bid_qtys, size_t bid_len,
                              const double* ask_prices, const double* ask_qtys, size_t ask_len);

uint8_t lrvx_book_best_bid(LrvxBookHandle book, double* price_out);
uint8_t lrvx_book_best_ask(LrvxBookHandle book, double* price_out);
uint8_t lrvx_book_mid(LrvxBookHandle book, double* price_out);
uint8_t lrvx_book_spread(LrvxBookHandle book, double* spread_out);
double  lrvx_book_bid_at_price(LrvxBookHandle book, double price);
double  lrvx_book_ask_at_price(LrvxBookHandle book, double price);
uint8_t lrvx_book_is_crossed(LrvxBookHandle book);
void    lrvx_book_clear(LrvxBookHandle book);

uint32_t lrvx_book_get_bids(LrvxBookHandle book, double* prices_out,
                            double* qtys_out, uint32_t max_levels);
uint32_t lrvx_book_get_asks(LrvxBookHandle book, double* prices_out,
                            double* qtys_out, uint32_t max_levels);

L3 Order book

LrvxL3BookHandle lrvx_l3_book_create(void);
void             lrvx_l3_book_destroy(LrvxL3BookHandle book);

int32_t lrvx_l3_book_add_order(LrvxL3BookHandle book,
                               uint64_t order_id, double price,
                               double quantity, uint8_t side);
int32_t lrvx_l3_book_remove_order(LrvxL3BookHandle book, uint64_t order_id);
int32_t lrvx_l3_book_modify_order(LrvxL3BookHandle book,
                                  uint64_t order_id, double new_qty);

uint8_t lrvx_l3_book_best_bid(LrvxL3BookHandle book, double* price_out);
uint8_t lrvx_l3_book_best_ask(LrvxL3BookHandle book, double* price_out);
double  lrvx_l3_book_bid_at_price(LrvxL3BookHandle book, double price);
double  lrvx_l3_book_ask_at_price(LrvxL3BookHandle book, double price);

Composite book

Aggregates books across multiple exchanges per symbol.

LrvxCompositeBookHandle lrvx_composite_book_create(void);
void                    lrvx_composite_book_destroy(LrvxCompositeBookHandle book);

uint8_t lrvx_composite_book_best_bid(LrvxCompositeBookHandle book, uint32_t symbol,
                                     double* price_out, double* qty_out);
uint8_t lrvx_composite_book_best_ask(LrvxCompositeBookHandle book, uint32_t symbol,
                                     double* price_out, double* qty_out);
uint8_t lrvx_composite_book_has_arb(LrvxCompositeBookHandle book, uint32_t symbol);
void    lrvx_composite_book_mark_stale(LrvxCompositeBookHandle book,
                                       uint32_t exchange, uint32_t symbol);
void    lrvx_composite_book_check_staleness(LrvxCompositeBookHandle book,
                                            int64_t now_ns, int64_t threshold_ns);

Position tracker

FIFO/average cost position tracking.

LrvxPositionTrackerHandle lrvx_position_tracker_create(uint8_t cost_basis); // 0 = FIFO
void                      lrvx_position_tracker_destroy(LrvxPositionTrackerHandle tracker);

void   lrvx_position_tracker_on_fill(LrvxPositionTrackerHandle tracker,
                                     uint32_t symbol, uint8_t side,
                                     double price, double quantity);
double lrvx_position_tracker_position(LrvxPositionTrackerHandle tracker, uint32_t symbol);
double lrvx_position_tracker_avg_entry(LrvxPositionTrackerHandle tracker, uint32_t symbol);
double lrvx_position_tracker_realized_pnl(LrvxPositionTrackerHandle tracker, uint32_t symbol);
double lrvx_position_tracker_total_pnl(LrvxPositionTrackerHandle tracker);

Position group

Tracks individual named positions (open/partial-close/close).

LrvxPositionGroupHandle lrvx_position_group_create(void);
void                    lrvx_position_group_destroy(LrvxPositionGroupHandle tracker);

uint64_t lrvx_position_group_open(LrvxPositionGroupHandle tracker,
                                  uint64_t order_id, uint32_t symbol,
                                  uint8_t side, double price, double qty);
void     lrvx_position_group_close(LrvxPositionGroupHandle tracker,
                                   uint64_t position_id, double exit_price);
void     lrvx_position_group_partial_close(LrvxPositionGroupHandle tracker,
                                           uint64_t position_id,
                                           double qty, double exit_price);

double   lrvx_position_group_net_position(LrvxPositionGroupHandle tracker, uint32_t symbol);
double   lrvx_position_group_realized_pnl(LrvxPositionGroupHandle tracker, uint32_t symbol);
double   lrvx_position_group_total_pnl(LrvxPositionGroupHandle tracker);
uint32_t lrvx_position_group_open_count(LrvxPositionGroupHandle tracker, uint32_t symbol);
void     lrvx_position_group_prune(LrvxPositionGroupHandle tracker);

Order tracker

Tracks submitted/filled/canceled orders.

LrvxOrderTrackerHandle lrvx_order_tracker_create(void);
void                   lrvx_order_tracker_destroy(LrvxOrderTrackerHandle tracker);

uint8_t  lrvx_order_tracker_on_submitted(LrvxOrderTrackerHandle tracker,
                                         uint64_t order_id, uint32_t symbol,
                                         uint8_t side, double price, double qty);
uint8_t  lrvx_order_tracker_on_filled(LrvxOrderTrackerHandle tracker,
                                      uint64_t order_id, double fill_qty);
uint8_t  lrvx_order_tracker_on_canceled(LrvxOrderTrackerHandle tracker, uint64_t order_id);
uint8_t  lrvx_order_tracker_is_active(LrvxOrderTrackerHandle tracker, uint64_t order_id);
uint32_t lrvx_order_tracker_active_count(LrvxOrderTrackerHandle tracker);
uint32_t lrvx_order_tracker_total_count(LrvxOrderTrackerHandle tracker);
void     lrvx_order_tracker_prune(LrvxOrderTrackerHandle tracker);

Volume profile

LrvxVolumeProfileHandle lrvx_volume_profile_create(double tick_size);
void                    lrvx_volume_profile_destroy(LrvxVolumeProfileHandle profile);

void     lrvx_volume_profile_add_trade(LrvxVolumeProfileHandle profile,
                                       double price, double quantity, uint8_t is_buy);
double   lrvx_volume_profile_poc(LrvxVolumeProfileHandle profile);
double   lrvx_volume_profile_vah(LrvxVolumeProfileHandle profile);
double   lrvx_volume_profile_val(LrvxVolumeProfileHandle profile);
double   lrvx_volume_profile_total_volume(LrvxVolumeProfileHandle profile);
double   lrvx_volume_profile_total_delta(LrvxVolumeProfileHandle profile);
uint32_t lrvx_volume_profile_num_levels(LrvxVolumeProfileHandle profile);
void     lrvx_volume_profile_clear(LrvxVolumeProfileHandle profile);

Market profile

Tracks TPO-style market profile with initial balance.

LrvxMarketProfileHandle lrvx_market_profile_create(double tick_size,
                                                   uint32_t period_minutes,
                                                   int64_t session_start_ns);
void lrvx_market_profile_destroy(LrvxMarketProfileHandle profile);

void     lrvx_market_profile_add_trade(LrvxMarketProfileHandle profile,
                                       int64_t timestamp_ns, double price,
                                       double qty, uint8_t is_buy);
double   lrvx_market_profile_poc(LrvxMarketProfileHandle profile);
double   lrvx_market_profile_vah(LrvxMarketProfileHandle profile);
double   lrvx_market_profile_val(LrvxMarketProfileHandle profile);
double   lrvx_market_profile_ib_high(LrvxMarketProfileHandle profile);
double   lrvx_market_profile_ib_low(LrvxMarketProfileHandle profile);
uint8_t  lrvx_market_profile_is_poor_high(LrvxMarketProfileHandle profile);
uint8_t  lrvx_market_profile_is_poor_low(LrvxMarketProfileHandle profile);
uint32_t lrvx_market_profile_num_levels(LrvxMarketProfileHandle profile);
void     lrvx_market_profile_clear(LrvxMarketProfileHandle profile);

Footprint

Per-price buy/sell delta at bar resolution.

LrvxFootprintHandle lrvx_footprint_create(double tick_size);
void                lrvx_footprint_destroy(LrvxFootprintHandle footprint);

void     lrvx_footprint_add_trade(LrvxFootprintHandle footprint,
                                  double price, double quantity, uint8_t is_buy);
double   lrvx_footprint_total_delta(LrvxFootprintHandle footprint);
double   lrvx_footprint_total_volume(LrvxFootprintHandle footprint);
uint32_t lrvx_footprint_num_levels(LrvxFootprintHandle footprint);
void     lrvx_footprint_clear(LrvxFootprintHandle footprint);

Statistics

Function Returns Description
lrvx_stat_correlation(x, y, len) double Pearson correlation
lrvx_stat_profit_factor(pnl, len) double Gross profit / gross loss
lrvx_stat_win_rate(pnl, len) double Winning trade ratio
lrvx_stat_permutation_test(g1, l1, g2, l2, n) double Two-sample permutation p-value
lrvx_stat_bootstrap_ci(data, len, conf, n, &lo, &med, &hi) void Bootstrap confidence interval

Data writer

Writes trades and book updates to binary log segments.

LrvxDataWriterHandle lrvx_data_writer_create(const char* output_dir,
                                             uint64_t max_segment_mb,
                                             uint8_t exchange_id);
void lrvx_data_writer_destroy(LrvxDataWriterHandle writer);

uint8_t lrvx_data_writer_write_trade(LrvxDataWriterHandle writer,
                                     int64_t exchange_ts_ns, int64_t recv_ts_ns,
                                     double price, double qty,
                                     uint64_t trade_id, uint32_t symbol_id, uint8_t side);

// Raw int64 book levels (scale 1e8). bids/asks may be NULL when the
// matching count is 0. Returns 1 on success, 0 on failure.
uint8_t lrvx_data_writer_write_book(LrvxDataWriterHandle writer,
                                    int64_t exchange_ts_ns, int64_t recv_ts_ns,
                                    int64_t seq, uint32_t symbol_id,
                                    uint8_t is_snapshot,
                                    const LrvxBookLevel* bids, uint32_t n_bids,
                                    const LrvxBookLevel* asks, uint32_t n_asks);

// Batched book writer. headers + flat levels array, sliced per event
// via header.level_offset / bid_count / ask_count. Same struct layout
// as lrvx_data_reader_read_book_updates — round-trip works.
uint64_t lrvx_data_writer_write_books(LrvxDataWriterHandle writer,
                                      const LrvxBookUpdateHeader* headers,
                                      uint64_t n_events,
                                      const LrvxLevel* levels,
                                      uint64_t total_levels);

void lrvx_data_writer_flush(LrvxDataWriterHandle writer);
void lrvx_data_writer_close(LrvxDataWriterHandle writer);
void lrvx_data_writer_stats_p(LrvxDataWriterHandle writer, void* out); // → LrvxWriterStats

Data reader

Reads binary log segments.

LrvxDataReaderHandle lrvx_data_reader_create(const char* data_dir);
LrvxDataReaderHandle lrvx_data_reader_create_filtered(const char* data_dir,
                                                       int64_t from_ns, int64_t to_ns,
                                                       const uint32_t* symbols,
                                                       uint32_t num_symbols);
void lrvx_data_reader_destroy(LrvxDataReaderHandle reader);

uint64_t lrvx_data_reader_count(LrvxDataReaderHandle reader);
void     lrvx_data_reader_summary_p(LrvxDataReaderHandle reader, void* out); // → LrvxDatasetSummary
void     lrvx_data_reader_stats_p(LrvxDataReaderHandle reader, void* out);   // → LrvxReaderStats

// Returns number of trades read. If trades_out is NULL, counts only.
uint64_t lrvx_data_reader_read_trades(LrvxDataReaderHandle reader,
                                      LrvxTradeRecord* trades_out, uint64_t max_trades);

// Top-of-book per book update event. If bbos_out is NULL, counts only.
uint64_t lrvx_data_reader_read_bbo(LrvxDataReaderHandle reader,
                                   LrvxBBO* bbos_out, uint64_t max_events);

// Counts events and total levels in one pass. *total_levels_out may be NULL.
uint64_t lrvx_data_reader_count_book_updates(LrvxDataReaderHandle reader,
                                             uint64_t* total_levels_out);

// Reads book updates into pre-sized headers and a single flat levels array.
// Caller sizes both via lrvx_data_reader_count_book_updates() first.
// Each header carries level_offset, bid_count, ask_count for slicing the
// levels array. Bids are written before asks for each event.
uint64_t lrvx_data_reader_read_book_updates(LrvxDataReaderHandle reader,
                                            LrvxBookUpdateHeader* headers_out,
                                            uint64_t max_events,
                                            LrvxLevel* levels_out,
                                            uint64_t max_levels);

LrvxTradeRecord fields: exchange_ts_ns, recv_ts_ns, price_raw, qty_raw, trade_id, symbol_id, side.

LrvxBBO fields (size: 64 B): exchange_ts_ns, recv_ts_ns, seq, bid_price_raw, bid_qty_raw, ask_price_raw, ask_qty_raw, symbol_id, event_type (2=snapshot, 3=delta).

LrvxBookUpdateHeader fields (size: 48 B): exchange_ts_ns, recv_ts_ns, seq, level_offset, symbol_id, bid_count, ask_count, event_type.

LrvxLevel fields (size: 24 B): price_raw, qty_raw, side (0=bid, 1=ask).

Layout sizes are pinned with static_assert; language bindings (Codon, QuickJS) parse these structs from raw byte buffers and depend on exact offsets.

Live segments are safe to read while a writer is still appending. Compressed segments whose header has not yet been finalized (event_count == 0) are recovered by walking block headers and decompressing the first / last viable block; the very last block is often truncated, so the scan iterates backwards until one decompresses successfully. The same recovery is used by summary() / inspect().


Binary-log recorder hook

Built-in .lrvx sink. Owns a BinaryLogWriter and routes runner / live-engine events into it on the C++ side, without crossing into the host language per event. as_recorder yields a borrowed handle for lrvx_runner_set_market_data_recorder / lrvx_live_engine_set_market_data_recorder.

LrvxBinaryLogRecorderHookHandle
lrvx_binary_log_recorder_hook_create(const char* output_dir,
                                     uint64_t max_segment_mb,
                                     uint8_t exchange_id,
                                     uint8_t compression /* 0=None, 1=LZ4 */);
void lrvx_binary_log_recorder_hook_destroy(LrvxBinaryLogRecorderHookHandle hook);

LrvxMarketDataRecorderHandle
lrvx_binary_log_recorder_hook_as_recorder(LrvxBinaryLogRecorderHookHandle hook);

void lrvx_binary_log_recorder_hook_add_symbol(LrvxBinaryLogRecorderHookHandle hook,
                                              uint32_t symbol_id, const char* name,
                                              const char* base, const char* quote,
                                              int8_t price_precision,
                                              int8_t qty_precision);

void lrvx_binary_log_recorder_hook_flush(LrvxBinaryLogRecorderHookHandle hook);
LrvxWriterStats lrvx_binary_log_recorder_hook_stats(LrvxBinaryLogRecorderHookHandle hook);
void lrvx_binary_log_recorder_hook_stats_p(void* hook, void* out);

Segment operations

// Quick validate/merge
uint8_t lrvx_segment_validate(const char* path);
uint8_t lrvx_segment_merge(const char* input_dir, const char* output_path);

// Full API (results written to out pointer, see struct definitions in header)
void lrvx_segment_merge_full_p(const char* input_paths, size_t num_paths,
                                const char* output_dir, const char* output_name,
                                uint8_t sort, void* out);         // → LrvxMergeResult
void lrvx_segment_merge_dir_p(const char* input_dir,
                               const char* output_dir, void* out); // → LrvxMergeResult
void lrvx_segment_split_p(const char* input_path, const char* output_dir,
                           uint8_t mode, int64_t time_interval_ns,
                           uint64_t events_per_file, void* out);   // → LrvxSplitResult
void lrvx_segment_export_p(const char* input_path, const char* output_path,
                            uint8_t format, int64_t from_ns, int64_t to_ns,
                            const uint32_t* symbols, uint32_t num_symbols,
                            void* out);                            // → LrvxExportResult

uint8_t  lrvx_segment_recompress(const char* input_path, const char* output_path,
                                 uint8_t compression);
uint64_t lrvx_segment_extract_symbols(const char* input_path, const char* output_path,
                                      const uint32_t* symbols, uint32_t num_symbols);
uint64_t lrvx_segment_extract_time_range(const char* input_path, const char* output_path,
                                         int64_t from_ns, int64_t to_ns);

// Validation
void lrvx_segment_validate_full_p(const char* path, uint8_t verify_crc,
                                   uint8_t verify_timestamps, void* out); // → LrvxSegmentValidation
void lrvx_dataset_validate_p(const char* data_dir, void* out);            // → LrvxDatasetValidation

Partitioner

Splits a dataset into time or event-count partitions for parallel backtesting.

LrvxPartitionerHandle lrvx_partitioner_create(const char* data_dir);
void                  lrvx_partitioner_destroy(LrvxPartitionerHandle partitioner);

// All return number of partitions. If partitions_out is NULL, counts only.
uint32_t lrvx_partitioner_by_time(LrvxPartitionerHandle p, uint32_t num_partitions,
                                   int64_t warmup_ns,
                                   LrvxPartition* partitions_out, uint32_t max);
uint32_t lrvx_partitioner_by_duration(LrvxPartitionerHandle p, int64_t duration_ns,
                                       int64_t warmup_ns,
                                       LrvxPartition* partitions_out, uint32_t max);
uint32_t lrvx_partitioner_by_calendar(LrvxPartitionerHandle p, uint8_t unit,
                                       int64_t warmup_ns,
                                       LrvxPartition* partitions_out, uint32_t max);
uint32_t lrvx_partitioner_by_symbol(LrvxPartitionerHandle p, uint32_t num_partitions,
                                     LrvxPartition* partitions_out, uint32_t max);
uint32_t lrvx_partitioner_per_symbol(LrvxPartitionerHandle p,
                                      LrvxPartition* partitions_out, uint32_t max);
uint32_t lrvx_partitioner_by_event_count(LrvxPartitionerHandle p, uint32_t num_partitions,
                                          LrvxPartition* partitions_out, uint32_t max);

LrvxPartition fields: partition_id, from_ns, to_ns, warmup_from_ns, estimated_events, estimated_bytes.


Fixed-point conversion

int64_t lrvx_price_from_double(double value);
double  lrvx_price_to_double(int64_t raw);
int64_t lrvx_quantity_from_double(double value);
double  lrvx_quantity_to_double(int64_t raw);

Scale factor is 1e8 for both price and quantity.