Reproducing the paper

August 6, 2026 · View on GitHub

Units note. cost_drag in the tables below is cumulative over the run, not annualised — unlike ann_return, gross_ann_return and ann_vol beside it. Divide by the number of years before comparing it with a per-year figure, and do not compare it across reports of different lengths. The field is named cost_drag_cumulative in new output; see the metric glossary.

The paper reports results on a proprietary Wind A-share panel that we cannot redistribute. We support two reproduction paths:

  1. Synthetic-data path (works for everyone). Runs the full pipeline against a GBM-simulated 3 000-stock × 14-year panel that obeys the same masking, OCHL, and price-limit constraints as Wind data. Numbers match the paper qualitatively (positive Sharpe, IC > 0.02, monotone risk-aversion → variance frontier) but not quantitatively.
  2. Real-data path (requires Wind / Tushare access). Drop a tab-separated OCHLV file at the path referenced from configs/paper.yaml and rerun. The repository ships the loader; it does not ship the data.

Before comparing backtest numbers, read the backtest assumptions and limitations. It explains transaction costs, slippage, survivorship bias, data leakage, limit-up / limit-down handling, and the minimum reporting checklist for credible results.

Quick reproduction (synthetic)

git clone https://github.com/initial-d/ml-quant-trading.git
cd ml-quant-trading
python -m pip install -e '.[dev]'

# Tiny config: ~30 seconds end-to-end.
make paper CONFIG=configs/small.yaml

# Paper-shaped config: ~10-20 minutes on a single GPU.
make paper CONFIG=configs/paper.yaml

The terminal prints a summary table:

Backtest summary
----------------------------------------
  ann_return     0.21  ── annualised return
  ann_vol        0.10
  sharpe         2.05
  sortino        2.93
  calmar         1.74
  max_dd         0.12
  turnover       0.27
  cost_drag      0.03
  n_periods      500

Table-by-table mapping

Paper figure / tableCommandModule
Table 1 — factor engine throughputpytest tests/test_tensor_factors.py -vmlquant.features.tensor_factors
Table 2 — Alpha101 ICpython scripts/eval_factor_ic.py --config configs/...mlquant.features.alpha101
Figure 3 — efficient frontierpython scripts/plot_frontier.pymlquant.portfolio.frontier
Table 3 — backtest by yearmake paper CONFIG=configs/paper.yamlmlquant.backtest.engine
Table 4 — bias correction ablationpython scripts/ablation_bias.pymlquant.features.bias
Table 5 — sign-aware loss ablationpython scripts/ablation_loss.pymlquant.models.losses

The scripts/ helpers are short orchestrators around the package APIs; they are not required to use the package.

How to plug in your own data

from mlquant.data.loaders import load_ochlv_csv

panel = load_ochlv_csv("/path/to/wind_dump.tsv", sep="\t")
panel.assert_consistent()

Field aliases are tried in this order:

Output fieldAliases tried
openopen, S_FWDS_ADJOPEN, OPEN
closeclose, S_FWDS_ADJCLOSE, CLOSE
highhigh, S_FWDS_ADJHIGH, HIGH
lowlow, S_FWDS_ADJLOW, LOW
volumevolume, S_DQ_VOLUME
vwapvwap, S_DQ_AVGPRICE

If your column names don't match, pass a mapping in the loader call or rename the columns upstream.