优化三层打分模型:短期引入幅度因子与量能确认,中期资金信号连续化,长期加入价格维度,新增波动率调整
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,11 @@ export interface ShortDetail {
|
||||
oi: number
|
||||
oi_chg: number
|
||||
score: number
|
||||
oi_chg_pct: number
|
||||
price_chg_pct: number
|
||||
vol: number
|
||||
vol_ratio: number
|
||||
quadrant: string
|
||||
}
|
||||
|
||||
export interface MediumDetail {
|
||||
@@ -15,18 +20,31 @@ export interface MediumDetail {
|
||||
long_up_days: number
|
||||
long_down_days: number
|
||||
fund_signal: number
|
||||
window: number
|
||||
}
|
||||
|
||||
export interface LongDetail {
|
||||
avg_oi: number
|
||||
oi_before: number
|
||||
change_pct: number
|
||||
oi_score: number
|
||||
price_score: number
|
||||
price_return_30d_pct: number
|
||||
price_before_30d: number
|
||||
window: number
|
||||
}
|
||||
|
||||
export interface VolatilityDetail {
|
||||
daily_vol_pct: number
|
||||
atr_pct: number
|
||||
vol_penalty: number
|
||||
}
|
||||
|
||||
export interface ScoreDetail {
|
||||
short_details?: ShortDetail[]
|
||||
medium_detail?: MediumDetail
|
||||
long_detail?: LongDetail
|
||||
volatility?: VolatilityDetail
|
||||
}
|
||||
|
||||
export interface Score {
|
||||
|
||||
@@ -34,10 +34,32 @@ watch(
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
const quadrantTag = (q: string) => {
|
||||
const map: Record<string, string> = {
|
||||
accumulation: 'success',
|
||||
distribution: 'warning',
|
||||
covering: 'info',
|
||||
liquidation: 'danger',
|
||||
flat: '',
|
||||
}
|
||||
return map[q] ?? ''
|
||||
}
|
||||
|
||||
const quadrantLabel = (q: string) => {
|
||||
const map: Record<string, string> = {
|
||||
accumulation: '增仓涨',
|
||||
distribution: '增仓跌',
|
||||
covering: '减仓涨',
|
||||
liquidation: '减仓跌',
|
||||
flat: '持平',
|
||||
}
|
||||
return map[q] ?? q
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-drawer v-model="visible" title="打分明细" :size="isMobile ? '92%' : '640px'" destroy-on-close>
|
||||
<el-drawer v-model="visible" title="打分明细" :size="isMobile ? '92%' : '680px'" destroy-on-close>
|
||||
<div v-loading="loading" v-if="score">
|
||||
<el-descriptions :column="isMobile ? 1 : 2" border>
|
||||
<el-descriptions-item label="品种">{{ parseTsCode(score.ts_code).symbol }}</el-descriptions-item>
|
||||
@@ -60,20 +82,47 @@ watch(
|
||||
|
||||
<h4 class="section">短期 7 日逐日打分</h4>
|
||||
<div class="table-wrapper">
|
||||
<el-table :data="score.detail?.short_details ?? []" size="small" border class="detail-table">
|
||||
<el-table
|
||||
:data="score.detail?.short_details ?? []"
|
||||
size="small"
|
||||
border
|
||||
class="detail-table"
|
||||
max-height="400"
|
||||
>
|
||||
<el-table-column prop="trade_date" label="日期" width="100" />
|
||||
<el-table-column prop="close" label="收盘" />
|
||||
<el-table-column prop="pre_close" label="昨收" />
|
||||
<el-table-column prop="oi" label="持仓" />
|
||||
<el-table-column prop="oi_chg" label="持仓变化" />
|
||||
<el-table-column prop="score" label="单日得分" />
|
||||
<el-table-column prop="close" label="收盘" width="70" />
|
||||
<el-table-column label="涨跌幅" width="80">
|
||||
<template #default="{ row }">
|
||||
<span :style="{ color: row.price_chg_pct >= 0 ? '#e4393c' : '#1ca11c' }">
|
||||
{{ ((row.price_chg_pct ?? 0) * 100).toFixed(2) }}%
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="OI变化%" width="90">
|
||||
<template #default="{ row }">
|
||||
{{ ((row.oi_chg_pct ?? 0) * 100).toFixed(2) }}%
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="量比" width="65">
|
||||
<template #default="{ row }">
|
||||
{{ row.vol_ratio ?? '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="象限" width="85">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="quadrantTag(row.quadrant)" size="small">
|
||||
{{ quadrantLabel(row.quadrant) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="score" label="得分" width="65" />
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<h4 class="section">中期(15d)细节</h4>
|
||||
<el-descriptions :column="isMobile ? 1 : 2" border v-if="score.detail?.medium_detail">
|
||||
<el-descriptions-item label="价格收益率">
|
||||
{{ (score.detail.medium_detail.price_return_pct * 100).toFixed(2) }}%
|
||||
{{ score.detail.medium_detail.price_return_pct.toFixed(2) }}%
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="价格信号分">
|
||||
{{ score.detail.medium_detail.price_signal.toFixed(2) }}
|
||||
@@ -85,20 +134,48 @@ watch(
|
||||
{{ score.detail.medium_detail.long_down_days }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="资金意愿分" :span="isMobile ? 1 : 2">
|
||||
{{ score.detail.medium_detail.fund_signal }}
|
||||
{{ score.detail.medium_detail.fund_signal.toFixed(1) }}
|
||||
<span class="formula-hint">(50 + (增仓涨 - 增仓跌)/{{ score.detail.medium_detail.window ?? 15 }} × 50)</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<h4 class="section">长期(30d)细节</h4>
|
||||
<el-descriptions :column="isMobile ? 1 : 2" border v-if="score.detail?.long_detail">
|
||||
<el-descriptions-item label="OI 趋势分">
|
||||
{{ score.detail.long_detail.oi_score?.toFixed(1) ?? '-' }}
|
||||
<span class="formula-hint">(权重 60%)</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="价格趋势分">
|
||||
{{ score.detail.long_detail.price_score?.toFixed(1) ?? '-' }}
|
||||
<span class="formula-hint">(权重 40%)</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="30 日价格收益">
|
||||
{{ score.detail.long_detail.price_return_30d_pct?.toFixed(2) ?? '-' }}%
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="30 日前收盘">
|
||||
{{ score.detail.long_detail.price_before_30d?.toFixed(2) ?? '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="30 日均持仓">
|
||||
{{ score.detail.long_detail.avg_oi.toFixed(0) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="30 日前持仓">
|
||||
{{ score.detail.long_detail.oi_before.toFixed(0) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="变化幅度" :span="isMobile ? 1 : 2">
|
||||
{{ (score.detail.long_detail.change_pct * 100).toFixed(2) }}%
|
||||
<el-descriptions-item label="OI 变化幅度" :span="isMobile ? 1 : 2">
|
||||
{{ score.detail.long_detail.change_pct.toFixed(2) }}%
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<h4 class="section">波动率调整</h4>
|
||||
<el-descriptions :column="isMobile ? 1 : 2" border v-if="score.detail?.volatility">
|
||||
<el-descriptions-item label="日波动率(30d std)">
|
||||
{{ (score.detail.volatility.daily_vol_pct * 100).toFixed(2) }}%
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="ATR%">
|
||||
{{ (score.detail.volatility.atr_pct * 100).toFixed(2) }}%
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="波动率惩罚系数" :span="isMobile ? 1 : 2">
|
||||
{{ score.detail.volatility.vol_penalty.toFixed(3) }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
@@ -113,6 +190,11 @@ watch(
|
||||
overflow-x: auto;
|
||||
}
|
||||
.detail-table {
|
||||
min-width: 520px;
|
||||
min-width: 620px;
|
||||
}
|
||||
.formula-hint {
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 12px;
|
||||
margin-left: 6px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user