update pay ui
This commit is contained in:
133
app.py
133
app.py
@@ -5897,6 +5897,21 @@ def get_stock_quotes():
|
|||||||
start_datetime = datetime.combine(trading_day, start_time)
|
start_datetime = datetime.combine(trading_day, start_time)
|
||||||
end_datetime = datetime.combine(trading_day, end_time)
|
end_datetime = datetime.combine(trading_day, end_time)
|
||||||
|
|
||||||
|
# 获取前一个交易日(用于计算涨跌幅基准)
|
||||||
|
prev_trading_day = None
|
||||||
|
with engine.connect() as conn:
|
||||||
|
result = conn.execute(text("""
|
||||||
|
SELECT EXCHANGE_DATE
|
||||||
|
FROM trading_days
|
||||||
|
WHERE EXCHANGE_DATE < :date
|
||||||
|
ORDER BY EXCHANGE_DATE DESC
|
||||||
|
LIMIT 1
|
||||||
|
"""), {"date": trading_day}).fetchone()
|
||||||
|
if result:
|
||||||
|
prev_trading_day = result[0].date() if hasattr(result[0], 'date') else result[0]
|
||||||
|
|
||||||
|
print(f"当前交易日: {trading_day}, 前一交易日: {prev_trading_day}")
|
||||||
|
|
||||||
# If the trading day is in the future relative to current time,
|
# If the trading day is in the future relative to current time,
|
||||||
# return only names without data
|
# return only names without data
|
||||||
if trading_day > current_time.date():
|
if trading_day > current_time.date():
|
||||||
@@ -5912,20 +5927,38 @@ def get_stock_quotes():
|
|||||||
# ==================== 性能优化:批量查询所有股票数据 ====================
|
# ==================== 性能优化:批量查询所有股票数据 ====================
|
||||||
# 使用 IN 子句一次查询所有股票,避免逐只循环查询
|
# 使用 IN 子句一次查询所有股票,避免逐只循环查询
|
||||||
try:
|
try:
|
||||||
# 批量查询价格和涨跌幅数据(使用窗口函数)
|
# 先从 MySQL ea_trade 表查询前一交易日的收盘价(日线数据,查询更快)
|
||||||
# 涨跌幅基于当日开盘价计算:(最新价 - 开盘价) / 开盘价 * 100
|
prev_close_map = {}
|
||||||
|
if prev_trading_day:
|
||||||
|
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['trade_date'] = prev_trading_day
|
||||||
|
|
||||||
|
prev_close_result = conn.execute(text(f"""
|
||||||
|
SELECT SECCODE, F007N as close_price
|
||||||
|
FROM ea_trade
|
||||||
|
WHERE SECCODE IN ({placeholders})
|
||||||
|
AND TRADEDATE = :trade_date
|
||||||
|
"""), params).fetchall()
|
||||||
|
|
||||||
|
# 构建代码到收盘价的映射(需要匹配完整代码格式)
|
||||||
|
base_close_map = {row[0]: float(row[1]) if row[1] else None for row in prev_close_result}
|
||||||
|
|
||||||
|
# 为每个完整代码(带后缀)分配收盘价
|
||||||
|
for code in codes:
|
||||||
|
base_code = code.split('.')[0]
|
||||||
|
if base_code in base_close_map:
|
||||||
|
prev_close_map[code] = base_close_map[base_code]
|
||||||
|
|
||||||
|
print(f"前一交易日({prev_trading_day})收盘价查询返回 {len(prev_close_result)} 条数据")
|
||||||
|
|
||||||
|
# 批量查询当前价格数据
|
||||||
batch_price_query = """
|
batch_price_query = """
|
||||||
WITH open_prices AS (
|
WITH last_prices AS (
|
||||||
SELECT
|
|
||||||
code,
|
|
||||||
open as open_price,
|
|
||||||
ROW_NUMBER() OVER (PARTITION BY code ORDER BY timestamp ASC) as rn
|
|
||||||
FROM stock_minute
|
|
||||||
WHERE code IN %(codes)s
|
|
||||||
AND timestamp >= %(start)s
|
|
||||||
AND timestamp <= %(end)s
|
|
||||||
),
|
|
||||||
last_prices AS (
|
|
||||||
SELECT
|
SELECT
|
||||||
code,
|
code,
|
||||||
close as last_price,
|
close as last_price,
|
||||||
@@ -5935,13 +5968,9 @@ def get_stock_quotes():
|
|||||||
AND timestamp >= %(start)s
|
AND timestamp >= %(start)s
|
||||||
AND timestamp <= %(end)s
|
AND timestamp <= %(end)s
|
||||||
)
|
)
|
||||||
SELECT
|
SELECT code, last_price
|
||||||
op.code,
|
FROM last_prices
|
||||||
lp.last_price,
|
WHERE rn = 1
|
||||||
(lp.last_price - op.open_price) / op.open_price * 100 as change_pct
|
|
||||||
FROM open_prices op
|
|
||||||
INNER JOIN last_prices lp ON op.code = lp.code
|
|
||||||
WHERE op.rn = 1 AND lp.rn = 1
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
batch_data = client.execute(batch_price_query, {
|
batch_data = client.execute(batch_price_query, {
|
||||||
@@ -5952,12 +5981,18 @@ def get_stock_quotes():
|
|||||||
|
|
||||||
print(f"批量查询返回 {len(batch_data)} 条价格数据")
|
print(f"批量查询返回 {len(batch_data)} 条价格数据")
|
||||||
|
|
||||||
# 解析批量查询结果
|
# 解析批量查询结果,使用前一交易日收盘价计算涨跌幅
|
||||||
price_data_map = {}
|
price_data_map = {}
|
||||||
for row in batch_data:
|
for row in batch_data:
|
||||||
code = row[0]
|
code = row[0]
|
||||||
last_price = float(row[1]) if row[1] is not None else None
|
last_price = float(row[1]) if row[1] is not None else None
|
||||||
change_pct = float(row[2]) if row[2] is not None else None
|
prev_close = prev_close_map.get(code)
|
||||||
|
|
||||||
|
# 计算涨跌幅:(当前价 - 前一交易日收盘价) / 前一交易日收盘价 * 100
|
||||||
|
change_pct = None
|
||||||
|
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
|
||||||
|
|
||||||
price_data_map[code] = {
|
price_data_map[code] = {
|
||||||
'price': last_price,
|
'price': last_price,
|
||||||
'change': change_pct
|
'change': change_pct
|
||||||
@@ -5982,34 +6017,40 @@ def get_stock_quotes():
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"批量查询 ClickHouse 失败: {e},回退到逐只查询")
|
print(f"批量查询 ClickHouse 失败: {e},回退到逐只查询")
|
||||||
# 降级方案:逐只股票查询(保持向后兼容)
|
# 降级方案:逐只股票查询(使用前一交易日收盘价计算涨跌幅)
|
||||||
for code in codes:
|
for code in codes:
|
||||||
try:
|
try:
|
||||||
data = client.execute("""
|
# 查询当前价格
|
||||||
WITH first_price AS (
|
current_data = client.execute("""
|
||||||
SELECT close FROM stock_minute
|
SELECT close FROM stock_minute
|
||||||
WHERE code = %(code)s AND timestamp >= %(start)s AND timestamp <= %(end)s
|
WHERE code = %(code)s AND timestamp >= %(start)s AND timestamp <= %(end)s
|
||||||
ORDER BY timestamp LIMIT 1
|
ORDER BY timestamp DESC LIMIT 1
|
||||||
),
|
|
||||||
last_price AS (
|
|
||||||
SELECT close FROM stock_minute
|
|
||||||
WHERE code = %(code)s AND timestamp >= %(start)s AND timestamp <= %(end)s
|
|
||||||
ORDER BY timestamp DESC LIMIT 1
|
|
||||||
)
|
|
||||||
SELECT last_price.close as last_price,
|
|
||||||
(last_price.close - first_price.close) / first_price.close * 100 as change
|
|
||||||
FROM last_price CROSS JOIN first_price
|
|
||||||
WHERE EXISTS (SELECT 1 FROM first_price) AND EXISTS (SELECT 1 FROM last_price)
|
|
||||||
""", {'code': code, 'start': start_datetime, 'end': end_datetime})
|
""", {'code': code, 'start': start_datetime, 'end': end_datetime})
|
||||||
|
|
||||||
if data and data[0] and data[0][0] is not None:
|
last_price = float(current_data[0][0]) if current_data and current_data[0] and current_data[0][0] else None
|
||||||
results[code] = {
|
|
||||||
'price': float(data[0][0]) if data[0][0] is not None else None,
|
# 从 MySQL ea_trade 表查询前一交易日收盘价
|
||||||
'change': float(data[0][1]) if data[0][1] is not None else None,
|
prev_close = None
|
||||||
'name': stock_names.get(code, f'股票{code.split(".")[0]}')
|
if prev_trading_day and last_price is not None:
|
||||||
}
|
base_code = code.split('.')[0]
|
||||||
else:
|
with engine.connect() as conn:
|
||||||
results[code] = {'price': None, 'change': None, 'name': stock_names.get(code, f'股票{code.split(".")[0]}')}
|
prev_result = conn.execute(text("""
|
||||||
|
SELECT F007N as close_price
|
||||||
|
FROM ea_trade
|
||||||
|
WHERE SECCODE = :code AND TRADEDATE = :trade_date
|
||||||
|
"""), {'code': base_code, 'trade_date': prev_trading_day}).fetchone()
|
||||||
|
prev_close = float(prev_result[0]) if prev_result and prev_result[0] else None
|
||||||
|
|
||||||
|
# 计算涨跌幅
|
||||||
|
change_pct = None
|
||||||
|
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
|
||||||
|
|
||||||
|
results[code] = {
|
||||||
|
'price': last_price,
|
||||||
|
'change': change_pct,
|
||||||
|
'name': stock_names.get(code, f'股票{code.split(".")[0]}')
|
||||||
|
}
|
||||||
except Exception as inner_e:
|
except Exception as inner_e:
|
||||||
print(f"Error processing stock {code}: {inner_e}")
|
print(f"Error processing stock {code}: {inner_e}")
|
||||||
results[code] = {'price': None, 'change': None, 'name': stock_names.get(code, f'股票{code.split(".")[0]}')}
|
results[code] = {'price': None, 'change': None, 'name': stock_names.get(code, f'股票{code.split(".")[0]}')}
|
||||||
|
|||||||
Reference in New Issue
Block a user