Add JoinQuant browser backtest automation
This commit is contained in:
@@ -4,6 +4,12 @@ from __future__ import annotations
|
||||
|
||||
import click
|
||||
|
||||
from plugins.joinquant.browser import (
|
||||
browser_snapshot,
|
||||
run_browser_backtest,
|
||||
save_login_state,
|
||||
write_browser_config_template,
|
||||
)
|
||||
from plugins.joinquant.export_targets import export_targets
|
||||
from plugins.joinquant.ingest import ingest_joinquant_outputs
|
||||
from plugins.joinquant.reconcile import reconcile_joinquant
|
||||
@@ -217,3 +223,103 @@ def prepare_smoke_cmd(
|
||||
f"PnL={summary['total_pnl']:,.2f}, cost={summary['total_cost']:,.2f}, "
|
||||
f"blocked={summary['blocked_trades']}"
|
||||
)
|
||||
|
||||
|
||||
@joinquant.command("browser-login")
|
||||
@click.option(
|
||||
"--storage-state",
|
||||
default="~/.config/chinese-equity-quant/joinquant_storage_state.json",
|
||||
show_default=True,
|
||||
help="Path where the authenticated browser state is stored",
|
||||
)
|
||||
@click.option(
|
||||
"--login-url",
|
||||
default="https://www.joinquant.com/user/login/index",
|
||||
show_default=True,
|
||||
)
|
||||
@click.option("--headless", is_flag=True, help="Use a headless browser")
|
||||
@click.option(
|
||||
"--wait-seconds",
|
||||
default=0,
|
||||
show_default=True,
|
||||
type=int,
|
||||
help="Seconds to wait before saving state; 0 prompts for Enter after login",
|
||||
)
|
||||
def browser_login_cmd(storage_state, login_url, headless, wait_seconds):
|
||||
"""Open JoinQuant login and save reusable browser session state."""
|
||||
path = save_login_state(
|
||||
storage_state=storage_state,
|
||||
login_url=login_url,
|
||||
headless=headless,
|
||||
wait_seconds=wait_seconds,
|
||||
)
|
||||
click.echo(f"Saved JoinQuant browser state: {path}")
|
||||
|
||||
|
||||
@joinquant.command("write-browser-config")
|
||||
@click.option("--out-path", required=True, help="Path for JSON browser automation config")
|
||||
@click.option("--strategy-url", default="", help="JoinQuant strategy edit/backtest URL")
|
||||
def write_browser_config_cmd(out_path, strategy_url):
|
||||
"""Write a browser automation selector/action config template."""
|
||||
path = write_browser_config_template(out_path, strategy_url=strategy_url)
|
||||
click.echo(f"Saved JoinQuant browser config template: {path}")
|
||||
|
||||
|
||||
@joinquant.command("browser-snapshot")
|
||||
@click.option("--url", required=True, help="Logged-in JoinQuant page URL to inspect")
|
||||
@click.option(
|
||||
"--storage-state",
|
||||
default="~/.config/chinese-equity-quant/joinquant_storage_state.json",
|
||||
show_default=True,
|
||||
)
|
||||
@click.option("--out-dir", required=True, help="Directory for page.html and page.png")
|
||||
@click.option("--headed", is_flag=True, help="Run with a visible browser")
|
||||
@click.option("--timeout-ms", default=60_000, show_default=True, type=int)
|
||||
def browser_snapshot_cmd(url, storage_state, out_dir, headed, timeout_ms):
|
||||
"""Save a page screenshot and HTML for selector discovery."""
|
||||
paths = browser_snapshot(
|
||||
url=url,
|
||||
storage_state=storage_state,
|
||||
out_dir=out_dir,
|
||||
headless=not headed,
|
||||
timeout_ms=timeout_ms,
|
||||
)
|
||||
click.echo(f"Saved HTML: {paths['html']}")
|
||||
click.echo(f"Saved screenshot: {paths['screenshot']}")
|
||||
|
||||
|
||||
@joinquant.command("run-browser-backtest")
|
||||
@click.option("--manifest-path", required=True, help="Manifest from `joinquant prepare-smoke`")
|
||||
@click.option("--config-path", required=True, help="JSON browser automation config")
|
||||
@click.option(
|
||||
"--storage-state",
|
||||
default="~/.config/chinese-equity-quant/joinquant_storage_state.json",
|
||||
show_default=True,
|
||||
)
|
||||
@click.option("--out-dir", default=None, help="Browser-run artifact directory")
|
||||
@click.option("--headed", is_flag=True, help="Run with a visible browser")
|
||||
@click.option("--no-auto-reconcile", is_flag=True, help="Skip ingest/reconcile after downloads")
|
||||
def run_browser_backtest_cmd(
|
||||
manifest_path,
|
||||
config_path,
|
||||
storage_state,
|
||||
out_dir,
|
||||
headed,
|
||||
no_auto_reconcile,
|
||||
):
|
||||
"""Run JoinQuant browser automation from manifest and config."""
|
||||
report = run_browser_backtest(
|
||||
manifest_path=manifest_path,
|
||||
config_path=config_path,
|
||||
storage_state=storage_state,
|
||||
out_dir=out_dir,
|
||||
headless=not headed,
|
||||
auto_reconcile=not no_auto_reconcile,
|
||||
)
|
||||
click.echo(f"Saved browser run report: {report['report_path']}")
|
||||
if report["downloaded"]:
|
||||
click.echo("Downloaded JoinQuant CSVs:")
|
||||
for key, path in report["downloaded"].items():
|
||||
click.echo(f" {key}: {path}")
|
||||
if report["reconcile_paths"]:
|
||||
click.echo(f"Saved reconciliation summary: {report['reconcile_paths']['summary_md']}")
|
||||
|
||||
Reference in New Issue
Block a user