mirror of
https://github.com/shy3130/tick-stock-panel.git
synced 2026-11-02 10:26:13 +00:00
refactor(ui): 分区命名统一 —「纪律与触发」改为「风控触发」(弹窗+回测抽屉+测试+文档)
This commit is contained in:
+1
-1
@@ -62,7 +62,7 @@
|
||||
|
||||
**因子与策略挖掘**:复用已有日频因子和 matrix-native 策略,通过 T-1 市场环境、相关去重和嵌套样本外验证生成研究候选。任务在 spawn worker 中运行,支持持久 run ID、取消、刷新重连和显式发布;自动周度任务默认关闭且永不自动发布。完整口径见 [因子与策略挖掘](./mining.md)。
|
||||
|
||||
**策略设置统一**:回测页「高级策略设置」抽屉与策略页设置弹窗采用同一信息架构(策略条件 / 策略权重 / 纪律与触发 / 回测范围)。风控与持仓纪律(止损 · 止盈 · 移动止损 · 回撤止盈 · 最长持仓)以策略设置保存的值为默认,回测抽屉内可临时覆盖,也可「应用到策略」持久化;策略页保存的叠加条件随回测请求继承,与扫描 / 监控同一口径;回测范围(资产类型 / 股票池)为回测专属概念。
|
||||
**策略设置统一**:回测页「高级策略设置」抽屉与策略页设置弹窗采用同一信息架构(策略条件 / 策略权重 / 风控触发 / 回测范围)。风控与持仓纪律(止损 · 止盈 · 移动止损 · 回撤止盈 · 最长持仓)以策略设置保存的值为默认,回测抽屉内可临时覆盖,也可「应用到策略」持久化;策略页保存的叠加条件随回测请求继承,与扫描 / 监控同一口径;回测范围(资产类型 / 股票池)为回测专属概念。
|
||||
|
||||
**市场阶段与主线**:市场环境页在原 5 档状态之外新增情绪周期阶段(冰点/启动/主升/高潮/退潮/修复,由连板梯队的高度、宽度、晋级率、梯队完整度判定,平均段长约 10 天)与主线识别(概念/行业维度的涨停梯队聚合排名,可配置宽基标签过滤)。完整口径见 [市场阶段与主线识别](./market-phase.md)。
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ it('renders section nav with 策略条件 page active by default', async () => {
|
||||
|
||||
expect(container.textContent).toContain('策略条件')
|
||||
expect(container.textContent).toContain('策略权重')
|
||||
expect(container.textContent).toContain('纪律与触发')
|
||||
expect(container.textContent).toContain('风控触发')
|
||||
expect(container.textContent).toContain('基础参数')
|
||||
expect(container.textContent).toContain('叠加条件')
|
||||
// 默认页可见, 其他分区隐藏 (常驻挂载避免编辑草稿丢失)
|
||||
@@ -134,14 +134,14 @@ it('switches pages through the nav rail', async () => {
|
||||
expect(pageHidden('对通过筛选的候选按因子加权打分排序')).toBe(false)
|
||||
expect(pageHidden('决定哪些股票进入候选')).toBe(true)
|
||||
|
||||
act(() => { findButton('纪律与触发').click() })
|
||||
act(() => { findButton('风控触发').click() })
|
||||
expect(pageHidden('控制买卖时点')).toBe(false)
|
||||
expect(pageHidden('对通过筛选的候选按因子加权打分排序')).toBe(true)
|
||||
})
|
||||
|
||||
it('shows unsaved-change hint on edit and clears it when reverted', async () => {
|
||||
await render()
|
||||
act(() => { findButton('纪律与触发').click() })
|
||||
act(() => { findButton('风控触发').click() })
|
||||
|
||||
const stopLabel = [...container.querySelectorAll('span')].find(s => s.textContent === '止损')!
|
||||
const stopInput = stopLabel.parentElement!.querySelector('input[type="number"]') as HTMLInputElement
|
||||
@@ -151,7 +151,7 @@ it('shows unsaved-change hint on edit and clears it when reverted', async () =>
|
||||
|
||||
setNumberInput(stopInput, '9')
|
||||
expect(container.textContent).toContain('有未保存的改动')
|
||||
const navBtn = [...container.querySelectorAll('nav button')].find(b => b.textContent?.includes('纪律与触发'))!
|
||||
const navBtn = [...container.querySelectorAll('nav button')].find(b => b.textContent?.includes('风控触发'))!
|
||||
expect(navBtn.querySelector('.bg-amber-400')).toBeTruthy()
|
||||
|
||||
setNumberInput(stopInput, '8')
|
||||
@@ -161,7 +161,7 @@ it('shows unsaved-change hint on edit and clears it when reverted', async () =>
|
||||
|
||||
it('trading page exposes full risk fields and save carries them', async () => {
|
||||
await render()
|
||||
act(() => { findButton('纪律与触发').click() })
|
||||
act(() => { findButton('风控触发').click() })
|
||||
|
||||
// 与回测抽屉同构的 6 项纪律字段
|
||||
for (const label of ['止损', '止盈', '移动止损', '回撤止盈启动', '回撤止盈回撤', '最长持仓']) {
|
||||
@@ -189,7 +189,7 @@ it('trading page exposes full risk fields and save carries them', async () => {
|
||||
|
||||
it('drawdown clamps to activate value (与回测抽屉同联动)', async () => {
|
||||
await render()
|
||||
act(() => { findButton('纪律与触发').click() })
|
||||
act(() => { findButton('风控触发').click() })
|
||||
|
||||
const taLabel = [...container.querySelectorAll('span')].find(s => s.textContent === '回撤止盈启动')!
|
||||
const tdLabel = [...container.querySelectorAll('span')].find(s => s.textContent === '回撤止盈回撤')!
|
||||
|
||||
@@ -531,7 +531,7 @@ export function StrategySettingsDialog({ strategyId, onClose, onSaved, onAiModif
|
||||
: [
|
||||
{ id: 'screen' as const, label: '策略条件', icon: Filter, accent: 'text-sky-400' },
|
||||
{ id: 'scoring' as const, label: '策略权重', icon: Star, accent: 'text-amber-400' },
|
||||
{ id: 'trading' as const, label: '纪律与触发', icon: TrendingUp, accent: 'text-emerald-400' },
|
||||
{ id: 'trading' as const, label: '风控触发', icon: TrendingUp, accent: 'text-emerald-400' },
|
||||
]
|
||||
}, [detail, isComposite])
|
||||
|
||||
@@ -771,7 +771,7 @@ export function StrategySettingsDialog({ strategyId, onClose, onSaved, onAiModif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 纪律与触发 */}
|
||||
{/* 风控触发 */}
|
||||
<div className={page === 'trading' ? PAGE_ANIM : 'hidden'}>
|
||||
<div className="space-y-3">
|
||||
<p className="text-[11px] leading-5 text-muted/70">控制买卖时点:出入场触发器对回测与监控生效(任一命中即触发);策略扫描不消费触发器,仍按策略自身规则。风控与持仓纪律作为策略默认值保存,回测 / 优化 / 走查打开时自动继承。</p>
|
||||
|
||||
@@ -194,7 +194,7 @@ const BASIC_FILTER_RANGES = [
|
||||
{ minKey: 'turnover_min', maxKey: 'turnover_max', label: '换手率', unit: '%', step: '0.5' },
|
||||
]
|
||||
// 高级设置分区 — 与策略设置弹窗 (StrategySettingsDialog) 同一信息架构:
|
||||
// 策略条件(基础过滤+参数+叠加) / 策略权重 / 纪律与触发(风控+买卖触发) / 回测范围。
|
||||
// 策略条件(基础过滤+参数+叠加) / 策略权重 / 风控触发(风控+买卖触发) / 回测范围。
|
||||
// 回测抽屉编辑的是本次回测的 overrides, 策略弹窗编辑的是策略定义; 字段与口径两边一致。
|
||||
type AdvancedSettingsTab = 'conditions' | 'scoring' | 'trading' | 'range'
|
||||
type StrategyGroup = 'all' | 'custom' | 'ai' | 'composite'
|
||||
@@ -207,7 +207,7 @@ const STRATEGY_GROUPS: { id: StrategyGroup; label: string }[] = [
|
||||
const ADVANCED_TABS: { id: AdvancedSettingsTab; label: string; icon: typeof Filter }[] = [
|
||||
{ id: 'conditions', label: '策略条件', icon: Filter },
|
||||
{ id: 'scoring', label: '策略权重', icon: Star },
|
||||
{ id: 'trading', label: '纪律与触发', icon: TrendingUp },
|
||||
{ id: 'trading', label: '风控触发', icon: TrendingUp },
|
||||
{ id: 'range', label: '回测范围', icon: CalendarRange },
|
||||
]
|
||||
const toSignalId = (sig: string) => (sig.startsWith('signal_') || sig.startsWith('csg_')) ? sig : `signal_${sig}`
|
||||
@@ -3015,7 +3015,7 @@ export function StrategyBacktest({ loadCandidate, onLoadConsumed }: {
|
||||
</ConfigSection>
|
||||
</div>
|
||||
|
||||
{/* 纪律与触发: 成交口径说明 + 风控与持仓纪律 + 买卖触发器 */}
|
||||
{/* 风控触发: 成交口径说明 + 风控与持仓纪律 + 买卖触发器 */}
|
||||
<div className={settingsTab === 'trading' ? 'space-y-3' : 'hidden'}>
|
||||
<div className="rounded-btn border border-accent/25 bg-accent/5 px-3 py-2.5 text-[11px] leading-5 text-secondary">
|
||||
<div className="font-medium text-foreground">触发 / 成交 / 仓位关系</div>
|
||||
|
||||
Reference in New Issue
Block a user