mirror of
https://ghfast.top/https://github.com/aeroxw/easy_tdx_max.git
synced 2026-09-12 15:44:18 +08:00
fix(web-ui): 参数寻优「查看」用寻优时的标的快照,避免输入框/路由切换污染 URL
- OptimizeView「查看」拼 URL 前从输入框实时值取 code/startDate/endDate/category, 导致两个问题:(1) 寻优后改输入框代码再点查看,URL 指向没回测过的标的; (2) 切走再回 /optimize,组件 ref 丢失,URL 里 symbol/startDate/endDate 全空。 - 将标的上下文快照(取行情成功那一刻冻结)下沉到 Pinia store 的 optimizeContext, 与 optimizeResult/optimizeAllResult 同生命周期持久化,跨路由保留。 - buildBacktestQuery 改读 store.optimizeContext,输入框改动与组件卸载都不再污染。
This commit is contained in:
@@ -18,6 +18,7 @@ import type {
|
|||||||
BacktestRequest,
|
BacktestRequest,
|
||||||
BacktestResult,
|
BacktestResult,
|
||||||
Bar,
|
Bar,
|
||||||
|
Category,
|
||||||
MultiStrategyBacktestRequest,
|
MultiStrategyBacktestRequest,
|
||||||
PortfolioBacktestRequest,
|
PortfolioBacktestRequest,
|
||||||
PortfolioResult,
|
PortfolioResult,
|
||||||
@@ -162,6 +163,21 @@ export const useBacktestStore = defineStore('backtest', () => {
|
|||||||
const optimizeResult = ref<OptimizeResult | null>(null)
|
const optimizeResult = ref<OptimizeResult | null>(null)
|
||||||
const optimizeRunning = ref(false)
|
const optimizeRunning = ref(false)
|
||||||
|
|
||||||
|
/** 寻优实际使用的标的上下文(取行情成功那一刻冻结)。
|
||||||
|
* 放在 store 而非组件里,是为了在用户切走再回 /optimize 时,「查看」按钮仍能拼出正确 URL
|
||||||
|
* —— 组件 ref 在卸载后丢失,而 store 与 optimizeResult 同生命周期保留。
|
||||||
|
* 由 OptimizeView 在 loadBars() 成功后通过 setOptimizeContext() 写入。 */
|
||||||
|
const optimizeContext = ref<{
|
||||||
|
code: string
|
||||||
|
category: Category
|
||||||
|
startDate: string
|
||||||
|
endDate: string
|
||||||
|
} | null>(null)
|
||||||
|
|
||||||
|
function setOptimizeContext(ctx: { code: string; category: Category; startDate: string; endDate: string }) {
|
||||||
|
optimizeContext.value = ctx
|
||||||
|
}
|
||||||
|
|
||||||
/** 提交寻优后台任务并轮询直到完成。 */
|
/** 提交寻优后台任务并轮询直到完成。 */
|
||||||
async function runOptimize(req: OptimizeBacktestRequest) {
|
async function runOptimize(req: OptimizeBacktestRequest) {
|
||||||
optimizeRunning.value = true
|
optimizeRunning.value = true
|
||||||
@@ -240,6 +256,7 @@ export const useBacktestStore = defineStore('backtest', () => {
|
|||||||
multiStrategyRunning,
|
multiStrategyRunning,
|
||||||
optimizeResult,
|
optimizeResult,
|
||||||
optimizeRunning,
|
optimizeRunning,
|
||||||
|
optimizeContext,
|
||||||
optimizeAllResult,
|
optimizeAllResult,
|
||||||
optimizeAllRunning,
|
optimizeAllRunning,
|
||||||
// getters
|
// getters
|
||||||
@@ -255,5 +272,6 @@ export const useBacktestStore = defineStore('backtest', () => {
|
|||||||
clearMultiStrategy,
|
clearMultiStrategy,
|
||||||
runOptimize,
|
runOptimize,
|
||||||
runOptimizeAll,
|
runOptimizeAll,
|
||||||
|
setOptimizeContext,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -66,6 +66,13 @@ async function onRun() {
|
|||||||
// 1. 先取行情
|
// 1. 先取行情
|
||||||
const ok = await symbolPicker.value?.loadBars()
|
const ok = await symbolPicker.value?.loadBars()
|
||||||
if (!ok) return
|
if (!ok) return
|
||||||
|
// 取行情成功 → 冻结本次寻优真正使用的标的上下文,供「查看」拼 URL(存 store,跨路由保留)
|
||||||
|
store.setOptimizeContext({
|
||||||
|
code: code.value,
|
||||||
|
category: category.value,
|
||||||
|
startDate: startDate.value,
|
||||||
|
endDate: endDate.value,
|
||||||
|
})
|
||||||
// 2. 校验寻优参数
|
// 2. 校验寻优参数
|
||||||
if (Object.keys(paramGrid.value).length === 0) {
|
if (Object.keys(paramGrid.value).length === 0) {
|
||||||
store.error = '请勾选至少 1 个参数并填入取值'
|
store.error = '请勾选至少 1 个参数并填入取值'
|
||||||
@@ -91,6 +98,13 @@ async function onRunAll() {
|
|||||||
// 1. 先取行情
|
// 1. 先取行情
|
||||||
const ok = await symbolPicker.value?.loadBars()
|
const ok = await symbolPicker.value?.loadBars()
|
||||||
if (!ok) return
|
if (!ok) return
|
||||||
|
// 取行情成功 → 冻结本次寻优真正使用的标的上下文,供「查看」拼 URL(存 store,跨路由保留)
|
||||||
|
store.setOptimizeContext({
|
||||||
|
code: code.value,
|
||||||
|
category: category.value,
|
||||||
|
startDate: startDate.value,
|
||||||
|
endDate: endDate.value,
|
||||||
|
})
|
||||||
// 2. 一键寻优
|
// 2. 一键寻优
|
||||||
await store.runOptimizeAll({
|
await store.runOptimizeAll({
|
||||||
cash: cash.value,
|
cash: cash.value,
|
||||||
@@ -99,16 +113,20 @@ async function onRunAll() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 「查看」跳转时,把当前标的 + 周期 + 日期范围一并塞进 query,
|
/** 「查看」跳转时,把本次寻优实际使用的标的 + 周期 + 日期范围一并塞进 query,
|
||||||
* 让回测页能完整复现寻优时的行情(而非只带策略参数)。 */
|
* 让回测页能完整复现寻优时的行情(而非只带策略参数)。
|
||||||
|
* 注意:必须读 store.optimizeContext(取行情成功时冻结),不能读输入框实时值 ——
|
||||||
|
* 否则寻优完成后改了输入框代码,「查看」URL 会被污染,指向一个根本没被回测过的标的;
|
||||||
|
* 且不能读组件 ref,否则切走再回 /optimize 时排名还在但上下文已丢失。 */
|
||||||
function buildBacktestQuery(strategyName: string, params: Record<string, number | string>) {
|
function buildBacktestQuery(strategyName: string, params: Record<string, number | string>) {
|
||||||
|
const ctx = store.optimizeContext
|
||||||
return {
|
return {
|
||||||
strategy: strategyName,
|
strategy: strategyName,
|
||||||
params: JSON.stringify(params),
|
params: JSON.stringify(params),
|
||||||
symbol: code.value,
|
symbol: ctx?.code ?? '',
|
||||||
startDate: startDate.value,
|
startDate: ctx?.startDate ?? '',
|
||||||
endDate: endDate.value,
|
endDate: ctx?.endDate ?? '',
|
||||||
category: category.value,
|
category: ctx?.category ?? category.value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user