Files
easy_tdx_max/web-ui/scripts/run-grading-tests.mjs
T
Justin Gu cf843cebad release: v1.17.14 — Web UI 数据评级系统(S/A/B/C/D 五档,三入口覆盖)
纯前端 TypeScript 实现,零后端改动。回测/组合/寻优三处结果顶部
显示评级徽章,让普通人 1 秒判断「适不适合经常参与」。

评级不看收益率(避免被近期大涨误导),只看风险调整后的持有体验:
卡玛/最大回撤/胜率/利润因子/夏普/波动率六维加权 + 一票否决。
京东方「收益 126% 但胜率 35%」案例 = D 档(核心验证点)。

长线低频策略(6年6笔)不会被冤枉:交易<10笔时只降权胜率/利润因子
维度,不否决整个评级(修复用户实测反馈)。

- 新增 web-ui/src/grading/ 核心模块(engine/thresholds/combinedMetrics/index)
- 新增 GradeBadge.vue + GradeDetails.vue 组件
- 接入 BacktestView/PortfolioView/OptimizeView(寻优排名表加评级列)
- 15 个自检测试(node:test + rolldown 打包),覆盖京东方 D / 长线 B 等场景
2026-07-05 01:21:18 +08:00

51 lines
1.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 把评级测试入口打包成单文件 JS,再用 node:test 跑。
*
* 项目未引入 vitest/jest,临时用 rolldownvite 自带依赖)打包,
* 避免 Node 原生 strip-types 对 ESM 无后缀 import 的限制。
*
* 运行:node scripts/run-grading-tests.mjs
*/
import { build } from 'rolldown'
import { mkdtempSync, writeFileSync, rmSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join, resolve } from 'node:path'
import { spawnSync } from 'node:child_process'
const tmpDir = mkdtempSync(join(tmpdir(), 'grading-tests-'))
const bundlePath = join(tmpDir, 'bundle.mjs')
// 入口:导入测试文件,触发 node:test 注册
const entryPath = join(tmpDir, 'entry.mjs')
writeFileSync(
entryPath,
`import '${resolve('src/grading/__tests__/grade.test.ts').replace(/\\/g, '/')}'\n`,
)
console.log('→ 打包中…')
try {
await build({
input: entryPath,
output: {
file: bundlePath,
format: 'esm',
},
// 顶层 await / dynamic import 都 OK
platform: 'node',
// 不外部化 node 内置
external: ['node:test', 'node:assert', 'node:assert/strict', 'node:os', 'node:fs', 'node:path', 'node:child_process'],
// 强制把测试文件和 grading 模块都打进 bundle
treeshake: false,
})
} catch (e) {
console.error('打包失败:', e)
process.exit(1)
}
console.log('→ 运行测试…')
const r = spawnSync('node', ['--test', bundlePath], { stdio: 'inherit' })
rmSync(tmpDir, { recursive: true, force: true })
process.exit(r.status ?? 0)