feat(strategy): 策略实例做实P0+P1+策略库A+B混合布局(spec§12.6定稿)——实例=策略档案:①绑定:paper/live账户+回测任务加instance_id(paper_accounts/live_accounts ALTER迁移),发起即建档(无档案自动建),绑已有档案时D1发起快照(账户用档案参数复印件)②回写:事件型(回测_on_done/回放线程)落盘update_instance_run;持续型(实走/影子/实盘)读时聚合_instance_runtime(四格覆盖+在跑账户+漂移检测)③D2/D3同步:POST /paper/sync/{id}批量刷运行中模拟账户(实走+影子锁死一致),实盘不在线改参④D5删除保护409⑤P1全景:GET instances/{id}/overview(全部运行账户+净值尾部+合并持仓归因)收编挂起项「按实例归因持仓」⑥前端:策略库重做A+B混合(统计条+在跑巡检模式+左栏代码树中文主显/文件副行+档案区漂移角标/同步/全景;STRATEGY_LABELS抽共享常量),InstanceOverview抽屉(echarts净值对比+归因持仓表),模拟盘/实盘表单加实例档案下拉(选中预填+绑定,路由?instance=直进);mock层enriched/sync/overview(路由序enriched先于{id});+7绑定测试,921绿,build绿,dev浏览器验收过 [vps]
This commit is contained in:
@@ -401,6 +401,43 @@ export const strategyInstancesMock: { instances: StrategyInstance[] } = {
|
||||
],
|
||||
}
|
||||
|
||||
/* §12.6 实例做实:enriched(读时聚合)与全景 overview mock */
|
||||
export interface RunningAccountMock {
|
||||
kind: 'paper' | 'shadow' | 'live'
|
||||
aid: number
|
||||
label: string
|
||||
ret: number | null
|
||||
drifted?: boolean
|
||||
}
|
||||
export const strategyInstancesEnrichedMock = {
|
||||
instances: (strategyInstancesMock.instances as Array<StrategyInstance & { running_accounts?: RunningAccountMock[]; drift?: boolean }>).map((i) => ({
|
||||
...i,
|
||||
running_accounts: i.status.paper_live === 'running'
|
||||
? [{ kind: 'paper', aid: 101, label: i.name, ret: i.last_return }]
|
||||
: (i.status.live === 'running'
|
||||
? [{ kind: 'live', aid: 201, label: `${i.name}·live`, ret: i.last_return }]
|
||||
: []),
|
||||
drift: i.id === 2,
|
||||
})),
|
||||
}
|
||||
|
||||
export function instanceOverviewMock(id: number) {
|
||||
const inst = strategyInstancesMock.instances.find((i) => i.id === id) || strategyInstancesMock.instances[0]
|
||||
const days = ['07-20', '07-21', '07-22', '07-23', '07-24', '07-25', '07-26', '07-27', '07-28']
|
||||
const mk = (base: number, drift: number) => days.map((d, k) => ({ date: d, equity: Math.round(base * (1 + 0.002 * k * drift + (k % 3) * 0.001 * drift)) }))
|
||||
return {
|
||||
instance: { ...inst },
|
||||
runs: [
|
||||
{ kind: 'paper', aid: 101, label: inst.name, mode: 'live', status: 'running', ret: inst.last_return, equity: mk(1_000_000, 1) },
|
||||
{ kind: 'shadow', aid: 102, label: `${inst.name}·影子`, mode: 'shadow', status: 'running', ret: (inst.last_return || 0) - 0.001, equity: mk(1_000_000, 0.98) },
|
||||
],
|
||||
positions: [
|
||||
{ symbol: '600000', volume: 2000, avg_price: 10.52, accounts: [{ label: inst.name, volume: 2000 }] },
|
||||
{ symbol: '600519', volume: 100, avg_price: 1480.0, accounts: [{ label: `${inst.name}·影子`, volume: 100 }] },
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
/* ========== 因子 factor ========== */
|
||||
export const factorListMock = {
|
||||
factors: [
|
||||
|
||||
@@ -20,9 +20,13 @@ const routes: Route[] = [
|
||||
{ m: 'get', re: /^\/strategy\/list$/, build: () => D.strategiesMock },
|
||||
// strategy instances(实例层 · 代码下参数变体)
|
||||
{ m: 'get', re: /^\/strategy\/instances$/, build: () => D.strategyInstancesMock },
|
||||
// enriched 必须排在单实例正则之前(否则 /instances/enriched 被当 {id} 吞)
|
||||
{ m: 'get', re: /^\/strategy\/instances\/enriched$/, build: () => D.strategyInstancesEnrichedMock },
|
||||
{ m: 'get', re: /^\/strategy\/instances\/[^/]+\/overview$/, build: (url) => D.instanceOverviewMock(Number(url.split('/')[3])) },
|
||||
{ m: 'get', re: /^\/strategy\/instances\/[^/]+$/, build: (url) => { const id = Number(url.split('/')[3]); const inst = D.strategyInstancesMock.instances.find((i) => i.id === id); return { instance: inst ?? D.strategyInstancesMock.instances[0] } } },
|
||||
{ m: 'post', re: /^\/strategy\/instances$/, build: () => ({ id: 99 }) },
|
||||
{ m: 'delete', re: /^\/strategy\/instances\/[^/]+$/, build: () => ({ ok: true }) },
|
||||
{ m: 'post', re: /^\/paper\/sync\/[^/]+$/, build: () => ({ synced: 2 }) },
|
||||
// strategy code files(在线编辑)
|
||||
{ m: 'get', re: /^\/strategy\/files$/, build: () => D.strategyFilesMock },
|
||||
{ m: 'post', re: /^\/strategy\/file\/[^/]+\/check$/, build: () => ({ ok: true }) },
|
||||
|
||||
Reference in New Issue
Block a user