rebuild(screener): add controlled formulas and rolling backtests
This commit is contained in:
@@ -111,7 +111,19 @@ const workspace = {
|
||||
run(3, "curated", "动态多因子(基础版)", "completed", "curated-02", candidateNamed("000022", "多因子样本", "综合因子得分居前")),
|
||||
],
|
||||
custom_strategies: [{ id: 7, name: "我的选股策略", version: 2, formula }],
|
||||
custom_runs: [run(4, "custom", "我的选股策略", "completed", "custom-7", candidateNamed("000031", "自定义样本", "用户条件确定性命中"))],
|
||||
custom_runs: [{
|
||||
...run(4, "custom", "我的选股策略", "completed", "custom-7", candidateNamed("000031", "自定义样本", "用户条件确定性命中")),
|
||||
backtest: {
|
||||
sample_size: 7,
|
||||
evaluated_dates: 7,
|
||||
stable: false,
|
||||
win_rate: null,
|
||||
average_return_3d: null,
|
||||
period_start: "2026-07-01",
|
||||
period_end: "2026-07-09",
|
||||
message: "小样本:当前7个有效样本,满20个后显示胜率与平均收益",
|
||||
},
|
||||
}],
|
||||
};
|
||||
|
||||
const track = {
|
||||
@@ -138,6 +150,19 @@ async function mockScreener(page) {
|
||||
const body = route.request().method() === "GET" ? [track] : { id: 9 };
|
||||
return route.fulfill({ contentType: "application/json", body: JSON.stringify(body) });
|
||||
});
|
||||
await page.route("**/api/screener/formula/compile", (route) => route.fulfill({
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({
|
||||
prompt_version: "screener:formula-compiler:v1",
|
||||
formula: {
|
||||
universe: { exclude_st: true, listed_days_min: 120 },
|
||||
filters: [{ field: "amount_billion", op: ">=", value: 3 }],
|
||||
score: [{ field: "return_20d", weight: 1, direction: "desc" }],
|
||||
limit: 20,
|
||||
min_score: 0.55,
|
||||
},
|
||||
}),
|
||||
}));
|
||||
}
|
||||
|
||||
test("stage 9 screening preserves deterministic modes, explicit tracking and responsive layout", async ({ page }) => {
|
||||
@@ -161,6 +186,9 @@ test("stage 9 screening preserves deterministic modes, explicit tracking and res
|
||||
await page.getByRole("button", { name: "策略选股" }).click();
|
||||
await expect(page.getByText("策略库")).toBeVisible();
|
||||
await expect(page.getByText("动态多因子(基础版)", { exact: true })).toBeVisible();
|
||||
await expect(page.getByText("风险等级", { exact: true })).toBeVisible();
|
||||
await expect(page.getByText("评分权重", { exact: true })).toBeVisible();
|
||||
await expect(page.locator(".strategy-detail")).toContainText("20日涨幅 · 60% · 高优");
|
||||
await expect(page.locator(".screener-results")).toContainText("分红样本");
|
||||
await page.locator(".strategy-items").getByRole("button", { name: /动态多因子/ }).click();
|
||||
await expect(page.locator(".screener-results")).toContainText("多因子样本");
|
||||
@@ -173,6 +201,12 @@ test("stage 9 screening preserves deterministic modes, explicit tracking and res
|
||||
await expect(page.getByRole("button", { name: "我的选股策略 第 2 版" })).toBeVisible();
|
||||
await expect(page.locator(".screener-results")).toContainText("自定义样本");
|
||||
await expect(page.locator(".screener-results")).not.toContainText("多因子样本");
|
||||
await expect(page.getByText(/小样本:当前7个有效样本/)).toBeVisible();
|
||||
await page.getByPlaceholder(/近20日走势较强/).fill("成交额至少3亿元,偏重20日走势");
|
||||
await page.getByRole("button", { name: "转换", exact: true }).click();
|
||||
await expect(page.getByRole("status")).toContainText("已转换为受控公式");
|
||||
await expect(page.locator(".factor-list input[type=number]").first()).toHaveValue("100");
|
||||
await expect(page.locator(".filter-list input[type=number]").first()).toHaveValue("3");
|
||||
await page.getByRole("button", { name: "夜间" }).click();
|
||||
await page.setViewportSize({ width: 390, height: 844 });
|
||||
expect(await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth)).toBeLessThanOrEqual(0);
|
||||
|
||||
Reference in New Issue
Block a user