update pay ui

This commit is contained in:
2025-12-03 08:02:49 +08:00
parent cb4f5b6281
commit aaaf66ca09
7 changed files with 491 additions and 84 deletions

158
app.py
View File

@@ -6285,6 +6285,164 @@ def get_stock_kline(stock_code):
return jsonify({'error': f'Unsupported chart type: {chart_type}'}), 400
@app.route('/api/stock/batch-kline', methods=['POST'])
def get_batch_kline_data():
"""批量获取多只股票的K线/分时数据
请求体:{ codes: string[], type: 'timeline'|'daily', event_time?: string }
返回:{ success: true, data: { [code]: { data: [], trade_date: '', ... } } }
"""
try:
data = request.json
codes = data.get('codes', [])
chart_type = data.get('type', 'timeline')
event_time = data.get('event_time')
if not codes:
return jsonify({'success': False, 'error': '请提供股票代码列表'}), 400
if len(codes) > 50:
return jsonify({'success': False, 'error': '单次最多查询50只股票'}), 400
try:
event_datetime = datetime.fromisoformat(event_time) if event_time else datetime.now()
except ValueError:
return jsonify({'success': False, 'error': 'Invalid event_time format'}), 400
client = get_clickhouse_client()
# 批量获取股票名称
stock_names = {}
with engine.connect() as conn:
base_codes = list(set([code.split('.')[0] for code in codes]))
if base_codes:
placeholders = ','.join([f':code{i}' for i in range(len(base_codes))])
params = {f'code{i}': code for i, code in enumerate(base_codes)}
result = conn.execute(text(
f"SELECT SECCODE, SECNAME FROM ea_stocklist WHERE SECCODE IN ({placeholders})"
), params).fetchall()
for row in result:
stock_names[row[0]] = row[1]
# 确定目标交易日
target_date = get_trading_day_near_date(event_datetime.date())
is_after_market = event_datetime.time() > dt_time(15, 0)
if target_date and is_after_market:
next_trade_date = get_trading_day_near_date(target_date + timedelta(days=1))
if next_trade_date:
target_date = next_trade_date
if not target_date:
# 返回空数据
return jsonify({
'success': True,
'data': {code: {'data': [], 'trade_date': event_datetime.date().strftime('%Y-%m-%d'), 'type': chart_type} for code in codes}
})
start_time = datetime.combine(target_date, dt_time(9, 30))
end_time = datetime.combine(target_date, dt_time(15, 0))
results = {}
if chart_type == 'timeline':
# 批量查询分时数据
batch_data = client.execute("""
SELECT code, timestamp, close, volume
FROM stock_minute
WHERE code IN %(codes)s
AND timestamp BETWEEN %(start)s AND %(end)s
ORDER BY code, timestamp
""", {
'codes': codes,
'start': start_time,
'end': end_time
})
# 按股票代码分组
stock_data = {}
for row in batch_data:
code = row[0]
if code not in stock_data:
stock_data[code] = []
stock_data[code].append({
'time': row[1].strftime('%H:%M'),
'price': float(row[2]),
'volume': float(row[3])
})
# 组装结果
for code in codes:
base_code = code.split('.')[0]
stock_name = stock_names.get(base_code, f'股票{base_code}')
data_list = stock_data.get(code, [])
results[code] = {
'code': code,
'name': stock_name,
'data': data_list,
'trade_date': target_date.strftime('%Y-%m-%d'),
'type': 'timeline'
}
elif chart_type == 'daily':
# 批量查询日线数据从MySQL ea_trade表
with engine.connect() as conn:
base_codes = list(set([code.split('.')[0] for code in codes]))
if base_codes:
placeholders = ','.join([f':code{i}' for i in range(len(base_codes))])
params = {f'code{i}': code for i, code in enumerate(base_codes)}
params['start_date'] = target_date - timedelta(days=60)
params['end_date'] = target_date
daily_result = conn.execute(text(f"""
SELECT SECCODE, TRADEDATE, F003N as open, F005N as high, F006N as low, F007N as close, F004N as volume
FROM ea_trade
WHERE SECCODE IN ({placeholders})
AND TRADEDATE BETWEEN :start_date AND :end_date
ORDER BY SECCODE, TRADEDATE
"""), params).fetchall()
# 按股票代码分组
stock_data = {}
for row in daily_result:
code_base = row[0]
if code_base not in stock_data:
stock_data[code_base] = []
stock_data[code_base].append({
'date': row[1].strftime('%Y-%m-%d') if hasattr(row[1], 'strftime') else str(row[1]),
'open': float(row[2]) if row[2] else 0,
'high': float(row[3]) if row[3] else 0,
'low': float(row[4]) if row[4] else 0,
'close': float(row[5]) if row[5] else 0,
'volume': float(row[6]) if row[6] else 0
})
# 组装结果
for code in codes:
base_code = code.split('.')[0]
stock_name = stock_names.get(base_code, f'股票{base_code}')
data_list = stock_data.get(base_code, [])
results[code] = {
'code': code,
'name': stock_name,
'data': data_list,
'trade_date': target_date.strftime('%Y-%m-%d'),
'type': 'daily'
}
print(f"批量K线查询完成: {len(codes)} 只股票, 类型: {chart_type}, 交易日: {target_date}")
return jsonify({
'success': True,
'data': results
})
except Exception as e:
print(f"批量K线查询错误: {e}")
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/api/stock/<stock_code>/latest-minute', methods=['GET'])
def get_latest_minute_data(stock_code):
"""获取最新交易日的分钟频数据"""