Harden JoinQuant browser smoke automation

This commit is contained in:
Yuxuan Yan
2026-07-04 19:27:48 +08:00
parent 5fada75d23
commit efa9d24c73
4 changed files with 206 additions and 19 deletions
+30
View File
@@ -8,6 +8,7 @@ write a configured standalone file for a real run.
from __future__ import annotations
import json
from pathlib import Path
from string import Template
from typing import Literal
@@ -33,6 +34,7 @@ PORTFOLIO_NAME = "${portfolio_name}"
TARGET_MODE = "${mode}"
ALLOW_SHORT = ${allow_short}
TARGET_FILE_PREFIX = "" # Optional uploaded-file prefix, for example "run1/"
_EMBEDDED_TARGETS = ${embedded_targets}
def initialize(context):
@@ -55,6 +57,7 @@ def _today_file_name(context):
def _read_target_file(file_name):
${embedded_target_read}
data = read_file(TARGET_FILE_PREFIX + file_name)
if isinstance(data, bytes):
data = data.decode("utf-8")
@@ -201,6 +204,8 @@ exec(_WRAPPER_TEMPLATE.substitute(
portfolio_name="run1",
mode="target_shares",
allow_short="False",
embedded_targets="{}",
embedded_target_read="",
))
@@ -209,23 +214,47 @@ def render_wrapper_strategy(
portfolio_name: str,
mode: WrapperMode = "target_shares",
allow_short: bool = False,
embedded_targets: dict[str, str] | None = None,
) -> str:
"""Render the standalone JoinQuant wrapper strategy source."""
if mode not in {"target_shares", "target_value"}:
raise ValueError("mode must be 'target_shares' or 'target_value'")
embedded_targets = embedded_targets or {}
embedded_target_read = ""
if embedded_targets:
embedded_target_read = (
" if file_name in _EMBEDDED_TARGETS:\n"
" return _EMBEDDED_TARGETS[file_name]\n"
)
return _WRAPPER_TEMPLATE.substitute(
portfolio_name=portfolio_name,
mode=mode,
allow_short="True" if allow_short else "False",
embedded_targets=json.dumps(embedded_targets, ensure_ascii=False, indent=4),
embedded_target_read=embedded_target_read,
)
def _load_embedded_targets(targets_dir: str | Path | None) -> dict[str, str]:
if targets_dir is None:
return {}
root = Path(targets_dir)
targets = {
path.name: path.read_text(encoding="utf-8")
for path in sorted(root.glob("*.csv"))
}
if not targets:
raise ValueError(f"No CSV target files found under {root}")
return targets
def write_wrapper_strategy(
*,
portfolio_name: str,
mode: WrapperMode = "target_shares",
out_path: str | Path,
allow_short: bool = False,
embedded_targets_dir: str | Path | None = None,
) -> Path:
"""Write a configured standalone JoinQuant wrapper strategy."""
path = Path(out_path)
@@ -235,6 +264,7 @@ def write_wrapper_strategy(
portfolio_name=portfolio_name,
mode=mode,
allow_short=allow_short,
embedded_targets=_load_embedded_targets(embedded_targets_dir),
),
encoding="utf-8",
)