涨停分析高股对接

This commit is contained in:
renzhijun
2026-02-05 15:01:16 +08:00
parent 995ee7f220
commit c4cbd5a11f
9 changed files with 664 additions and 155 deletions

View File

@@ -142,42 +142,77 @@
</view>
<!-- <view style="color: #2B2B2B; font-weight: 500; display: flex; margin: 25rpx 20rpx;">
<view style="color: #2B2B2B; font-weight: 500; display: flex; margin: 25rpx 20rpx;">
<image style="width: 40rpx; height: 42rpx;" src="/pagesStock/static/icon/all-icon-3.png"
mode="widthFix"></image>
<view style="margin-left: 10rpx;">
<view style="font-size: 30rpx; font-weight: bold;">高位股统计</view>
<view style="font-size: 24rpx; font-weight: 500; margin-top: 10rpx;">
<text
style="color: #F3C368; border: 1rpx solid #F3C368; border-radius: 5rpx; text-align: center; padding: 0 10rpx;">高位股10只</text>
style="color: #F3C368; border: 1rpx solid #F3C368; border-radius: 5rpx; text-align: center; padding: 0 10rpx;">
高位股{{highPositionStats.total_count}}
</text>
<text
style="color: #EC3440; border: 1rpx solid #EC3440; border-radius: 5rpx; text-align: center; padding: 0 10rpx; margin: 0 10rpx;">平均3.7</text>
style="color: #EC3440; border: 1rpx solid #EC3440; border-radius: 5rpx; text-align: center; padding: 0 10rpx; margin: 0 10rpx;">
平均{{highPositionStats.avg_continuous_days}}
</text>
<text
style="color: #F59B38; border: 1rpx solid #F59B38; border-radius: 5rpx; text-align: center; padding: 0 10rpx;">最高9版</text>
<text
style="color: #FFF; background-color: #F59B38; border-radius: 5rpx; text-align: center; padding: 0 10rpx; margin-left: 10rpx;">中风险</text>
style="color: #F59B38; border: 1rpx solid #F59B38; border-radius: 5rpx; text-align: center; padding: 0 10rpx;">
最高{{highPositionStats.max_continuous_days}}
</text>
<text :style="{
color: '#FFF',
backgroundColor: riskAssessment.color,
borderRadius: '5rpx',
textAlign: 'center',
padding: '0 10rpx',
marginLeft: '10rpx'
}">
{{riskAssessment.level}}
</text>
</view>
</view>
</view>
<view v-for="(item,index) in 10" :key="index"
<view v-for="(stock,index) in highPositionStockList" :key="index"
style="background-color: #FAFAFC; border-radius: 10rpx; padding: 15rpx 20rpx; display: flex; align-items: center; margin: 10rpx 25rpx;">
<view style="flex: 1;">
<view style="color: #2B2B2B; font-weight: bold; font-size: 26rpx;">博菲电气</view>
<view style="color: #999999; font-weight: 500; font-size: 24rpx; margin-top: 5rpx;">(销量一字,高风险)
<view style="color: #2B2B2B; font-weight: bold; font-size: 26rpx;">{{stock.sname}}</view>
<view :style="{
color: '#999999',
fontWeight: 500,
fontSize: '24rpx',
marginTop: '5rpx'
}">
({{stock.risk_info.status}})
</view>
</view>
<view
style="display: flex; align-items: center; justify-content: center; padding: 4rpx 10rpx; background-color: #FFECEC; border-radius: 5rpx; border: 1rpx solid #EF4444; color: #EF4444; font-size: 20rpx; font-weight: 400; margin: 0 10rpx;">
<image style="width: 15rpx; height: 17rpx; margin-right: 10rpx;"
src="/pagesStock/static/icon/all-icon-4.png" mode="widthFix"></image>
<view>9连板</view>
<view :style="{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
padding: '4rpx 10rpx',
backgroundColor: stock.risk_info.bg,
borderRadius: '5rpx',
border: `1rpx solid ${stock.risk_info.border}`,
color: stock.risk_info.color,
fontSize: '20rpx',
fontWeight: 400,
margin: '0 10rpx'
}">
<image v-if="['high', 'medium'].includes(getStockHeatType(stock))" :style="{
width: '15rpx',
height: '17rpx',
marginRight: '10rpx',
tintColor: heatIconMap[getStockHeatType(stock)].icon4Color
}" :src="heatIconMap[getStockHeatType(stock)].icon4" mode="widthFix"></image>
<view>{{stock.continuous_days_num}}连板</view>
</view>
<image style="width: 27rpx; height: 25rpx;" src="/pagesStock/static/icon/all-icon-5.png"
mode="widthFix"></image>
<image :style="{width: '27rpx', height: '25rpx'}" :src="heatIconMap[getStockHeatType(stock)].icon5"
mode="widthFix"></image>
</view>
@@ -186,7 +221,7 @@
<image style="width: 27rpx; height: 25rpx; margin-right: 10rpx;"
src="/pagesStock/static/icon/all-icon-5.png" mode="widthFix"></image>
<text>高位股风险较高追涨需谨慎</text>
</view> -->
</view>
</view>
</scroll-view>
@@ -360,6 +395,69 @@
// '板块分布',
// '热门概念词云'
// ],
highPositionStats: {
total_count: 0, // 高位股数量
avg_continuous_days: 0, // 平均连板数
max_continuous_days: 0 // 最高连板数
},
riskAssessment: { // 风险评估结果
level: "正常",
color: "#22c55e"
},
highPositionStockList: [], // 新增:存储筛选后的高位股列表
// 风险阈值常量(对应参考代码)
RISK_THRESHOLDS: {
CRITICAL: 7,
HIGH: 5,
MEDIUM: 3,
LOW: 2,
},
// 风险颜色常量
RISK_COLORS: {
critical: {
color: "#ef4444",
bg: "rgba(239, 68, 68, 0.2)",
border: "rgba(239, 68, 68, 0.4)",
},
high: {
color: "#f97316",
bg: "rgba(249, 115, 22, 0.2)",
border: "rgba(249, 115, 22, 0.4)",
},
medium: {
color: "#eab308",
bg: "rgba(234, 179, 8, 0.2)",
border: "rgba(234, 179, 8, 0.4)",
},
low: {
color: "#22c55e",
bg: "rgba(34, 197, 94, 0.2)",
border: "rgba(34, 197, 94, 0.4)",
},
},
heatIconMap: {
high: {
icon4: '/pagesStock/static/icon/all-icon-4.png',
icon4Color: '#EF4444', // 高热度图标颜色
icon5: '/pagesStock/static/icon/all-icon-5.png' // 高热度右侧图标
},
medium: {
icon4: '/pagesStock/static/icon/all-icon-9.png',
icon4Color: '#F97316', // 中热度图标颜色
icon5: '/pagesStock/static/icon/all-icon-6.png' // 中热度右侧图标
},
low: {
icon4: '', // 低热度不显示icon4
icon4Color: '#F3B800',
icon5: '/pagesStock/static/icon/all-icon-7.png' // 低热度右侧图标
},
none: {
icon4: '', // 冷门
icon4Color: '#01AB5D',
icon5: '/pagesStock/static/icon/all-icon-8.png' // 无热度右侧图标
}
},
originData: null, // 原始接口数据
bkTypes: [
'板块分布',
@@ -442,9 +540,6 @@
this.activeIndex = e.index
this.contentTop = this.navH + 20 / 750 * inject('windowWidth')
//this.selectedFullDate = this.getPreviousDayDate();
//console.log("selectedFullDate", this.selectedFullDate)
//this.fetchData()
},
@@ -461,6 +556,155 @@
//}
},
methods: {
getStockHeatType(stock) {
// 假设通过连板数计算热度(可根据实际业务逻辑调整)
const days = stock.continuous_days_num || 0;
if (days >= this.RISK_THRESHOLDS.CRITICAL) { // ≥5连板 → 高热度
return 'high';
} else if (days >= this.RISK_THRESHOLDS.HIGH) { // 3-4连板 → 中热度
return 'medium';
} else if (days >= this.RISK_THRESHOLDS.MEDIUM) { // 2连板 → 低热度
return 'low';
} else { // <2连板 → 冷门(无热度)
return 'none';
}
},
//解析连板数(从"2天2板"格式中提取数字)
parseContinuousDays(continuousDaysStr) {
if (!continuousDaysStr) return 0;
const match = continuousDaysStr.match(/(\d+)天/);
return match ? Number(match[1]) : 0;
},
// 风险等级判断函数
getRiskLevel(days) {
const {
RISK_THRESHOLDS,
RISK_COLORS
} = this;
if (days >= RISK_THRESHOLDS.CRITICAL) {
return {
level: "极高",
color: RISK_COLORS.critical.color,
bg: RISK_COLORS.critical.bg,
border: RISK_COLORS.critical.border,
status: "缩量一字,高风险",
};
}
if (days >= RISK_THRESHOLDS.HIGH) {
return {
level: "高",
color: RISK_COLORS.high.color,
bg: RISK_COLORS.high.bg,
border: RISK_COLORS.high.border,
status: "放量分歧,需观察",
};
}
if (days >= RISK_THRESHOLDS.MEDIUM) {
return {
level: "中",
color: RISK_COLORS.medium.color,
bg: RISK_COLORS.medium.bg,
border: RISK_COLORS.medium.border,
status: "正常波动",
};
}
return {
level: "低",
color: RISK_COLORS.low.color,
bg: RISK_COLORS.low.bg,
border: RISK_COLORS.low.border,
status: "健康",
};
},
// 计算高位股统计数据
calculateHighPositionStats() {
if (!this.originData || !this.originData.stocks) return;
// 1. 筛选高位股:连板数 >= 2 的股票 + 补充连板数和风险信息
const highPositionStocks = this.originData.stocks
.filter(stock => {
const days = this.parseContinuousDays(stock.continuous_days);
return days >= 2;
})
.map(stock => {
const days = this.parseContinuousDays(stock.continuous_days);
const riskInfo = this.getRiskLevel(days);
return {
...stock,
continuous_days_num: days, // 提取纯数字的连板数
risk_info: riskInfo // 风险等级信息
};
})
// 2. 按连板天数降序排列
.sort((a, b) => b.continuous_days_num - a.continuous_days_num);
// 3. 赋值给页面渲染用的列表(
this.highPositionStockList = highPositionStocks
// 4. 原有统计数据计算逻辑(保持不变)
const totalCount = highPositionStocks.length;
const maxDays = highPositionStocks.length ?
Math.max(...highPositionStocks.map(s => this.parseContinuousDays(s.continuous_days))) :
0;
const totalDays = highPositionStocks.reduce((sum, stock) => {
return sum + this.parseContinuousDays(stock.continuous_days);
}, 0);
const avgDays = totalCount > 0 ? (totalDays / totalCount).toFixed(1) : 0;
// 5. 更新统计数据
this.highPositionStats = {
total_count: totalCount,
avg_continuous_days: avgDays,
max_continuous_days: maxDays
};
// 6. 计算风险等级
this.calculateRiskAssessment();
},
// 计算风险评估
calculateRiskAssessment() {
const {
avg_continuous_days,
max_continuous_days,
total_count
} = this.highPositionStats;
const avgDays = Number(avg_continuous_days) || 0;
const maxDays = Number(max_continuous_days) || 0;
const totalCount = Number(total_count) || 0;
// 计算风险评分(和参考代码一致)
const score = avgDays * 2 + maxDays * 0.5 + totalCount * 0.3;
// 根据评分确定风险等级和颜色
if (score >= 20) {
this.riskAssessment = {
level: "高风险",
color: "#ef4444"
};
} else if (score >= 12) {
this.riskAssessment = {
level: "中风险",
color: "#f97316"
};
} else if (score >= 6) {
this.riskAssessment = {
level: "偏高",
color: "#eab308"
};
} else {
this.riskAssessment = {
level: "正常",
color: "#22c55e"
};
}
},
getHeatColor(value, max) {
// 处理边界最大值为0时直接返回绿色
if (max === 0) return '#01AB5D';
@@ -575,6 +819,9 @@
// 3. 核心限制最多显示16条切片操作放在最后
this.bkList = bkList.slice(0, 16);
this.initPieChart();
this.calculateHighPositionStats();
} else {
uni.showToast({
title: '数据请求失败',
@@ -702,39 +949,39 @@
ztCount - prevZtCount;
this.tabTypes[1].change = changeValue;
// =======================================
// ===== 新增:判断选中日期是否为系统当天,若是则日期减一天 =====
if (this.selectedFullDate) {
// 获取系统当前日期并格式化为 YYYYMMDD
const today = new Date();
const todayYear = today.getFullYear();
const todayMonth = String(today.getMonth() + 1).padStart(2, '0');
const todayDay = String(today.getDate()).padStart(2, '0');
const todayFormatted = `${todayYear}${todayMonth}${todayDay}`;
// 判断选中日期是否等于系统当天
if (this.selectedFullDate === todayFormatted) {
// 创建选中日期的Date对象
const selectedDate = new Date(
parseInt(this.selectedFullDate.substring(0, 4)), // 年
parseInt(this.selectedFullDate.substring(4, 6)) - 1, // 月月份从0开始
parseInt(this.selectedFullDate.substring(6, 8)) // 日
);
// 将日期减一天
selectedDate.setDate(selectedDate.getDate() - 1);
// 格式化前一天的日期为 YYYYMMDD 格式(补零处理)
const prevYear = selectedDate.getFullYear();
const prevMonth = String(selectedDate.getMonth() + 1).padStart(2, '0');
const prevDay = String(selectedDate.getDate()).padStart(2, '0');
const prevDateFormatted = `${prevYear}${prevMonth}${prevDay}`;
// 更新选中的日期为前一天
this.selectedFullDate = prevDateFormatted;
console.log(`选中日期为当天(${todayFormatted}),已自动调整为前一天:`, prevDateFormatted);
}
}
// ===== 新增:判断选中日期是否为系统当天,若是则日期减一天 =====
if (this.selectedFullDate) {
// 获取系统当前日期并格式化为 YYYYMMDD
const today = new Date();
const todayYear = today.getFullYear();
const todayMonth = String(today.getMonth() + 1).padStart(2, '0');
const todayDay = String(today.getDate()).padStart(2, '0');
const todayFormatted = `${todayYear}${todayMonth}${todayDay}`;
// 判断选中日期是否等于系统当天
if (this.selectedFullDate === todayFormatted) {
// 创建选中日期的Date对象
const selectedDate = new Date(
parseInt(this.selectedFullDate.substring(0, 4)), // 年
parseInt(this.selectedFullDate.substring(4, 6)) - 1, // 月月份从0开始
parseInt(this.selectedFullDate.substring(6, 8)) // 日
);
// 将日期减一天
selectedDate.setDate(selectedDate.getDate() - 1);
// 格式化前一天的日期为 YYYYMMDD 格式(补零处理)
const prevYear = selectedDate.getFullYear();
const prevMonth = String(selectedDate.getMonth() + 1).padStart(2, '0');
const prevDay = String(selectedDate.getDate()).padStart(2, '0');
const prevDateFormatted = `${prevYear}${prevMonth}${prevDay}`;
// 更新选中的日期为前一天
this.selectedFullDate = prevDateFormatted;
console.log(`选中日期为当天(${todayFormatted}),已自动调整为前一天:`, prevDateFormatted);
}
}
this.fetchData()
},