update pay ui
This commit is contained in:
139
app.py
139
app.py
@@ -6412,6 +6412,10 @@ def get_stock_kline(stock_code):
|
||||
except ValueError:
|
||||
return jsonify({'error': 'Invalid event_time format'}), 400
|
||||
|
||||
# 确保股票代码包含后缀(ClickHouse 中数据带后缀)
|
||||
if '.' not in stock_code:
|
||||
stock_code = f"{stock_code}.SH" if stock_code.startswith('6') else f"{stock_code}.SZ"
|
||||
|
||||
# 获取股票名称
|
||||
with engine.connect() as conn:
|
||||
result = conn.execute(text(
|
||||
@@ -7837,8 +7841,13 @@ def get_index_kline(index_code):
|
||||
except ValueError:
|
||||
return jsonify({'error': 'Invalid event_time format'}), 400
|
||||
|
||||
# 确保指数代码包含后缀(ClickHouse 中数据带后缀)
|
||||
# 399xxx -> 深交所, 其他(000xxx等)-> 上交所
|
||||
if '.' not in index_code:
|
||||
index_code = f"{index_code}.SZ" if index_code.startswith('39') else f"{index_code}.SH"
|
||||
|
||||
# 指数名称(暂无索引表,先返回代码本身)
|
||||
index_name = index_code
|
||||
index_name = index_code.split('.')[0]
|
||||
|
||||
if chart_type == 'minute':
|
||||
return get_index_minute_kline(index_code, event_datetime, index_name)
|
||||
@@ -12710,6 +12719,134 @@ def get_hotspot_overview():
|
||||
}), 500
|
||||
|
||||
|
||||
@app.route('/api/concept/<concept_id>/stocks', methods=['GET'])
|
||||
def get_concept_stocks(concept_id):
|
||||
"""
|
||||
获取概念的相关股票列表(带实时涨跌幅)
|
||||
|
||||
Args:
|
||||
concept_id: 概念 ID(来自 ES concept_library_v3)
|
||||
|
||||
Returns:
|
||||
- stocks: 股票列表 [{code, name, reason, change_pct}, ...]
|
||||
"""
|
||||
try:
|
||||
from elasticsearch import Elasticsearch
|
||||
from clickhouse_driver import Client
|
||||
|
||||
# 1. 从 ES 获取概念的股票列表
|
||||
es_client = Elasticsearch(["http://222.128.1.157:19200"])
|
||||
es_result = es_client.get(index='concept_library_v3', id=concept_id)
|
||||
|
||||
if not es_result.get('found'):
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': f'概念 {concept_id} 不存在'
|
||||
}), 404
|
||||
|
||||
source = es_result.get('_source', {})
|
||||
concept_name = source.get('concept', concept_id)
|
||||
raw_stocks = source.get('stocks', [])
|
||||
|
||||
if not raw_stocks:
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'data': {
|
||||
'concept_id': concept_id,
|
||||
'concept_name': concept_name,
|
||||
'stocks': []
|
||||
}
|
||||
})
|
||||
|
||||
# 提取股票代码和原因
|
||||
stocks_info = []
|
||||
stock_codes = []
|
||||
for s in raw_stocks:
|
||||
if isinstance(s, dict):
|
||||
code = s.get('code', '')
|
||||
if code and len(code) == 6:
|
||||
stocks_info.append({
|
||||
'code': code,
|
||||
'name': s.get('name', ''),
|
||||
'reason': s.get('reason', '')
|
||||
})
|
||||
stock_codes.append(code)
|
||||
|
||||
# 2. 从 ClickHouse 获取最新涨跌幅
|
||||
change_map = {}
|
||||
if stock_codes:
|
||||
try:
|
||||
ch_client = Client(
|
||||
host='127.0.0.1',
|
||||
port=9000,
|
||||
user='default',
|
||||
password='Zzl33818!',
|
||||
database='stock'
|
||||
)
|
||||
|
||||
# 转换为 ClickHouse 格式
|
||||
ch_codes = []
|
||||
code_mapping = {}
|
||||
for code in stock_codes:
|
||||
if code.startswith('6'):
|
||||
ch_code = f"{code}.SH"
|
||||
elif code.startswith('0') or code.startswith('3'):
|
||||
ch_code = f"{code}.SZ"
|
||||
else:
|
||||
ch_code = f"{code}.BJ"
|
||||
ch_codes.append(ch_code)
|
||||
code_mapping[ch_code] = code
|
||||
|
||||
ch_codes_str = "','".join(ch_codes)
|
||||
|
||||
# 查询最新分钟数据
|
||||
query = f"""
|
||||
SELECT code, close, pre_close
|
||||
FROM stock_minute
|
||||
WHERE code IN ('{ch_codes_str}')
|
||||
AND timestamp >= today()
|
||||
ORDER BY timestamp DESC
|
||||
LIMIT 1 BY code
|
||||
"""
|
||||
result = ch_client.execute(query)
|
||||
|
||||
for row in result:
|
||||
ch_code, close_price, pre_close = row
|
||||
if ch_code in code_mapping and pre_close and pre_close > 0:
|
||||
original_code = code_mapping[ch_code]
|
||||
change_pct = (float(close_price) - float(pre_close)) / float(pre_close) * 100
|
||||
change_map[original_code] = round(change_pct, 2)
|
||||
|
||||
except Exception as ch_err:
|
||||
app.logger.warning(f"ClickHouse 获取涨跌幅失败: {ch_err}")
|
||||
|
||||
# 3. 合并数据
|
||||
result_stocks = []
|
||||
for stock in stocks_info:
|
||||
stock['change_pct'] = change_map.get(stock['code'])
|
||||
result_stocks.append(stock)
|
||||
|
||||
# 按涨跌幅排序(涨停优先)
|
||||
result_stocks.sort(key=lambda x: x.get('change_pct') or -999, reverse=True)
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'data': {
|
||||
'concept_id': concept_id,
|
||||
'concept_name': concept_name,
|
||||
'stock_count': len(result_stocks),
|
||||
'stocks': result_stocks
|
||||
}
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
app.logger.error(f"获取概念股票失败: {e}")
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': str(e)
|
||||
}), 500
|
||||
|
||||
|
||||
@app.route('/api/market/concept-alerts', methods=['GET'])
|
||||
def get_concept_alerts():
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user