fix(optimize): 策略切换时按策略参数自动填网格,避免 grid 不匹配

Optimize.vue 硬编码默认 grid 为 fast_window/slow_window(DoubleMa 参数),
切换策略不更新。选 DualThrust/AtrRsi 等策略时 grid 仍是 fast/slow_window,
参数对该策略无效 → 所有组合跑出完全相同结果(实证 opt_235fa738 DualThrust
24 组合 total_return 全=-0.0023, distinct=1/24)。

加 watch(form.strategy):切换时拉 /strategy/{name}/params,按 parameters+
defaults 以默认值为中心生成网格,保证参数名匹配策略。历史无效优化无法挽回。
This commit is contained in:
2026-07-17 15:33:03 +08:00
parent 65021bd32c
commit 4f0e3162b3
+33 -2
View File
@@ -1,8 +1,8 @@
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ref, reactive, onMounted, watch } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { getStrategies, type StrategyItem } from '@/api/strategy'
import { getStrategies, getParams, type StrategyItem } from '@/api/strategy'
import { submitOptimize } from '@/api/backtest'
const router = useRouter()
@@ -42,6 +42,37 @@ function parseGrid(): Record<string, [number, number, number]> | null {
return grid
}
/**
* 策略切换时按其自身参数自动填充网格,避免 grid 参数与策略不匹配。
* 否则如 DualThrust/AtrRsi 用了 DoubleMa 的 fast/slow_window(硬编码默认),
* 参数对该策略无效 → 所有组合跑出完全相同结果(历史 opt_235fa738 等 24 组合全相同)。
* 范围以参数默认值为中心,用户按需调整。
*/
async function loadGridForStrategy(name: string): Promise<void> {
if (!name) return
try {
const p = await getParams(name)
const lines: string[] = []
for (const pname of p.parameters) {
if (pname === 'vt_symbol') continue
const def = Number(p.defaults?.[pname])
if (!Number.isFinite(def)) continue
const step = Math.max(1, Math.round(Math.abs(def) / 10) || 1)
const start = Math.max(0, def - step)
const end = def + step
lines.push(`${pname},${start},${end},${step}`)
}
if (lines.length) {
form.gridText = lines.join('\n')
ElMessage.info(`已按 ${name} 参数填充网格,请按需调整范围`)
}
} catch {
// 拉取参数失败时保持用户当前网格
}
}
watch(() => form.strategy, (n) => { if (n) loadGridForStrategy(n) })
async function onSubmit(): Promise<void> {
const grid = parseGrid()
if (!grid) return