tradesimr

tradesimr is an R-native trading execution and simulation engine with a C++ execution core. It turns strategy intentions and explicit orders into simulated trades, positions, cash, P&L, risk, and performance outputs under configurable execution, margin, funding, and cost assumptions.

The package is designed to sit between strategy packages and market-data adapters:

Current Scope

CRAN-Core Contract

The package’s supported CRAN-facing boundary, durable-schema policy, execution semantics, and 0.18.x compatibility freeze are documented in inst/CRAN-CORE.md. Local dashboards, services, and orchestration remain optional tooling rather than mandatory runtime components.

Installation

From the local repository:

install.packages("devtools")
devtools::install("/Users/oliver/Documents/2025/_2025-07-21_tradesimr/tradesimr")

Or from GitHub:

devtools::install_github("OliverLDS/tradesimr")

Minimal Backtest

library(tradesimr)

bars <- data.frame(
  timestamp = as.POSIXct("2026-01-01", tz = "UTC") + 0:4 * 60,
  open = c(100, 101, 102, 101, 103),
  high = c(101, 102, 103, 102, 104),
  low = c(99, 100, 101, 100, 102),
  close = c(101, 102, 101, 103, 104),
  tgt_pos = c(0, 1, 1, 0, -1)
)

sim <- sim_backtest(bars, init_cash = 10000, lev = 10, fee_rt = 0.0005)

sim_metrics(sim)
sim_orders(sim)
sim_account(sim)

Fee-Aware Target Semantics

Target positions and target weights are first translated into contract actions at their decision boundary. An opening or increasing target action fills only on its next eligible bar. At that fill price, tradesimr clips the requested quantity to the largest contract-step quantity that satisfies:

equity - transaction_fee >= initial_margin

For example, a +1 target with lev = 1 and a nonzero fee opens a near-100%-notional long position after reserving the fee, rather than failing because the original target consumed exactly all cash. Explicit contract orders are not resized and still fail if their requested quantity violates margin.

Incremental Exchange Example

library(tradesimr)

exchange <- sim_exchange_new(list(
  cash = 10000,
  ctr_step = 1,
  lev = 10,
  mmr = 0.02,
  portfolio_margin = TRUE
))

sim_asset_add(exchange, "BTC-USDT-SWAP", asset_id = 1L)

bar <- data.frame(
  timestamp = as.POSIXct("2026-01-01 00:00:00", tz = "UTC"),
  symbol = "BTC-USDT-SWAP",
  asset_id = 1L,
  open = 100,
  high = 102,
  low = 99,
  close = 101
)

sim_exchange_add_bars(exchange, bar)
sim_submit_order(
  exchange,
  agent_id = "agent-a",
  symbol = "BTC-USDT-SWAP",
  asset_id = 1L,
  side = "buy",
  qty = 1,
  process = TRUE
)

sim_exchange_step(exchange, bar)
sim_exchange_account(exchange)
sim_exchange_orders(exchange)

Dashboards And Scripts

The package includes separate static dashboards:

Local entrypoints live under:

Example:

zsh scripts/run_live_state_dashboard.zsh
zsh scripts/open_live_agent_dashboard.zsh

Persistence

Simulation and exchange state can be exported as durable files:

sim_export(sim, "sim-out")
loaded <- sim_import("sim-out")

Live exchange sessions can also be saved and loaded:

sim_exchange_save(exchange, "exchange-out")
exchange2 <- sim_exchange_load("exchange-out")

Development Status

tradesimr is under active development. The current design favors stable event schemas, replayability, and explicit exchange/accounting boundaries before expanding production-grade live service features.

Performance Profiling

Bulk portfolio replay exposes phase timings through sim_portfolio_target_replay(..., profile = TRUE). The installed Vox-style fixture can be run locally without affecting the normal test suite:

source(system.file("examples", "vox_arena_replay_benchmark.R", package = "tradesimr"))
run_vox_arena_replay_benchmark(n_days = 252, use_bulk = TRUE, profile = TRUE)$timings

Use fixture = "vox" for the Arena-shaped workload: eight assets, 64 single-asset deterministic accounts, and two multi-asset accounts. Profiling artifacts are deliberately local rather than package fixtures:

run_vox_arena_replay_benchmark(
  n_days = 252, fixture = "vox", profile = TRUE,
  memory_profile = TRUE, artifact_path = "local-benchmark/vox"
)$metrics

The artifact directory receives scalar phase timings, per-boundary latency, peak memory, sampled garbage collections, and, when enabled, Rprof and large-allocation Rprofmem traces.

The test suite always verifies the timing contract on a small fixture. To run the full 252-boundary performance workload, set TRADESIMR_RUN_PERF_TESTS=true. Set TRADESIMR_MAX_BULK_REPLAY_SECONDS only when enforcing a budget on a controlled machine; no hardware-dependent wall-time limit is imposed by default.