Files
chinese-equity-quant/plugins/joinquant

JoinQuant Comparison Plugin

This plugin exports frozen targets from the internal A-share research pipeline, drives a standalone JoinQuant wrapper strategy, ingests JoinQuant output files, and reconciles them against the internal reference simulator.

The plugin validates system mechanics, not alpha quality:

  • date alignment
  • symbol mapping
  • target position generation
  • open execution timing
  • lot rounding and filled shares
  • position carry
  • trading cost and PnL accounting
  • blocked trades from suspension and price limits

Commands

uv run python cli.py joinquant prepare-smoke \
  --out-dir /tmp/chinese-equity-quant-realdata

uv sync --extra joinquant-browser
uv run playwright install chromium

uv run python cli.py joinquant browser-login \
  --storage-state ~/.config/chinese-equity-quant/joinquant_storage_state.json

uv run python cli.py joinquant write-browser-config \
  --out-path /tmp/chinese-equity-quant-realdata/joinquant_browser_config.json \
  --strategy-url "https://www.joinquant.com/..." \
  --flow backtest

uv run python cli.py joinquant run-browser-backtest \
  --manifest-path /tmp/chinese-equity-quant-realdata/joinquant_smoke_manifest.json \
  --config-path /tmp/chinese-equity-quant-realdata/joinquant_browser_config.json \
  --storage-state ~/.config/chinese-equity-quant/joinquant_storage_state.json

uv run python cli.py joinquant write-browser-config \
  --out-path /tmp/chinese-equity-quant-realdata/joinquant_sim_config.json \
  --strategy-url "https://www.joinquant.com/<模拟盘 page>" \
  --flow sim-trade

uv run python cli.py joinquant run-browser-sim \
  --manifest-path /tmp/chinese-equity-quant-realdata/joinquant_smoke_manifest.json \
  --config-path /tmp/chinese-equity-quant-realdata/joinquant_sim_config.json \
  --storage-state ~/.config/chinese-equity-quant/joinquant_storage_state.json

uv run python cli.py joinquant export-targets \
  --positions-path portfolio/run1.pq \
  --portfolio-name run1 \
  --mode target_shares \
  --execution-calendar-path data/daily_bars/csi500 \
  --start-date 2026-07-01 \
  --end-date 2026-07-31 \
  --out-dir plugins_output/joinquant/targets

uv run python cli.py joinquant write-wrapper \
  --portfolio-name run1 \
  --mode target_shares \
  --out-path plugins_output/joinquant/wrapper_strategy_run1.py

uv run python cli.py joinquant ingest \
  --portfolio-name run1 \
  --fills-csv path/to/jq_fills.csv \
  --positions-csv path/to/jq_positions.csv \
  --pnl-csv path/to/jq_pnl.csv \
  --out-dir plugins_output/joinquant/ingested

uv run python cli.py joinquant reconcile \
  --portfolio-name run1 \
  --targets-dir plugins_output/joinquant/targets/run1 \
  --our-fills-path fills/run1.pq \
  --our-positions-path portfolio/run1.pq \
  --our-pnl-path pnl/run1.pq \
  --jq-fills-path plugins_output/joinquant/ingested/run1/fills.pq \
  --jq-positions-path plugins_output/joinquant/ingested/run1/positions.pq \
  --jq-pnl-path plugins_output/joinquant/ingested/run1/pnl.pq \
  --out-dir plugins_output/joinquant/reconcile

target_shares is the default and uses the built integer position_shares from portfolio build, matching what the internal simulator executes. For strict simulator-vs-JoinQuant comparison, pass --execution-calendar-path so position dates are shifted to the next session open, matching the internal simulator's next-open convention.

prepare-smoke automates the local side of the first sanity check: tiny real data download, one-stock long-only position file, internal simulation, aligned target export, wrapper generation, and a manifest with expected JoinQuant CSV export paths.

run-browser-backtest automates the remote JoinQuant web run through Playwright. It reuses a saved browser login state, executes the configured UI actions, downloads JoinQuant CSVs when configured, and runs ingest/reconcile automatically once all three CSVs are present.

run-browser-sim is the forward-test / 模拟盘 equivalent. Use a --flow sim-trade config to upload the frozen next-session target file, save the strategy, and start or restart the JoinQuant simulated-trading job. After close, run it again with download actions or use ingest / reconcile directly on exported CSVs.