13. Appendix
This appendix collects the reference tables that the preceding chapters rely on: the numeric values of every enumeration exported by tse_enums.h, tse_duration.h and tse_log.h; the complete name map from every user-facing action to its C, C++ and Python spelling; the status and last-error contract shared by all three surfaces; the labels, identifiers, boundary conventions and fixed buffer capacities of the C ABI; the schema of the SQLite table into which the blotter journals executed trades; and the defaults that the two wrappers apply on top of a default-free C surface. Sections A through D and F are taken from the current headers of ABI generation 6; section E has no header behind it and is taken from the engine's own blotter SQL, which is internal to the library.
A. Enumerations
Enumeration values are identical across all three surfaces; only the spelling differs. The C constants live in the named headers; the C++ wrapper mirrors each as an enum class in namespace tse with the same lower-snake enumerator names (exceptions are noted per table); the Python wrapper mirrors each as an IntEnum class in module tse with PascalCase member names. For string forms the library exports tse_instrument_to_string, tse_underlying_to_string, tse_venue_to_string, tse_side_to_string, tse_cmp_to_string, tse_price_type_to_string, tse_quantity_mode_to_string, tse_tif_to_string, tse_txn_type_to_string and tse_priority_to_string in tse_enums.h, plus tse_duration_to_string in tse_duration.h. In the tables below the C prefix named in each lead is stripped from the constant column.
TseInstrument (tse_enums.h, prefix tse_instrument_) — C++ tse::Instrument, Python tse.Instrument.
| Constant | Value | Constant | Value |
|---|---|---|---|
undefined | 0 | equity | 1 |
option | 2 | future | 4 |
debt | 8 | currency | 16 |
index | 32 |
TseUnderlying (tse_enums.h, prefix tse_underlying_) — C++ tse::Underlying, Python tse.Underlying.
| Constant | Value | Constant | Value |
|---|---|---|---|
undefined | 0 | equity | 1 |
debt | 2 | currency | 4 |
commodity | 8 | crypto | 16 |
etf | 32 | index | 64 |
TseVenue (tse_enums.h, prefix tse_venue_) — C++ tse::Venue, Python tse.Venue; the enumerator names are identical on all three surfaces.
| Constant | Value | Constant | Value | Constant | Value |
|---|---|---|---|---|---|
undefined | 0 | NYSE | 1 | NASDAQ | 2 |
CBOE | 3 | CME | 4 | ICE | 5 |
TSX | 6 | B3 | 7 | BMV | 8 |
BCS | 9 | BVC | 10 | BVL | 11 |
BYMA | 12 | LSE | 13 | EUREX | 14 |
EURONEXT | 15 | MOEX | 16 | XETRA | 17 |
SIX | 18 | BME | 19 | BIT | 20 |
OMX | 21 | OSLO | 22 | WSE | 23 |
BIST | 24 | TSE | 25 | HKEX | 26 |
ASX | 27 | SSE | 28 | SZSE | 29 |
NSE | 30 | BSE | 31 | KRX | 32 |
SGX | 33 | TWSE | 34 | IDX | 35 |
SET | 36 | MYX | 37 | BINANCE | 38 |
COINBASE | 39 | KRAKEN | 40 | BITSTAMP | 41 |
OKX | 42 | BYBIT | 43 | BITFINEX | 44 |
KUCOIN | 45 | GEMINI | 46 | HTX | 47 |
user_defined_1 | 48 | user_defined_2 | 49 | user_defined_3 | 50 |
user_defined_4 | 51 | user_defined_5 | 52 | user_defined_6 | 53 |
user_defined_7 | 54 | user_defined_8 | 55 | user_defined_9 | 56 |
user_defined_10 | 57 | US | 58 | EU | 59 |
UK | 60 |
TseSide (tse_enums.h, prefix tse_side_) — the full mirror of the engine's side/quotation enumeration; the numeric values are the engine codes, and long carries the aliases bid/buy while short carries ask/sell. C++ tse::Side spells the keyword collisions long_ and short_; Python tse.Side uses Long and Short.
| Constant | Value | Constant | Value |
|---|---|---|---|
undefined | 0 | neutral | 1 |
long | 2 | short | 4 |
mid | 8 | trade | 16 |
quote | 32 | general | 64 |
TseCmp (tse_enums.h, prefix tse_cmp_) — C++ tse::Cmp, Python tse.Cmp. Directions: ge >=, lt <, gt >, le <=, eq =, ne !=.
| Constant | Value | Constant | Value |
|---|---|---|---|
ge | 0 | lt | 1 |
gt | 2 | le | 3 |
eq | 4 | ne | 5 |
TsePriceType (tse_enums.h, prefix tse_price_) — C++ tse::PriceType; the Python class is named tse.Price.
| Constant | Value | Constant | Value |
|---|---|---|---|
undefined | 0 | market | 1 |
limit | 2 | general | 3 |
TseTxnType (tse_enums.h, prefix tse_txn_) — the transaction kind of a multileg leg, engine codes. C++ tse::TxnType, Python tse.TxnType (Enter, Exit, StopLoss, StopLossTrailing, TakeProfit, Chaining, Forced, TakeProfitTrailing).
| Constant | Value | Constant | Value |
|---|---|---|---|
undefined | 0 | enter | 1 |
exit | 2 | stoploss | 4 |
stoploss_trailing | 8 | takeprofit | 16 |
chaining | 32 | forced | 64 |
takeprofit_trailing | 128 |
TsePriority (tse_enums.h, prefix tse_priority_) — the order priority of a multileg leg, engine codes. C++ tse::Priority, Python tse.Priority (NonReplaceable for the third value).
| Constant | Value | Constant | Value |
|---|---|---|---|
undefined | 0 | replaceable | 1 |
non_replaceable | 2 |
TseQuantityMode (tse_enums.h, prefix tse_quantity_) — C++ tse::QuantityMode; the Python class is named tse.Quantity, with FromSignal for the last value.
| Constant | Value | Constant | Value |
|---|---|---|---|
undefined | 0 | all | 1 |
fixed | 2 | from_signal | 3 |
TseTif (tse_enums.h, prefix tse_tif_) — C++ tse::Tif, Python tse.Tif.
| Constant | Value | Constant | Value |
|---|---|---|---|
undefined | 0 | day | 1 |
gtd | 2 | gtc | 3 |
gts | 4 | atc | 5 |
opg | 6 | fok | 7 |
ioc | 8 | aon | 9 |
TseMode (tse_enums.h, prefix tse_mode_) — the account licensing mode set by tse_account_set_mode. C++ tse::Mode, Python tse.Mode.
| Constant | Value | Constant | Value |
|---|---|---|---|
backtest | 0 | live | 1 |
TseDuration (tse_duration.h, prefix tse_duration_) — C++ tse::Duration with identical spellings; Python tse.Duration in PascalCase (Duration.FiveSeconds, Duration.ThirtyMinutes, ...).
| Constant | Value | Constant | Value | Constant | Value |
|---|---|---|---|---|---|
nanoseconds | 0 | microseconds | 1 | milliseconds | 2 |
seconds | 3 | five_seconds | 4 | ten_seconds | 5 |
thirty_seconds | 6 | minutes | 7 | two_minutes | 8 |
three_minutes | 9 | five_minutes | 10 | ten_minutes | 11 |
fifteen_minutes | 12 | thirty_minutes | 13 | hours | 14 |
two_hours | 15 | three_hours | 16 | six_hours | 17 |
eight_hours | 18 | twelve_hours | 19 | days | 20 |
two_days | 21 | three_days | 22 | weeks | 23 |
months | 24 | quarters | 25 | years | 26 |
TseLogLevel (tse_log.h, prefix tse_log_) — C++ tse::LogLevel ends in none; the Python member for value 6 is spelled LogLevel.Off.
| Constant | Value | Constant | Value |
|---|---|---|---|
trace | 0 | debug | 1 |
info | 2 | warning | 3 |
error | 4 | critical | 5 |
none | 6 |
The remaining exported enumerations are declared next to the surface they belong to. TseStatus (tse_types.h) is tabulated in the next section of this appendix; the others are tabulated in their own chapters: TseStorageRegime and TseCurrency in tse_types.h; TseMdType in tse_marketdata.h; TseRuleType in tse_rule.h; TseRiskPolicyType in tse_risk.h; TseOhlcvField and TseBidAskField in tse_execution.h; TseBookLevelKind, TseBookMessageKind and TseBookMissingLevel in tse_book.h.
B. Name map
The map below covers every user-facing action of the export layer. In the C++ column an unqualified name is a method of tse::Account; in the Python column an unqualified name is a method of tse.Account; a Market., Execution., Book., ExPost. or Storage. prefix marks the holder object, and a tse:: or tse. prefix marks a free function of the namespace or module. Where a family of C functions differs only in a type or kind suffix, the row writes the varying part as <t> or <kind> and lists the admissible values.
Library, versions and diagnostics.
| Action | C | C++ | Python |
|---|---|---|---|
| set initial params (folders, log level) | tse_set_initial_params | tse::setInitialParams | tse.set_initial_params |
| initialization error text | tse_last_init_error | tse::lastInitError | tse.last_init_error |
| set log level | tse_set_log_level | tse::setLogLevel | Account.set_log_level |
| ABI version | tse_abi_version | tse::abiVersion | tse.abi_version / Account.abi_version |
| supported durations | tse_supported_durations | tse::supportedDurations | tse.supported_durations |
| supported market-data types | tse_supported_mdtypes | tse::supportedMdTypes | tse.supported_md_types |
| fix-point scale / encode / decode | tse_finvalue_scale, tse_finvalue_from_double, tse_finvalue_to_double | tse::finValueScale, finValueFromDouble, finValueToDouble | tse.fin_value_scale, fin_value_from_double, fin_value_to_double |
| last engine error | tse_last_error | thrown as tse::Error | raised as tse.TseError |
Account and contracts.
| Action | C | C++ | Python |
|---|---|---|---|
| create account (regime, currency required) | tse_account_create | tse::Account constructor | tse.Account constructor |
| destroy account | tse_account_destroy | Account destructor | close |
| set licensing mode | tse_account_set_mode | setMode | set_mode |
| set equity baseline and risk-free rate | tse_set_account_equity | setAccountEquity | set_account_equity |
| declare contract | tse_add_contract / tse_add_contract_id | addContract | add_contract |
| look up contract id | tse_get_contract_id | getContractId | get_contract_id |
Market data.
| Action | C | C++ | Python |
|---|---|---|---|
| create adapter | tse_market_create | createMarket | create_market |
push tick, <t> in ohlcv, bidask, trade | tse_market_push_<t>_by_name / _by_id | Market.pushOhlcv / pushBidAsk / pushTrade (symbol and id overloads) | Market.push_<t>_by_name / _by_id |
| push executed trade | tse_market_push_executed_by_name / _by_id | Market.pushExecuted | Market.push_executed_by_name / _by_id |
| push book message | tse_market_push_book_by_name / _by_id | Market.pushBook | Market.push_book_by_name / _by_id |
Execution.
| Action | C | C++ | Python |
|---|---|---|---|
| create Simulator execution | tse_exec_create_simulator | createSimulator | create_simulator |
| create custom execution | tse_exec_create_custom | createCustom | create_custom |
| report a fill | tse_exec_apply_fill | Execution.applyFill | Execution.apply_fill |
| fully-executed order count | tse_exec_get_count | Execution.getCount | Execution.get_count |
| running flag | tse_exec_is_running | Execution.isRunning | Execution.is_running |
Inputs and patterns.
| Action | C | C++ | Python |
|---|---|---|---|
typed input, <t> in ohlcv, bidask, trade, executed, book | tse_add_input_<t> | addInputOhlcv / addInputBidAsk / addInputTrade / addInputExecuted / addInputBook | add_input_<t> |
| built-in book-imbalance input | tse_add_input_book_imbalance | addInputBookImbalance | add_input_book_imbalance |
| record a value from a processor | tse_storage_push | Storage.push | Storage.push |
| stored value count | tse_storage_size | Storage.size | Storage.size |
pattern, <kind> in comparison, crossover, threshold, peak, timestamp, formula | tse_add_pattern_<kind> | addPatternComparison / addPatternCrossover / addPatternThreshold / addPatternPeak / addPatternTimestamp / addPatternFormula | add_pattern_<kind> |
Rules.
| Action | C | C++ | Python |
|---|---|---|---|
| market rule (entry / exit / rebalance) | tse_add_rule_market | addRuleMarket | add_rule_market |
| risk rule (stop-loss / take-profit families) | tse_add_rule_risk | addRuleRisk | add_rule_risk |
| multileg rule | tse_add_rule_multileg | addRuleMultileg | add_rule_multileg |
| bracket rule | tse_add_rule_bracket | addRuleBracket | add_rule_bracket |
| OCO rule | tse_add_rule_oco | addRuleOco | add_rule_oco |
amend rule, <kind> in cancel, replace, modify | tse_add_rule_<kind> | addRuleCancel / addRuleReplace / addRuleModify | add_rule_<kind> |
Robot lifecycle and bulk actions.
| Action | C | C++ | Python |
|---|---|---|---|
| add robot | tse_add_robot | addRobot | add_robot |
| start / stop / halt | tse_start / tse_stop / tse_halt | start / stop / halt | start / stop / halt |
| cancel all resting orders | tse_cancel_all | cancelAll | cancel_all |
| close the whole position | tse_sale_all | saleAll | sale_all |
| halt, then cancel all | tse_halt_and_cancel_all | haltAndCancelAll | halt_and_cancel_all |
| halt, then close position | tse_halt_and_sale_all | haltAndSaleAll | halt_and_sale_all |
| halt, cancel and close | tse_halt_and_cancel_sale_all | haltAndCancelSaleAll | halt_and_cancel_sale_all |
Results and external-trade booking.
| Action | C | C++ | Python |
|---|---|---|---|
| account summary | tse_get_summary | getSummary | get_summary |
| per-robot summary | tse_get_robot_summary | getRobotSummary | get_robot_summary |
| all summaries | tse_get_summaries | getSummaries | get_summaries |
| retained trades | tse_get_trades | getTrades | get_trades |
| book external trade (moves the portfolio) | tse_book_trade | bookTrade | book_trade without snapshots |
| book against supplied exposure (pure P&L) | tse_book_trade_with_exposure | bookTradeWithExposure | book_trade with both snapshots |
Portfolio, reset and risk policies.
| Action | C | C++ | Python |
|---|---|---|---|
| portfolio aggregate state | tse_get_portfolio_state | getPortfolioState | get_portfolio_state |
| single position state | tse_get_position_state | getPositionState | get_position_state |
| subscribe / unsubscribe marking | tse_portfolio_subscribe / tse_portfolio_unsubscribe | portfolioSubscribe / portfolioUnsubscribe | portfolio_subscribe / portfolio_unsubscribe |
| register a position without an adapter | tse_portfolio_add_contract | portfolioAddContract | portfolio_add_contract |
| reset whole portfolio | tse_reset_portfolio | resetPortfolio | reset_portfolio |
| reset one position | tse_reset_position | resetPosition | reset_position |
| threshold risk policy | tse_add_risk_policy | addRiskPolicy | add_risk_policy |
| trading-window risk policy | tse_add_risk_policy_time_period | addRiskPolicyTimePeriod | add_risk_policy_time_period |
| remove risk policy | tse_remove_risk_policy | removeRiskPolicy | remove_risk_policy |
Order books.
| Action | C | C++ | Python |
|---|---|---|---|
| create a book | tse_book_create | createBook | create_book |
| destroy a book early | tse_book_destroy | account-owned, no call | account-owned, no call |
| apply a message | tse_book_apply | Book.apply | Book.apply |
| whole-book imbalance | tse_book_imbalance | Book.imbalance | Book.imbalance |
| imbalance to price bounds | tse_book_imbalance_to_bound | Book.imbalanceToBound | Book.imbalance_to_bound |
| imbalance to depth | tse_book_imbalance_to_depth | Book.imbalanceToDepth | Book.imbalance_to_depth |
| one side's aggregates | tse_book_side_stats | Book.sideStats | Book.side_stats |
| aggregates to a bound | tse_book_side_stats_to_bound | Book.sideStatsToBound | Book.side_stats_to_bound |
| top level rows | tse_book_levels_top | Book.levelsTop | Book.levels_top |
| book error text | tse_book_last_error | thrown as tse::Error | raised as tse.TseError |
ex_post statistics and features.
| Action | C | C++ | Python |
|---|---|---|---|
| write the scores database | tse_ex_post_save | exPostSave | ex_post_save |
| validate an existing database | tse_ex_post_load | exPostLoad | ex_post_load |
| create a live scoring object | tse_ex_post_create | createExPost | create_ex_post |
| destroy it | tse_ex_post_destroy | ExPost destructor | ExPost.close |
| robot count / label / bucket count | tse_ex_post_robot_count / _robot_label / _bucket_count | ExPost.robotCount / robotLabel / bucketCount | ExPost.robot_count / robot_label / bucket_count |
| parameter axis | tse_ex_post_param_count / tse_ex_post_param_name | ExPost::paramCount / paramName | ExPost.param_count / param_name |
| momentum feature | tse_ex_post_feature_momentum | ExPost.featureMomentum | ExPost.feature_momentum |
| EWMA feature | tse_ex_post_feature_ewma | ExPost.featureEwma | ExPost.feature_ewma |
| level-crossings feature | tse_ex_post_feature_level_crossings | ExPost.featureLevelCrossings | ExPost.feature_level_crossings |
Persistence.
| Action | C | C++ | Python |
|---|---|---|---|
register input processor, <t> in ohlcv, bidask, trade, executed | tse_register_input_processor_<t> | registerInputProcessor / registerInputProcessorBidAsk / registerInputProcessorTrade / registerInputProcessorExecuted | register_input_processor / _bidask / _trade / _executed |
| register formula processor | tse_register_formula_processor | registerFormulaProcessor | register_formula_processor |
savable input, <t> in ohlcv, bidask, trade, executed | tse_add_input_<t>_by_key | addInputOhlcvByKey / addInputBidAskByKey / addInputTradeByKey / addInputExecutedByKey | add_input_<t>_by_key |
| savable formula pattern | tse_add_pattern_formula_by_key | addPatternFormulaByKey | add_pattern_formula_by_key |
| save / load a robot recipe | tse_save / tse_load | save / load | save / load |
| bind a loaded input | tse_bind_input | bindInput | bind_input |
Data loading, timeserie toolbox and grid search.
| Action | C | C++ | Python |
|---|---|---|---|
| load OHLCV CSV | tse_load_ohlcv_csv / tse_load_ohlcv_csv_ex | Account::loadOhlcvCsv | load_ohlcv_csv |
| load bid/ask CSV | tse_load_bidask_csv | Account::loadBidAskCsv | load_bidask_csv |
| load trade CSV | tse_load_trade_csv | Account::loadTradeCsv | load_trade_csv |
| free loaded ticks | tse_free_ticks / tse_free_bidask_ticks / tse_free_trade_ticks | handled by std::vector | handled by lists |
| CSV-loader error text | tse_last_csv_error | thrown as tse::Error | tse.last_csv_error |
| columnar CSV reader | tse_csv_reader_* | tse::CsvReader | tse.CsvReader |
| CSV writer | tse_csv_writer_* | tse::CsvWriter | tse.CsvWriter |
| head / tail subrange | tse_timeserie_head_<t> / tse_timeserie_tail_<t> | tse::head / tse::tail (overloads for every serie kind) | tse.head / tse.tail (scalar series only) |
| split by duration | tse_timeserie_split_by_duration_<t> | tse::splitByDuration | tse.split_by_duration (scalar series only) |
| diff / lag / log transform | tse_timeserie_diff_scalar / _lag_scalar / _log_scalar | tse::diff / tse::lag / tse::log | tse.diff / tse.lag / tse.log |
| grid search | tse_run_grid | tse::runGrid | tse.run_grid |
C. Statuses and errors
Every C entry point that can fail returns TseStatus; handle-creating functions (tse_account_create, tse_market_create, tse_exec_create_simulator, tse_exec_create_custom, tse_book_create, tse_ex_post_create) return the handle directly, or NULL on error. Every C entry point is wrapped in a noexcept try/catch inside the library: no exception ever crosses the C boundary. A failure comes back as tse_error or a NULL handle, and the reason is a human-readable text waiting in the last-error channel that owns the failed call.
TseStatus (tse_types.h) — the two constants of the status type.
| Constant | Value |
|---|---|
tse_ok | 0 |
tse_error | 1 |
Each area of the library has exactly one last-error channel, scoped to match the lifetime of what it reports on.
| Channel | Declared in | Scope |
|---|---|---|
tse_last_error(account) | tse_error.h | Per account: any failed call belonging to that account or its child handles. |
tse_last_init_error() | tse_params.h | Process-wide: tse_set_initial_params, which runs before any account exists. |
tse_last_csv_error() | tse_dataplane.h | Thread-local: the CSV loaders tse_load_*_csv; empty when the last load on this thread succeeded. |
tse_book_last_error(book) | tse_book.h | Per book handle; a failed tse_book_create itself reports through tse_last_error(account). |
tse_csv_reader_error(reader) | tse_timeserie.h | Per CSV-reader handle. |
tse_csv_writer_error(writer) | tse_timeserie.h | Per CSV-writer handle. |
tse_connection_last_error(client) | tse_connection/tse_connection_client.h | Per connection client, in the separate connection library. |
The C++ wrapper turns every failed status into an exception. It throws exactly one type, tse::Error, whose message carries the last-error text of the channel the failed call belongs to; the pre-account entry points stay exception-free (tse::setInitialParams is noexcept and returns bool, with the detail in tse::lastInitError()).
The Python wrapper raises tse.TseError under the same contract, and mirrors the pre-account channels as module-level functions tse.last_init_error(lib) and tse.last_csv_error().
struct Error final : std::runtime_error {
using std::runtime_error::runtime_error;
};
try:
account = tse.Account("research", tse.StorageRegime.Mem)
account.start("robot")
except tse.TseError as error:
print(error)
D. Labels, identifiers and capacities
Labels and identifiers. Entities are addressed by string labels: the account, the market adapters, the execution, the Inputs, the Patterns, the Rules and the Robots are all created under a label and referenced by it everywhere else — a Pattern names the Inputs it observes, a Rule names its Pattern, a Robot names its Rules. Contracts are the exception: they are addressed by symbol, or by the numeric uint64_t contract id returned by tse_add_contract_id / tse_get_contract_id. In a record that carries both, such as TseRetained, a contractId of zero means addressing by symbol.
Fixed string capacities. At the C boundary these strings live in fixed-size fields: labels occupy 64 bytes (63 useful characters); symbols and order identifiers occupy 32 bytes (31 useful characters). The useful length is one less than the capacity because of the NUL terminator. Oversized values fail loud: the call is rejected on input and the owning last-error channel carries the diagnostic — "the value exceeds the boundary capacity (63 characters for labels, 31 for symbols and identifiers)". Nothing is silently truncated.
| Field | C field | Capacity | Useful length | Carried by |
|---|---|---|---|---|
| contract symbol | symbol | char[32] | 31 | TseTrade, TseRetained, TseOrder, TseLegDescriptor.contractSymbol |
| client order id | clientOrderId | char[32] | 31 | TseTrade, TseRetained, TseOrder |
| broker order id | brokerOrderId | char[32] | 31 | TseTrade, TseRetained |
| rule label | ruleLabel | char[64] | 63 | TseTrade, TseRetained, TseOrder |
| robot label | robotLabel | char[64] | 63 | TseTrade, TseRetained, TseOrder |
The two order identifiers. An order carries two identifiers with distinct birthplaces. The client order id is minted on the client side when the order is created; the engine's intended-trade record carries it, the fill callback of a custom execution receives it in TseOrder, and tse_exec_apply_fill addresses fills by it. The broker order id is minted at the execution point — by the Simulator, or by the venue behind a custom execution — when the order is accepted or filled; the engine's executed-trade record carries it. The retained trade, journaled by the blotter, carries both, which is exactly the identifier block that recurs across TseTrade and TseRetained.
Capacity-in / count-out. tse_get_trades, tse_get_summaries and tse_book_levels_top share one protocol: pass the capacity of the output array in *inoutCount; on return it holds the number actually written; pass a null output pointer to query the required count without writing. When the capacity is smaller than the number of available elements the surplus is silently not written — query the count first. The wrappers hide the round trip entirely.
Count-then-buffer. The timeserie toolbox (tse_timeserie.h) and the ex_post feature readers (tse_ex_post.h) use the sibling convention: a NULL output buffer makes the call store the required element count (for features, the row count into *inoutRowCount) and touch nothing else.
Zero time bounds. In tse_get_trades, and fixed as part of the ABI: a zero fromNanoseconds means the 1970 epoch and a zero toNanoseconds means the 2100 epoch, so zero bounds mean "no bound" and 0, 0 selects everything.
Whole-row truncation of matrix extraction. tse_csv_reader_read_matrix_by_name / _by_index return a row-major flat buffer whose capacity and written count are in double elements; on a short buffer truncation drops whole rows only, so the written count always stays a multiple of the column count.
structSize stamping. TseBookMessage, TseCsvOptions and TseCsvWriterOptions carry a leading structSize field that the caller must set to sizeof of the struct; the C++ and Python wrappers fill it automatically.
Borrowed strings. A char const* returned by a CSV reader or writer handle stays valid until the next read on the same handle or its destruction. tse_last_csv_error is thread-local and stays valid until the next load on the same thread. tse_ex_post_robot_label copies into a caller buffer, NUL-terminated and truncated to the given capacity; tse_csv_reader_cell_* writes up to capacity-1 bytes plus a NUL, and with a NULL output stores the cell length instead.
Absent-value markers. TSE_ABSENT_HIGH_PRICE ((double)INT64_MIN) and TSE_ABSENT_LOW_PRICE ((double)INT64_MAX) mark a position with no observed extreme yet, with the matching timestamps written as zero (tse_trades.h); C++ mirrors them as tse::absentHighPrice / tse::absentLowPrice. TSE_ABSENT_MULTIPLE (zero) marks a placeholder exposure node in TsePositionState.multiple (tse_portfolio.h).
Versions. tse_abi_version() returns 6; the robot recipe written by tse_save uses persistence schema version 3, and a mismatched schema is rejected on load with a diagnostic.
Reading the two identifiers off a retained trade:
std::vector<tse::Trade> const trades {account.getTrades()};
std::string const
client {trades.front().clientOrderId},
broker {trades.front().brokerOrderId};
for trade in account.get_trades():
print(trade.clientOrderId.decode(), trade.brokerOrderId.decode())
The C capacity-in / count-out round trip, and what the wrappers do in its place:
size_t count = 0;
tse_get_trades(account, 0, 0, NULL, NULL, &count);
TseTrade* trades = calloc(count, sizeof(TseTrade));
tse_get_trades(account, 0, 0, NULL, trades, &count);
free(trades);
std::vector<tse::Trade> const trades {account.getTrades()};
trades = account.get_trades()
E. The retained trades table
An account created under a storage regime that includes the database — tse_storage_regime_db, C++ tse::StorageRegime::db, Python tse.StorageRegime.Db — journals every executed trade into a SQLite file. The file lives in the data folder passed as TseInitialParams.dataFolderPath to tse_set_initial_params; when no data folder has been configured the engine places it next to the running executable. Its name is the account label followed by _Blotter_retained_trades.sqlite3.db. The trades themselves occupy one table, retained_trades, and this section is its schema, so that a client can open the file and query it with plain SQL instead of going through the API.
The columns fall into six groups. The order identifiers are client_order_id and broker_order_id, the pair described above under labels and identifiers. The labels are rule_label, which is stored inline, robot_id, which is a foreign key into the strategies table whose label column holds the robot label, and contract_id, which is the numeric contract id rendered as decimal text and is a foreign key into the contracts table whose name column holds the symbol. The timestamps are ts_mkt_event and ts_execution, both nanoseconds since the 1970 epoch. The price and quantity block is price, quantity, fee and booked_pl together with the codes that classify the trade and the order behind it. The contract-exposure snapshot taken at the moment of the trade is the prev_contract_exposure_* family plus the four position-extreme columns. The portfolio-exposure snapshot is the prev_portfolio_exposure_* family.
Every *_code column is declared as a foreign key into a small seeded lookup table that names its values, and the numbers are the same engine codes tabulated in the enumerations section. Three of those tables are seeded short of the enumeration they name, which matters the moment a query joins on them. side_types, referenced by all five side columns, holds exactly three rows — 1 neutral, 2 long_, 4 short_, the two directional names carrying the trailing underscore of the C++ keyword workaround — and has no row for the undefined side, code 0. price_types holds 0 undefined, 1 market and 2 limit, and has no row for general, code 3. quantity_types holds 0 undefined, 1 all and 2 fixed, and has no row for from_signal, code 3. The remaining tables cover their enumerations in full: book_mode_types (0 undefined, 1 main, 2 split), execution_types (0 undefined, 1 ongoing, 2 completed_full, 4 completed_partial), tif_types matching TseTif and priority_types matching TsePriority. Because the seeding is partial, resolve a code with a LEFT JOIN: an inner join on side_types, price_types or quantity_types silently drops every row whose code has no lookup row.
| Column | SQL type | Meaning |
|---|---|---|
id | INTEGER PRIMARY KEY AUTOINCREMENT | Row key; carries no trading meaning. |
client_order_id | TEXT | The client order id, minted on the client side. |
broker_order_id | TEXT | The broker order id, minted at the execution point. |
contract_id | TEXT NOT NULL | The contract id as decimal text; joins contracts(contract_id). |
rule_label | TEXT NOT NULL | Label of the rule that produced the order. |
robot_id | INTEGER NOT NULL | Joins strategies(id); the robot label is strategies.label. |
ts_mkt_event | INTEGER NOT NULL | Timestamp of the market event behind the trade, nanoseconds since the epoch. |
ts_execution | INTEGER NOT NULL | Timestamp of the execution, nanoseconds since the epoch. |
price | REAL NOT NULL | Execution price of the trade. |
quantity | REAL NOT NULL | Executed quantity. |
fee | REAL NOT NULL | Fee charged on this trade. |
booked_pl | REAL NOT NULL | Realized profit and loss booked by this trade. |
txn_side_code | INTEGER NOT NULL | Side of the transaction; side_types. |
pos_side_code | INTEGER NOT NULL | Side of the position the trade belongs to; side_types. |
book_mode_code | INTEGER NOT NULL | Booking mode of the trade; book_mode_types. |
execution_code | INTEGER NOT NULL | Execution state of the order; execution_types. |
price_type_code | INTEGER NOT NULL | Price type of the order; price_types. |
prev_contract_exposure_quantity | REAL NOT NULL | Position quantity in the contract snapshot. |
prev_contract_exposure_unrealized_pl | REAL NOT NULL | Unrealized profit and loss of that position. |
prev_contract_exposure_acquisition_price_ts | INTEGER NOT NULL | Timestamp of the average acquisition price. |
prev_contract_exposure_acquisition_price | REAL NOT NULL | Average acquisition price of the position. |
pos_high_price_ts | INTEGER NOT NULL | Timestamp of the highest price observed on the position; zero when none. |
pos_high_price | REAL NOT NULL | Highest observed price; TSE_ABSENT_HIGH_PRICE when the extremes are not seeded. |
pos_low_price_ts | INTEGER NOT NULL | Timestamp of the lowest price observed on the position; zero when none. |
pos_low_price | REAL NOT NULL | Lowest observed price; TSE_ABSENT_LOW_PRICE when the extremes are not seeded. |
prev_contract_exposure_side | INTEGER NOT NULL | Side of the position in the snapshot; side_types. |
prev_portfolio_exposure_acquisition_value | REAL NOT NULL | Acquisition value of the whole portfolio. |
prev_portfolio_exposure_side | INTEGER NOT NULL | Side of the portfolio; side_types. |
prev_portfolio_exposure_market_value_side | INTEGER NOT NULL | Side of the portfolio market value; side_types. |
exchange_rate_numerator | INTEGER NOT NULL | Numerator of the rational exchange rate stored with the trade. |
exchange_rate_denominator | INTEGER NOT NULL | Denominator of that rate; the monetary columns are stored unconverted. The two rate columns belong to the cross-currency work that is still in the process of shipping; on a single-currency account they carry the unit rate. |
tif_type_code | INTEGER NOT NULL | Time in force of the order; tif_types. |
quantity_type_code | INTEGER NOT NULL | Quantity mode of the order; quantity_types. |
priority_type_code | INTEGER NOT NULL | Order priority; priority_types. |
prev_contract_exposure_market_price_ts | INTEGER NOT NULL | Timestamp of the marking price of the position. |
prev_contract_exposure_market_price | REAL NOT NULL | Marking price of the position. |
prev_contract_exposure_market_price_seeded | INTEGER NOT NULL | One when the position has been marked at least once, zero otherwise. |
prev_portfolio_exposure_market_value | REAL NOT NULL | Market value of the whole portfolio. |
prev_portfolio_exposure_unrealized_pl | REAL NOT NULL | Unrealized profit and loss of the whole portfolio. |
The table carries one compound uniqueness constraint, written out at the end of this section. The insert is written as ON CONFLICT ... DO NOTHING against exactly this tuple, which makes journaling idempotent: one executed trade cannot be written twice. A fill that reaches the blotter a second time — a replayed message, a reconnect that redelivers the same execution report, a repeated run over the same data into the same file — matches the constraint and is dropped instead of inflating the trade count and double-counting booked_pl. Note what the tuple deliberately omits: the two order identifiers and the price play no part in it, so a duplicate is recognized even when the broker restates an identifier. Indexes cover the two timestamps, the rule label, the contract and the robot, each alone and in the combinations a reporting query normally uses, so time-ranged and per-robot selections stay cheap on a large file.
The same records reach the caller without any SQL through tse_get_trades, which fills an array of TseTrade — C++ getTrades, Python get_trades. TseTrade carries the identifiers, the labels, both timestamps, the price and quantity block and both exposure snapshots, resolving contract_id back into the symbol character field and robot_id back into robotLabel; rule_label, stored inline in the table, is copied straight into ruleLabel with nothing to resolve. Four column families stay in the table only: the exchange-rate pair, the order-detail codes price_type_code, tif_type_code, quantity_type_code and priority_type_code, which are exposed instead through TseRetained, the prev_contract_exposure_market_price_seeded flag, and prev_portfolio_exposure_market_value_side.
The constraint reads:
UNIQUE(contract_id, rule_label, robot_id, ts_mkt_event, ts_execution,
quantity, book_mode_code, pos_side_code,
exchange_rate_numerator, exchange_rate_denominator)
F. Wrapper defaults
The C ABI itself carries no defaults: every struct field and every argument is required, and coreId parameters are mandatory (a negative value runs the component without a separate pinned thread). The two wrappers reintroduce the following defaults — everything not listed here remains required on all three surfaces.
| Parameter | C++ default (tse.hpp) | Python default (tse.py) |
|---|---|---|
| account currency | Currency::usd | Currency.Usd |
| account core id | coreId = -1 | core_id=-1 |
| library location | linked at build time | lib_path=None: the TSE_EXPORT_LIB environment variable, else the platform library filename |
execution requiredDataLength | 3 | required_data_length=3 |
| execution core id | -1 | -1 |
| input and pattern core id | -1 | -1 |
getTrades / get_trades time bounds | 0, 0 (no bound) | 0, 0 (no bound) |
getTrades / get_trades robot selector | empty string = all robots | robot_label=None = all robots |
| threshold risk-policy contract | empty string = portfolio-wide | contract_symbol=None = portfolio-wide |
| time-period policy time zone | empty string = engine behaviour | time_zone_name="" |
removeRiskPolicy contract | separate overloads with and without | contract_symbol=None |
book_trade snapshots | two distinct methods | both None = portfolio-moving mode; both set = exposure mode |
CSV loader options (CsvOptions / make_csv_options) | separator ,, hasHeader true, ignoreParseErrors false, bufferSize 0, empty format and column names | separator=",", has_header=True, empty format and column names |
CsvReader construction | CsvOptions {} (so hasHeader true) | separator=",", has_header=False, ignore_parse_errors=False, buffer_size=0 |
CsvWriter construction | separator ,, formatTimestamps false, empty dateFormat | separator=",", format_timestamps=False, date_format=None |
| CSV write headers | {} = no header row | headers=None = no header row |
head / tail length | n = 5 | n=5 |
diff / lag / log | offset or lag 1, Currency::usd | 1, Currency.Usd |
| grid-search currency | Currency::usd | Currency.Usd |
| initial params | none: InitialParams is a plain aggregate with an explicit applyLogLevel flag | data_folder="", log_folder="" and log_level=None all mean "leave unchanged" |
Note the one asymmetry in the CSV readers: the C++ CsvReader default (CsvOptions {}) assumes a header row, while the Python CsvReader default (has_header=False), like the C-level tse_csv_reader_create(NULL), assumes none. The Python tick-loader helper make_csv_options assumes a header row, matching its C++ counterpart.
Version 5.0.0.0