heropanel修改
This commit is contained in:
112
app.py
112
app.py
@@ -11154,37 +11154,115 @@ def get_events_effectiveness_stats():
|
|||||||
RelatedStock.event_id.in_(event_ids)
|
RelatedStock.event_id.in_(event_ids)
|
||||||
).all()
|
).all()
|
||||||
|
|
||||||
# 构建事件 ID 到事件的映射,用于获取涨跌幅
|
# 去重统计股票
|
||||||
event_map = {e.id: e for e in events_query}
|
|
||||||
|
|
||||||
# 统计股票数量(去重),并关联事件涨跌幅
|
|
||||||
unique_stocks = {}
|
unique_stocks = {}
|
||||||
for rs in related_stocks:
|
for rs in related_stocks:
|
||||||
stock_key = rs.stock_code
|
stock_key = rs.stock_code
|
||||||
# 获取关联事件的最大涨幅作为该股票的涨幅参考
|
if stock_key and stock_key not in unique_stocks:
|
||||||
event = event_map.get(rs.event_id)
|
|
||||||
event_max_chg = event.related_max_chg if event else 0
|
|
||||||
|
|
||||||
if stock_key not in unique_stocks:
|
|
||||||
unique_stocks[stock_key] = {
|
unique_stocks[stock_key] = {
|
||||||
'stockCode': rs.stock_code,
|
'stockCode': rs.stock_code,
|
||||||
'stockName': rs.stock_name,
|
'stockName': rs.stock_name,
|
||||||
'maxChg': event_max_chg or 0,
|
|
||||||
'eventId': rs.event_id,
|
'eventId': rs.event_id,
|
||||||
'correlation': rs.correlation or 0,
|
|
||||||
}
|
}
|
||||||
else:
|
|
||||||
# 保留最大涨幅的记录
|
|
||||||
if (event_max_chg or 0) > unique_stocks[stock_key]['maxChg']:
|
|
||||||
unique_stocks[stock_key]['maxChg'] = event_max_chg or 0
|
|
||||||
unique_stocks[stock_key]['eventId'] = rs.event_id
|
|
||||||
|
|
||||||
total_stocks = len(unique_stocks)
|
total_stocks = len(unique_stocks)
|
||||||
|
|
||||||
|
# 批量查询股票的实时涨跌幅(从 ClickHouse)
|
||||||
|
if unique_stocks:
|
||||||
|
try:
|
||||||
|
client = get_clickhouse_client()
|
||||||
|
|
||||||
|
# 标准化股票代码为 ClickHouse 格式
|
||||||
|
def normalize_code(code):
|
||||||
|
if not code:
|
||||||
|
return None
|
||||||
|
base = code.split('.')[0]
|
||||||
|
if base.startswith('6'):
|
||||||
|
return f"{base}.SH"
|
||||||
|
elif base.startswith(('0', '3')):
|
||||||
|
return f"{base}.SZ"
|
||||||
|
return code
|
||||||
|
|
||||||
|
normalized_codes = [normalize_code(c) for c in unique_stocks.keys() if c]
|
||||||
|
normalized_codes = [c for c in normalized_codes if c] # 过滤 None
|
||||||
|
|
||||||
|
# 构建代码映射
|
||||||
|
code_mapping = {}
|
||||||
|
for orig_code in unique_stocks.keys():
|
||||||
|
norm_code = normalize_code(orig_code)
|
||||||
|
if norm_code:
|
||||||
|
code_mapping[orig_code] = norm_code
|
||||||
|
|
||||||
|
# 获取当前交易日的时间范围
|
||||||
|
if hasattr(current_trading_day, 'strftime'):
|
||||||
|
target_date = current_trading_day
|
||||||
|
else:
|
||||||
|
target_date = datetime.strptime(str(current_trading_day), '%Y-%m-%d').date()
|
||||||
|
|
||||||
|
start_datetime = datetime.combine(target_date, dt_time(9, 30))
|
||||||
|
end_datetime = datetime.combine(target_date, dt_time(15, 0))
|
||||||
|
|
||||||
|
# 1. 从 ClickHouse 批量查询最新价格
|
||||||
|
batch_price_query = """
|
||||||
|
SELECT
|
||||||
|
code,
|
||||||
|
argMax(close, timestamp) as last_price
|
||||||
|
FROM stock_minute
|
||||||
|
WHERE code IN %(codes)s
|
||||||
|
AND timestamp >= %(start)s
|
||||||
|
AND timestamp <= %(end)s
|
||||||
|
GROUP BY code
|
||||||
|
"""
|
||||||
|
batch_data = client.execute(batch_price_query, {
|
||||||
|
'codes': normalized_codes,
|
||||||
|
'start': start_datetime,
|
||||||
|
'end': end_datetime
|
||||||
|
})
|
||||||
|
|
||||||
|
# 构建价格映射
|
||||||
|
price_map = {row[0]: float(row[1]) if row[1] else None for row in batch_data}
|
||||||
|
|
||||||
|
# 2. 批量获取前收盘价(使用 Redis 缓存)
|
||||||
|
prev_date_str = None
|
||||||
|
try:
|
||||||
|
target_idx = trading_days.index(target_date)
|
||||||
|
if target_idx > 0:
|
||||||
|
prev_trading_day = trading_days[target_idx - 1]
|
||||||
|
prev_date_str = prev_trading_day.strftime('%Y%m%d')
|
||||||
|
except (ValueError, IndexError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
prev_close_map = {}
|
||||||
|
if prev_date_str:
|
||||||
|
base_codes = list(set([code.split('.')[0] for code in unique_stocks.keys() if code]))
|
||||||
|
prev_close_map = get_cached_prev_close(base_codes, prev_date_str)
|
||||||
|
|
||||||
|
# 3. 计算涨跌幅并更新
|
||||||
|
for orig_code, stock_info in unique_stocks.items():
|
||||||
|
norm_code = code_mapping.get(orig_code)
|
||||||
|
base_code = orig_code.split('.')[0] if orig_code else ''
|
||||||
|
|
||||||
|
last_price = price_map.get(norm_code) if norm_code else None
|
||||||
|
prev_close = prev_close_map.get(base_code)
|
||||||
|
|
||||||
|
if last_price is not None and prev_close is not None and prev_close > 0:
|
||||||
|
change_pct = (last_price - prev_close) / prev_close * 100
|
||||||
|
stock_info['maxChg'] = round(change_pct, 2)
|
||||||
|
else:
|
||||||
|
stock_info['maxChg'] = 0
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
import traceback
|
||||||
|
print(f'[effectiveness-stats] 查询股票涨跌幅失败: {e}')
|
||||||
|
traceback.print_exc()
|
||||||
|
# 失败时设置默认值
|
||||||
|
for stock_info in unique_stocks.values():
|
||||||
|
stock_info['maxChg'] = 0
|
||||||
|
|
||||||
# 按涨幅排序,取 TOP10
|
# 按涨幅排序,取 TOP10
|
||||||
stock_stats = sorted(
|
stock_stats = sorted(
|
||||||
unique_stocks.values(),
|
unique_stocks.values(),
|
||||||
key=lambda x: x['maxChg'],
|
key=lambda x: x.get('maxChg', 0),
|
||||||
reverse=True
|
reverse=True
|
||||||
)[:10]
|
)[:10]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user