98 lines
4.2 KiB
Python
98 lines
4.2 KiB
Python
# 这是要替换的涨跌幅计算逻辑(第3729-3738行)
|
||
|
||
# 计算基于事件时间的涨跌幅(参考 app.py /api/stock/quotes 的实现)
|
||
change_pct = None
|
||
change_amount = None
|
||
current_price = None
|
||
|
||
try:
|
||
# 获取事件时间和当前时间
|
||
evt_time = event.start_time if event.start_time else event.created_at
|
||
cur_time = datetime.now()
|
||
|
||
# 获取交易日和时间范围
|
||
evt_date = evt_time.date()
|
||
evt_time_only = evt_time.time()
|
||
market_open = dt_time(9, 30)
|
||
market_close = dt_time(15, 0)
|
||
|
||
# 检查是否是交易日
|
||
is_trading_day_result = db.session.execute(text("""
|
||
SELECT 1 FROM trading_days WHERE EXCHANGE_DATE = :date
|
||
"""), {"date": evt_date}).fetchone()
|
||
|
||
trading_day = None
|
||
start_time = None
|
||
end_time = None
|
||
|
||
if is_trading_day_result:
|
||
# 是交易日
|
||
if evt_time_only < market_open:
|
||
# 盘前 - 使用当日开盘
|
||
trading_day, start_time, end_time = evt_date, market_open, market_close
|
||
elif evt_time_only > market_close:
|
||
# 盘后 - 使用下一交易日
|
||
next_day_result = db.session.execute(text("""
|
||
SELECT EXCHANGE_DATE FROM trading_days
|
||
WHERE EXCHANGE_DATE > :date ORDER BY EXCHANGE_DATE LIMIT 1
|
||
"""), {"date": evt_date}).fetchone()
|
||
if next_day_result:
|
||
trading_day, start_time, end_time = next_day_result[0].date(), market_open, market_close
|
||
else:
|
||
# 盘中 - 从事件时间到收盘
|
||
trading_day, start_time, end_time = evt_date, evt_time_only, market_close
|
||
else:
|
||
# 非交易日 - 获取下一交易日
|
||
next_day_result = db.session.execute(text("""
|
||
SELECT EXCHANGE_DATE FROM trading_days
|
||
WHERE EXCHANGE_DATE > :date ORDER BY EXCHANGE_DATE LIMIT 1
|
||
"""), {"date": evt_date}).fetchone()
|
||
if next_day_result:
|
||
trading_day, start_time, end_time = next_day_result[0].date(), market_open, market_close
|
||
|
||
# 如果有有效的交易日且不在未来,查询涨跌幅
|
||
if trading_day and trading_day <= cur_time.date():
|
||
start_dt = datetime.combine(trading_day, start_time)
|
||
end_dt = datetime.combine(trading_day, end_time)
|
||
|
||
# 查询第一个bar和最后一个bar的价格
|
||
price_data = client.execute("""
|
||
WITH first_price AS (
|
||
SELECT close FROM stock_minute
|
||
WHERE code = %(code)s AND timestamp >= %(start)s AND timestamp <= %(end)s
|
||
ORDER BY timestamp 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 first_price.close as first_price,
|
||
last_price.close as last_price,
|
||
(last_price.close - first_price.close) / first_price.close * 100 as change_pct
|
||
FROM last_price CROSS JOIN first_price
|
||
WHERE EXISTS (SELECT 1 FROM first_price) AND EXISTS (SELECT 1 FROM last_price)
|
||
""", {'code': stock.stock_code, 'start': start_dt, 'end': end_dt})
|
||
|
||
if price_data and price_data[0] and price_data[0][0] is not None:
|
||
first_price = float(price_data[0][0])
|
||
current_price = float(price_data[0][1])
|
||
change_pct = float(price_data[0][2])
|
||
change_amount = current_price - first_price
|
||
except Exception as e:
|
||
print(f"计算事件涨跌幅失败 {stock.stock_code}: {e}")
|
||
|
||
# 如果ClickHouse没有数据,fallback到原来的逻辑
|
||
if change_pct is None:
|
||
if latest_trade and prev_trade:
|
||
if prev_trade.F007N and prev_trade.F007N != 0:
|
||
change_amount = float(latest_trade.F007N) - float(prev_trade.F007N)
|
||
change_pct = (change_amount / float(prev_trade.F007N)) * 100
|
||
elif latest_trade and latest_trade.F010N:
|
||
change_pct = float(latest_trade.F010N)
|
||
change_amount = float(latest_trade.F009N) if latest_trade.F009N else None
|
||
|
||
# 如果还没有当前价格,使用latest_trade
|
||
if current_price is None and latest_trade and latest_trade.F007N:
|
||
current_price = float(latest_trade.F007N)
|