加入股汇参数和相应逻辑
This commit is contained in:
parent
5fb030135e
commit
46fc6a8da1
|
|
@ -74,6 +74,10 @@
|
||||||
3. 月度复盘:数据多一段就重跑标定脚本,校准阈值与 S0/k。
|
3. 月度复盘:数据多一段就重跑标定脚本,校准阈值与 S0/k。
|
||||||
4. check_db 表清单缺 pms_strategy 与 pms_op_log 的既有欠账,单独提。
|
4. check_db 表清单缺 pms_strategy 与 pms_op_log 的既有欠账,单独提。
|
||||||
|
|
||||||
|
**同日修订(2026-08-19,桥机判收后两条)**
|
||||||
|
一,判收补记。桥机 make test 与建表全部通过。dry_run 试算返回 +14.7197、区域中性,与标定报告同日值一致,方案第六节的前四步完成。宿主机的 python3 版本旧,不认 json.tool 的 --no-ensure-ascii 参数,去掉该参数即可,不是系统问题。
|
||||||
|
二,前端改版(用户要求:不占大块,放页面第一行)。撤掉「宏观择时」大面板,改为首行一枚紧凑徽标,与市场、买入、执行、自主、计划等徽标并排。常态显示指数值与区域;有建议、闸生效或数据不可用时转警示色;有建议时徽标显示"有建议",点击即走采纳确认。全部详情移进鼠标悬浮提示:近二十日迷你走势、阈值与档位、闸状态、建议卡带采纳按钮、最近宏观命令;运维模式下悬浮里另有试算与立即扫描两个按钮。偏热闸与数据不可用两条横幅保留。无头渲染判收九项全过、零页面错误(徽标带值、有建议标记、大面板已删、悬浮里建议卡/采纳按钮/二十根迷你条/最近命令/闸说明、横幅仍在)。改动只有 index.html 一个文件,回滚还原它即可;改的是前端资源,生效仍需 make deploy 重建镜像。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2026-08-18 · 决策系统卖出采纳复核:降门槛+全留痕 / 确认即加速 / 清仓完成清场
|
## 2026-08-18 · 决策系统卖出采纳复核:降门槛+全留痕 / 确认即加速 / 清仓完成清场
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,6 @@ pre.json{background:var(--surface-2);border:1px solid var(--hair);border-radius:
|
||||||
.mz-bars{display:flex;align-items:flex-end;gap:2px;height:34px;margin:7px 0 3px;}
|
.mz-bars{display:flex;align-items:flex-end;gap:2px;height:34px;margin:7px 0 3px;}
|
||||||
.mz-bar{width:9px;border-radius:2px;min-height:3px;opacity:.9;}
|
.mz-bar{width:9px;border-radius:2px;min-height:3px;opacity:.9;}
|
||||||
.mz-zone{padding:1px 9px;border-radius:9px;font-size:12px;font-weight:600;color:#fff;}
|
.mz-zone{padding:1px 9px;border-radius:9px;font-size:12px;font-weight:600;color:#fff;}
|
||||||
.mz-advice{margin:7px 0;padding:8px 11px;border:1px solid var(--warn);border-radius:9px;display:flex;gap:10px;align-items:center;flex-wrap:wrap;}
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -199,6 +198,40 @@ pre.json{background:var(--surface-2);border:1px solid var(--hair);border-radius:
|
||||||
<span class="chip" :class="ov.exec_halt?'warn':'ok'"><span class="dot"></span>执行 {{ ov.exec_halt ? '已暂停':'正常' }}</span>
|
<span class="chip" :class="ov.exec_halt?'warn':'ok'"><span class="dot"></span>执行 {{ ov.exec_halt ? '已暂停':'正常' }}</span>
|
||||||
<span class="chip" :class="ov.autonomy==='off'?'warn':'ok'"><span class="dot"></span>自主 {{ tx('autonomy', ov.autonomy) }}<span class="help" data-tip="系统自己出手的程度:全自动=闸门通过就执行;只提议=等你在『等我拍板』确认;暂停=不自动动作。">?</span></span>
|
<span class="chip" :class="ov.autonomy==='off'?'warn':'ok'"><span class="dot"></span>自主 {{ tx('autonomy', ov.autonomy) }}<span class="help" data-tip="系统自己出手的程度:全自动=闸门通过就执行;只提议=等你在『等我拍板』确认;暂停=不自动动作。">?</span></span>
|
||||||
<span class="chip" :class="planStatus.ok===false?'warn':'ok'"><span class="dot"></span>计划 {{ planStatus.ok===false ? '不可用' : (planStatus.date || '-') }}</span>
|
<span class="chip" :class="planStatus.ok===false?'warn':'ok'"><span class="dot"></span>计划 {{ planStatus.ok===false ? '不可用' : (planStatus.date || '-') }}</span>
|
||||||
|
<el-tooltip placement="bottom-start" effect="light" :show-after="120">
|
||||||
|
<template #content>
|
||||||
|
<div style="max-width:360px;font-size:12px;line-height:1.75">
|
||||||
|
<template v-if="macro.enabled===false"><b>宏观择时未启用</b><div class="muted">总开关 PMS_MACRO_ENABLED 在「参数设置」里打开</div></template>
|
||||||
|
<template v-else-if="!mzSig"><b>宏观择时</b>:暂无信号数据(还没扫描过;调度位在交易日 09:35)</template>
|
||||||
|
<template v-else>
|
||||||
|
<div><b>{{ mzSig.label }}</b>
|
||||||
|
<span class="mono" style="font-weight:700" :style="{color: mzColor(mzSig.zone)}">{{ mzSig.value==null ? '—' : (mzSig.value>0?'+':'') + Number(mzSig.value).toFixed(1) }}</span>
|
||||||
|
<span class="mz-zone" :style="{background: mzColor(mzSig.zone)}">{{ mzLabel(mzSig.zone) }}</span>
|
||||||
|
<span class="muted" v-if="mzSig.ymd"> {{ mzSig.ymd }}</span></div>
|
||||||
|
<div class="muted" v-if="mzSig.e_now>0">超额深度 {{ mzSig.e_now }}<template v-if="mzSig.streak"> · 区内第 {{ mzSig.streak }} 天</template></div>
|
||||||
|
<div class="muted" v-if="mzSig.note">{{ mzSig.note }}</div>
|
||||||
|
<div class="mz-bars" v-if="(mzSig.history||[]).length">
|
||||||
|
<span v-for="(h,i) in mzSig.history" :key="i" class="mz-bar" :style="mzBarStyle(h)"
|
||||||
|
:title="h.ymd + ' · ' + (h.value==null ? '不可用' : h.value) + ' · ' + mzLabel(h.zone)"></span>
|
||||||
|
</div>
|
||||||
|
<div class="muted" style="font-size:11px">近 {{ (mzSig.history||[]).length }} 个交易日 · 热 +{{ (macro.params||{}).hot_th }} / 冷 {{ (macro.params||{}).cold_th }} / 退出带 ±{{ (macro.params||{}).exit_band }} · 档位 {{ macro.autonomy==='full' ? '全自动' : (macro.autonomy==='propose_only' ? '只出建议' : '只算不动') }}</div>
|
||||||
|
<div v-if="macroGateOn" style="color:var(--warn)">偏热闸生效中:系统自主买入与策略买开腿已暂停(你的命令不受影响)</div>
|
||||||
|
<div v-if="mzSig.advice && !mzSig.advice.adopted" style="margin-top:4px">
|
||||||
|
<b>今日建议:{{ mzSig.advice.direction==='REDUCE' ? '降仓' : '升仓' }} {{ (mzSig.advice.pct*100).toFixed(1) }}%</b>
|
||||||
|
<button class="tbtn pri" style="margin-left:8px" @click="macroAdopt(mzSig.key)">采纳并下命令</button>
|
||||||
|
<div class="muted" style="font-size:11px">{{ mzSig.advice.why }} · 当日有效,隔日作废</div>
|
||||||
|
</div>
|
||||||
|
<div class="muted" v-if="mzSig.last_command" style="font-size:11px">最近宏观命令 {{ mzSig.last_command.command_id }} · {{ mzSig.last_command.cmd_type==='REDUCE_EXPOSURE' ? '降仓' : '升仓' }} · {{ mzSig.last_command.status }}</div>
|
||||||
|
<div v-show="mode==='ops'" style="margin-top:5px">
|
||||||
|
<button class="tbtn" @click="macroScan(true)">试算</button>
|
||||||
|
<button class="tbtn" @click="macroScan(false)">立即扫描</button>
|
||||||
|
</div>
|
||||||
|
<div style="color:var(--warn)" v-if="mzSig.error">读取失败: {{ mzSig.error }}</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<span class="chip" :class="mzChipCls" :style="mzAdvicePending ? 'cursor:pointer' : ''" @click="macroChipClick"><span class="dot"></span>宏观 {{ mzChipText }}</span>
|
||||||
|
</el-tooltip>
|
||||||
<span class="chip" :class="dm.shadow?'idle':'ok'" v-show="mode==='ops'"><span class="dot"></span>下发 {{ dm.mode || '-' }}<span class="help" data-tip="实盘=真发到 QMT 下单;影子=只记录不真下单,用来观察。">?</span></span>
|
<span class="chip" :class="dm.shadow?'idle':'ok'" v-show="mode==='ops'"><span class="dot"></span>下发 {{ dm.mode || '-' }}<span class="help" data-tip="实盘=真发到 QMT 下单;影子=只记录不真下单,用来观察。">?</span></span>
|
||||||
<div class="spacer"></div>
|
<div class="spacer"></div>
|
||||||
<div class="seg">
|
<div class="seg">
|
||||||
|
|
@ -262,44 +295,6 @@ pre.json{background:var(--surface-2);border:1px solid var(--hair);border-radius:
|
||||||
<span class="muted" style="font-size:11.5px;cursor:pointer" @click="showUpstream=true">下方查看全部 ▾</span>
|
<span class="muted" style="font-size:11.5px;cursor:pointer" @click="showUpstream=true">下方查看全部 ▾</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 宏观择时 (MACRO_TIMING_PLAN.md): 股汇对冲指数管整体仓位; 参数在「参数设置」PMS_MACRO_* -->
|
|
||||||
<div class="panel tblk">
|
|
||||||
<h3>宏观择时 <span class="muted" style="font-weight:400">· 股汇对冲指数 → 整体仓位</span>
|
|
||||||
<span v-if="macro.enabled===false" class="muted" style="font-size:12px;font-weight:normal">(总开关关闭, 只展示不动作)</span>
|
|
||||||
<span v-else-if="macro.autonomy" class="muted" style="font-size:12px;font-weight:normal">(档位 {{ macro.autonomy==='full' ? '全自动' : (macro.autonomy==='propose_only' ? '只出建议' : '只算不动') }})</span>
|
|
||||||
</h3>
|
|
||||||
<div v-for="s in (macro.signals||[])" :key="s.key" style="margin-bottom:6px">
|
|
||||||
<div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap">
|
|
||||||
<b>{{ s.label }}</b>
|
|
||||||
<span class="mono" style="font-size:21px;font-weight:700" :style="{color: mzColor(s.zone)}">{{ s.value==null ? '—' : (s.value>0?'+':'') + Number(s.value).toFixed(1) }}</span>
|
|
||||||
<span class="mz-zone" :style="{background: mzColor(s.zone)}">{{ mzLabel(s.zone) }}</span>
|
|
||||||
<span class="muted" v-if="s.e_now>0">超额深度 {{ s.e_now }}</span>
|
|
||||||
<span class="muted" v-if="s.streak">区内第 {{ s.streak }} 天</span>
|
|
||||||
<span class="muted" v-if="s.inflight">宏观命令在途</span>
|
|
||||||
<span class="muted" v-if="s.ymd" style="font-size:11.5px">{{ s.ymd }}</span>
|
|
||||||
<div class="spacer"></div>
|
|
||||||
<button class="tbtn" v-show="mode==='ops'" @click="macroScan(true)">试算</button>
|
|
||||||
<button class="tbtn" v-show="mode==='ops'" @click="macroScan(false)">立即扫描</button>
|
|
||||||
</div>
|
|
||||||
<div class="mz-bars" v-if="(s.history||[]).length">
|
|
||||||
<span v-for="(h,i) in s.history" :key="i" class="mz-bar"
|
|
||||||
:title="h.ymd + ' · ' + (h.value==null ? '不可用' : h.value) + ' · ' + mzLabel(h.zone)"
|
|
||||||
:style="mzBarStyle(h)"></span>
|
|
||||||
</div>
|
|
||||||
<div class="muted" style="font-size:11.5px" v-if="(s.history||[]).length">近 {{ s.history.length }} 个交易日 · 热区阈值 +{{ (macro.params||{}).hot_th }} / 冷区 {{ (macro.params||{}).cold_th }} / 退出带 ±{{ (macro.params||{}).exit_band }}</div>
|
|
||||||
<div v-if="s.advice && !s.advice.adopted" class="mz-advice">
|
|
||||||
<b>今日建议:{{ s.advice.direction==='REDUCE' ? '降仓' : '升仓' }} {{ (s.advice.pct*100).toFixed(1) }}%</b>
|
|
||||||
<span class="muted">{{ s.advice.why }}</span>
|
|
||||||
<button class="tbtn pri" @click="macroAdopt(s.key)">采纳并下命令</button>
|
|
||||||
<span class="muted" style="font-size:11.5px">当日有效, 隔日自动作废</span>
|
|
||||||
</div>
|
|
||||||
<div class="muted" v-if="s.note" style="font-size:12px">{{ s.note }}</div>
|
|
||||||
<div class="muted" v-if="s.last_command" style="font-size:12px">最近宏观命令 {{ s.last_command.command_id }} · {{ s.last_command.cmd_type==='REDUCE_EXPOSURE' ? '降仓' : '升仓' }} · {{ s.last_command.status }}<template v-if="s.last_command.target_amount"> · 进度 {{ money(s.last_command.done_amount||0) }} / {{ money(s.last_command.target_amount) }}</template></div>
|
|
||||||
<div style="color:var(--warn)" v-if="s.error">读取失败: {{ s.error }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="muted" v-if="!(macro.signals||[]).length">暂无信号数据(还没扫描过, 或宏观层未启用)</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 7) 上游信号 (只读参考) -->
|
<!-- 7) 上游信号 (只读参考) -->
|
||||||
<div class="panel tblk">
|
<div class="panel tblk">
|
||||||
<h3 style="cursor:pointer" @click="showUpstream=!showUpstream">上游信号 <span class="muted" style="font-weight:400">· 只读参考,不进下单逻辑</span> <span class="muted" style="font-size:12px;font-weight:normal">{{ showUpstream?'▲ 收起':'▼ 展开' }}</span></h3>
|
<h3 style="cursor:pointer" @click="showUpstream=!showUpstream">上游信号 <span class="muted" style="font-weight:400">· 只读参考,不进下单逻辑</span> <span class="muted" style="font-size:12px;font-weight:normal">{{ showUpstream?'▲ 收起':'▼ 展开' }}</span></h3>
|
||||||
|
|
@ -2154,6 +2149,29 @@ createApp({
|
||||||
ElementPlus.ElMessage[(d && d.ok) ? 'success' : 'error']((d && d.ok) ? ('已下达 ' + (d.command_id || '')) : ((d && d.error) || '采纳失败'));
|
ElementPlus.ElMessage[(d && d.ok) ? 'success' : 'error']((d && d.ok) ? ('已下达 ' + (d.command_id || '')) : ((d && d.error) || '采纳失败'));
|
||||||
await Promise.all([loadMacro(), loadCommands()]);
|
await Promise.all([loadMacro(), loadCommands()]);
|
||||||
}
|
}
|
||||||
|
// 首行徽标 (2026-08-19 用户要求由大面板改为首行紧凑显示, 详情进悬浮提示)
|
||||||
|
const mzSig = computed(() => (((macro.value || {}).signals) || [])[0] || null);
|
||||||
|
const mzAdvicePending = computed(() => { const s = mzSig.value; return !!(s && s.advice && !s.advice.adopted); });
|
||||||
|
const mzChipCls = computed(() => {
|
||||||
|
const m = macro.value || {};
|
||||||
|
if (m.enabled === false) return 'idle';
|
||||||
|
const s = mzSig.value;
|
||||||
|
if (!s) return 'idle';
|
||||||
|
if (mzAdvicePending.value || macroGateOn.value || s.zone === 'UNAVAILABLE') return 'warn';
|
||||||
|
return 'ok';
|
||||||
|
});
|
||||||
|
const mzChipText = computed(() => {
|
||||||
|
const m = macro.value || {};
|
||||||
|
if (m.enabled === false) return '未启用';
|
||||||
|
const s = mzSig.value;
|
||||||
|
if (!s) return '—';
|
||||||
|
if (s.zone === 'UNAVAILABLE') return '数据不可用';
|
||||||
|
const v = s.value == null ? '—' : ((s.value > 0 ? '+' : '') + Number(s.value).toFixed(1));
|
||||||
|
let t = v + ' ' + mzLabel(s.zone);
|
||||||
|
if (mzAdvicePending.value) t += ' · 有建议';
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
function macroChipClick() { if (mzAdvicePending.value && mzSig.value) macroAdopt(mzSig.value.key); }
|
||||||
|
|
||||||
async function loadUpstream() {
|
async function loadUpstream() {
|
||||||
const d = await call('get', '/api/upstream-signals');
|
const d = await call('get', '/api/upstream-signals');
|
||||||
|
|
@ -2433,6 +2451,7 @@ createApp({
|
||||||
upstream, showUpstream, usrc, loadUpstream,
|
upstream, showUpstream, usrc, loadUpstream,
|
||||||
macro, macroGateOn, macroUnavailable, mzLabel, mzColor, mzBarStyle,
|
macro, macroGateOn, macroUnavailable, mzLabel, mzColor, mzBarStyle,
|
||||||
loadMacro, macroScan, macroAdopt,
|
loadMacro, macroScan, macroAdopt,
|
||||||
|
mzSig, mzAdvicePending, mzChipCls, mzChipText, macroChipClick,
|
||||||
showAlerts, alertItems, alertLatest, alertLevelClass, alertGroups, alertStripItems,
|
showAlerts, alertItems, alertLatest, alertLevelClass, alertGroups, alertStripItems,
|
||||||
alertStripCount, alertTotalCount, catShown, toggleCat, ageText, alertRowClass,
|
alertStripCount, alertTotalCount, catShown, toggleCat, ageText, alertRowClass,
|
||||||
alertItemsF, levelShown, toggleLevel, levelCount, ALERT_LEVELS, lvLabel, lvClass, alertGridFixed, passLevel, flowText, flowClass,
|
alertItemsF, levelShown, toggleLevel, levelCount, ALERT_LEVELS, lvLabel, lvClass, alertGridFixed, passLevel, flowText, flowClass,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue