update pay ui
This commit is contained in:
@@ -18,6 +18,69 @@ import {
|
||||
import { FaBolt, FaArrowUp, FaArrowDown, FaChartLine, FaFire, FaVolumeUp } from 'react-icons/fa';
|
||||
import { getAlertTypeLabel, formatScore, getScoreColor } from '../utils/chartHelpers';
|
||||
|
||||
/**
|
||||
* Z-Score 指示器组件
|
||||
*/
|
||||
const ZScoreIndicator = ({ value, label, tooltip }) => {
|
||||
if (value === null || value === undefined) return null;
|
||||
|
||||
// Z-Score 颜色:越大越红,越小越绿
|
||||
const getZScoreColor = (z) => {
|
||||
const absZ = Math.abs(z);
|
||||
if (absZ >= 3) return z > 0 ? 'red.600' : 'green.600';
|
||||
if (absZ >= 2) return z > 0 ? 'red.500' : 'green.500';
|
||||
if (absZ >= 1) return z > 0 ? 'orange.400' : 'teal.400';
|
||||
return 'gray.400';
|
||||
};
|
||||
|
||||
// Z-Score 强度条宽度(最大 5σ)
|
||||
const barWidth = Math.min(Math.abs(value) / 5 * 100, 100);
|
||||
|
||||
return (
|
||||
<Tooltip label={tooltip || `${label}: ${value.toFixed(2)}σ`} placement="left">
|
||||
<HStack spacing={1} fontSize="xs">
|
||||
<Text color="gray.500" w="20px">{label}</Text>
|
||||
<Box position="relative" w="40px" h="6px" bg="gray.200" borderRadius="full" overflow="hidden">
|
||||
<Box
|
||||
position="absolute"
|
||||
left={value >= 0 ? '50%' : `${50 - barWidth / 2}%`}
|
||||
w={`${barWidth / 2}%`}
|
||||
h="100%"
|
||||
bg={getZScoreColor(value)}
|
||||
borderRadius="full"
|
||||
/>
|
||||
</Box>
|
||||
<Text color={getZScoreColor(value)} fontWeight="medium" w="28px" textAlign="right">
|
||||
{value >= 0 ? '+' : ''}{value.toFixed(1)}
|
||||
</Text>
|
||||
</HStack>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 持续确认率指示器
|
||||
*/
|
||||
const ConfirmRatioIndicator = ({ ratio }) => {
|
||||
if (ratio === null || ratio === undefined) return null;
|
||||
|
||||
const percent = Math.round(ratio * 100);
|
||||
const color = percent >= 80 ? 'green' : percent >= 60 ? 'orange' : 'red';
|
||||
|
||||
return (
|
||||
<Tooltip label={`持续确认率: ${percent}%(5分钟窗口内超标比例)`}>
|
||||
<HStack spacing={1}>
|
||||
<Box position="relative" w="32px" h="6px" bg="gray.200" borderRadius="full" overflow="hidden">
|
||||
<Box w={`${percent}%`} h="100%" bg={`${color}.500`} borderRadius="full" />
|
||||
</Box>
|
||||
<Text fontSize="xs" color={`${color}.500`} fontWeight="medium">
|
||||
{percent}%
|
||||
</Text>
|
||||
</HStack>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 单个异动项组件
|
||||
*/
|
||||
@@ -29,6 +92,7 @@ const AlertItem = ({ alert, onClick, isSelected }) => {
|
||||
|
||||
const isUp = alert.alert_type !== 'surge_down';
|
||||
const typeColor = isUp ? 'red' : 'green';
|
||||
const isV2 = alert.is_v2;
|
||||
|
||||
// 获取异动类型图标
|
||||
const getTypeIcon = (type) => {
|
||||
@@ -69,13 +133,30 @@ const AlertItem = ({ alert, onClick, isSelected }) => {
|
||||
<Text fontWeight="bold" fontSize="sm" noOfLines={1}>
|
||||
{alert.concept_name}
|
||||
</Text>
|
||||
{isV2 && (
|
||||
<Badge colorScheme="purple" size="xs" variant="subtle" fontSize="10px">
|
||||
V2
|
||||
</Badge>
|
||||
)}
|
||||
</HStack>
|
||||
<HStack spacing={2} fontSize="xs" color="gray.500">
|
||||
<Text>{alert.time}</Text>
|
||||
<Badge colorScheme={typeColor} size="sm" variant="subtle">
|
||||
{getAlertTypeLabel(alert.alert_type)}
|
||||
</Badge>
|
||||
{/* V2: 持续确认率 */}
|
||||
{isV2 && alert.confirm_ratio !== undefined && (
|
||||
<ConfirmRatioIndicator ratio={alert.confirm_ratio} />
|
||||
)}
|
||||
</HStack>
|
||||
|
||||
{/* V2: Z-Score 指标行 */}
|
||||
{isV2 && (alert.alpha_zscore !== undefined || alert.amt_zscore !== undefined) && (
|
||||
<HStack spacing={3} mt={1}>
|
||||
<ZScoreIndicator value={alert.alpha_zscore} label="α" tooltip={`Alpha Z-Score: ${alert.alpha_zscore?.toFixed(2)}σ(相对于历史同时段)`} />
|
||||
<ZScoreIndicator value={alert.amt_zscore} label="量" tooltip={`成交额 Z-Score: ${alert.amt_zscore?.toFixed(2)}σ`} />
|
||||
</HStack>
|
||||
)}
|
||||
</VStack>
|
||||
|
||||
{/* 右侧:分数和关键指标 */}
|
||||
@@ -104,12 +185,29 @@ const AlertItem = ({ alert, onClick, isSelected }) => {
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{/* 涨停数量 */}
|
||||
{alert.limit_up_count > 0 && (
|
||||
{/* V2: 动量指标 */}
|
||||
{isV2 && alert.momentum_5m !== undefined && Math.abs(alert.momentum_5m) > 0.3 && (
|
||||
<HStack spacing={1}>
|
||||
<Icon
|
||||
as={alert.momentum_5m > 0 ? FaArrowUp : FaArrowDown}
|
||||
color={alert.momentum_5m > 0 ? 'red.400' : 'green.400'}
|
||||
boxSize={3}
|
||||
/>
|
||||
<Text fontSize="xs" color={alert.momentum_5m > 0 ? 'red.400' : 'green.400'}>
|
||||
动量 {alert.momentum_5m > 0 ? '+' : ''}{alert.momentum_5m.toFixed(2)}
|
||||
</Text>
|
||||
</HStack>
|
||||
)}
|
||||
|
||||
{/* 涨停数量 / 涨停比例 */}
|
||||
{(alert.limit_up_count > 0 || (alert.limit_up_ratio > 0.05 && isV2)) && (
|
||||
<HStack spacing={1}>
|
||||
<Icon as={FaFire} color="orange.500" boxSize={3} />
|
||||
<Text fontSize="xs" color="orange.500">
|
||||
涨停 {alert.limit_up_count}
|
||||
{alert.limit_up_count > 0
|
||||
? `涨停 ${alert.limit_up_count}`
|
||||
: `涨停 ${Math.round(alert.limit_up_ratio * 100)}%`
|
||||
}
|
||||
</Text>
|
||||
</HStack>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user