# 这是要替换的涨跌幅计算逻辑(第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)