tearsheet
The HTML report generator for a LIVE command journal — the same metrics a backtest produces, computed from the fills that actually happened.
tearsheet reads a live command journal and turns its fill stream into the same tearsheet a
backtest produces. It is not a backtest reader: the input is the journal a running paper or live
session wrote, and the output is that session's performance
(crates/vike-report/src/lib.rs).
usage: tearsheet --journal DIR [--seed CASH] [--name LABEL] [--periods-per-year N] [--json]
[--html PATH] [--store DIR [--venue V] [--interval STR]]--journal DIR is required, or $VIKE_JOURNAL_DIR — the same variable that turns journaling on in
the producing binary, so you point the reader at exactly what you enabled. Without it the tool
exits 2 with the usage line. That printed line omits --mtm, which is nonetheless a real flag
whenever --store is present (crates/vike-report/src/tearsheet_cli.rs's run) — described
below.
The parity contract
Every closed-trade round-trip is reconstructed through vike_model::compute_fill — the one
cost-basis primitive that vike_exec::Account::fold and vike_backtest's SimBroker::apply_fill
both delegate to — and every performance number is a call into vike_analytics::metrics. No
metric is reimplemented here. So a live tearsheet and a backtest tearsheet over the same fill
sequence are computed bit-for-bit identically.
The analytics edge is deliberately vike-analytics, not vike-backtest
Those modules used to live in vike-backtest, so reusing them meant compiling 32,259 lines to
reach ~3,900: the simulator, the paper exchange and the whole gated harness tree came along, and
89% of what this crate built it could never call. vike-analytics depends on vike-model alone,
so the catalog now arrives without the machine that produced it. The numbers are the same
functions; only their home changed.
Flags
--seed is the account's starting capital, default 10000. It sets the base of the realized-only
equity curve, so it scales total_return, cagr and sharpe — pass the session's real starting
equity for accurate returns. --name labels the sheet. --periods-per-year is the
Sharpe/Sortino/Calmar/CAGR annualization factor, default 252 (report::DAILY_PERIODS_PER_YEAR);
note the equity curve here is realized-per-trade rather than a fixed calendar cadence, so
annualized ratios are approximate.
--json prints the LiveTearsheet as pretty JSON instead of the human table. --html PATH
additionally writes the self-contained HTML tearsheet through crate::render_html — a metrics
table, inline-SVG equity and underwater-drawdown charts, and a monthly-returns table when
timestamps allow — leaving the terminal output unchanged.
Store enrichment
--store DIR points at a vike-data DataFusion + Parquet hist store root, and needs the crate's
hist feature. Given both, two enrichments replace the bare realized-only sheet.
First, the equity curve is read from the store's kind=equity series
(crate::equity_curve_from_store) — a true mark-to-market curve. The equity sampler persists the
cross-venue account rollup under venue="portfolio", symbol="TOTAL" (per-exchange rows use
symbol=<exchange>), and that whole-account curve is what the tearsheet reads; it falls back to
the realized-only curve, with a note on stderr, when no such series exists. Second, each
reconstructed trade's MAE and MFE is back-filled from the store's OHLC bars over the trade window
(crate::backfill_excursions).
--interval is the bar series interval used for the excursion back-fill, default 1m. --venue
names the trades' venue for those bar lookups — the Trade type drops venue — and when omitted it
is derived from the journal's fills if they all share one; otherwise --venue is required. The
equity-curve lookup does not use it, because that series is the portfolio/TOTAL rollup
rather than a per-venue one.
--store errors without the hist feature
Built without --features hist, passing --store exits 2: the DataFusion backend is not compiled
in. That is a build question, not a store question, and the message says so rather than reporting a
missing series.
--mtm (which requires --store) swaps the equity source: instead of the sampler's kind=equity
series, the curve is reconstructed from the journal fills marked to market against the store's
(--venue, --interval) bars (crate::mtm_curve_from_store) — the sampler stays the default. It
additionally renders a "Runtime exposure" section into the --html output — turnover, gross and
net exposure, peak margin (crate::RuntimeStats). Without --store it is a no-op, and on the
default path everything is byte-identical to before the flag existed.
Where the numbers come from
The report side of this crate is a small set of pure steps, each its own module:
journal_read::fills_from_journal reads the journal's fill records, trades::reconstruct_trades
folds them into closed round-trips through the shared cost-basis primitive, equity builds the
curve from samples, the store or the trades themselves, mtm adds the positions-over-time fold
marked against store prices, and html::render_html renders. Nothing in the mtm path is
persisted: the live kind=equity sampler stays the primary source.
The bin is a thin shim over vike_report::tearsheet_cli::run, which takes both argv and the
environment as parameters — taking VIKE_JOURNAL_DIR from a caller-supplied map rather than
std::env::var is what moves its settings-registry row from Layer::Binary to Layer::Injected,
the registry's own declared target state.
Related: the command journal, reading the journal, the report, metrics, excursions, read a backtest report.