1
This commit is contained in:
parent
c03d5a88e8
commit
23dd333ae4
Binary file not shown.
Binary file not shown.
@ -61,8 +61,8 @@ async def intraday_market_temperature(prev_temp: MarketTemperature) -> MarketTem
|
|||||||
|
|
||||||
# ── 用东方财富 clist API 统计涨停跌停(比腾讯涨停价字段更可靠) ──
|
# ── 用东方财富 clist API 统计涨停跌停(比腾讯涨停价字段更可靠) ──
|
||||||
try:
|
try:
|
||||||
limit_up_count = 0
|
realtime_limit_up_count = 0
|
||||||
limit_down_count = 0
|
realtime_limit_down_count = 0
|
||||||
|
|
||||||
for fs, threshold in [
|
for fs, threshold in [
|
||||||
("m:0+t:6,m:0+t:80,m:0+t:81+s:2048", 9.9), # 主板 10%
|
("m:0+t:6,m:0+t:80,m:0+t:81+s:2048", 9.9), # 主板 10%
|
||||||
@ -84,7 +84,7 @@ async def intraday_market_temperature(prev_temp: MarketTemperature) -> MarketTem
|
|||||||
if pct == "-" or pct is None:
|
if pct == "-" or pct is None:
|
||||||
continue
|
continue
|
||||||
if float(pct) >= threshold:
|
if float(pct) >= threshold:
|
||||||
limit_up_count += 1
|
realtime_limit_up_count += 1
|
||||||
|
|
||||||
# 跌停:按涨幅升序取 top 200
|
# 跌停:按涨幅升序取 top 200
|
||||||
params_down = {
|
params_down = {
|
||||||
@ -102,8 +102,10 @@ async def intraday_market_temperature(prev_temp: MarketTemperature) -> MarketTem
|
|||||||
if pct == "-" or pct is None:
|
if pct == "-" or pct is None:
|
||||||
continue
|
continue
|
||||||
if float(pct) <= neg_threshold:
|
if float(pct) <= neg_threshold:
|
||||||
limit_down_count += 1
|
realtime_limit_down_count += 1
|
||||||
|
|
||||||
|
limit_up_count = realtime_limit_up_count
|
||||||
|
limit_down_count = realtime_limit_down_count
|
||||||
logger.info(f"东方财富盘中涨跌停: 涨停={limit_up_count} 跌停={limit_down_count}")
|
logger.info(f"东方财富盘中涨跌停: 涨停={limit_up_count} 跌停={limit_down_count}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"东方财富涨跌停统计失败,使用基线数据: {e}")
|
logger.warning(f"东方财富涨跌停统计失败,使用基线数据: {e}")
|
||||||
|
|||||||
@ -26,6 +26,23 @@ def calculate_market_temperature(trade_date: str = None) -> MarketTemperature:
|
|||||||
# 1. 涨跌家数
|
# 1. 涨跌家数
|
||||||
daily_df = tushare_client.get_daily_all(trade_date)
|
daily_df = tushare_client.get_daily_all(trade_date)
|
||||||
if daily_df.empty:
|
if daily_df.empty:
|
||||||
|
original_trade_date = trade_date
|
||||||
|
trade_dates = tushare_client.get_trade_dates()
|
||||||
|
fallback_dates = [d for d in trade_dates if d < trade_date][-5:]
|
||||||
|
for fallback_date in reversed(fallback_dates):
|
||||||
|
fallback_df = tushare_client.get_daily_all(fallback_date)
|
||||||
|
if not fallback_df.empty:
|
||||||
|
daily_df = fallback_df
|
||||||
|
trade_date = fallback_date
|
||||||
|
logger.warning(
|
||||||
|
"市场温度 %s 日线数据为空,回退到最近有效交易日 %s",
|
||||||
|
original_trade_date,
|
||||||
|
fallback_date,
|
||||||
|
)
|
||||||
|
break
|
||||||
|
|
||||||
|
if daily_df.empty:
|
||||||
|
logger.warning("市场温度 %s 无有效日线数据,返回占位温度", trade_date)
|
||||||
return MarketTemperature(trade_date=trade_date, temperature=50)
|
return MarketTemperature(trade_date=trade_date, temperature=50)
|
||||||
|
|
||||||
up_count = len(daily_df[daily_df["pct_chg"] > 0])
|
up_count = len(daily_df[daily_df["pct_chg"] > 0])
|
||||||
|
|||||||
Binary file not shown.
@ -21,6 +21,12 @@ _scan_lock = asyncio.Lock()
|
|||||||
_scan_running = False
|
_scan_running = False
|
||||||
|
|
||||||
|
|
||||||
|
def _has_valid_market_breadth(market_temp: MarketTemperature | None) -> bool:
|
||||||
|
if not market_temp:
|
||||||
|
return False
|
||||||
|
return (market_temp.up_count or 0) + (market_temp.down_count or 0) > 0
|
||||||
|
|
||||||
|
|
||||||
async def refresh_recommendations(trade_date: str = None, scan_session: str = "manual") -> dict:
|
async def refresh_recommendations(trade_date: str = None, scan_session: str = "manual") -> dict:
|
||||||
"""刷新推荐列表(带扫描锁防止并发)"""
|
"""刷新推荐列表(带扫描锁防止并发)"""
|
||||||
global _scan_running
|
global _scan_running
|
||||||
@ -633,23 +639,32 @@ async def _save_to_db(result: dict):
|
|||||||
# 保存市场温度
|
# 保存市场温度
|
||||||
mt = result.get("market_temp")
|
mt = result.get("market_temp")
|
||||||
if mt:
|
if mt:
|
||||||
# 使用 INSERT OR REPLACE 确保重复扫描能更新数据
|
if _has_valid_market_breadth(mt):
|
||||||
stmt = text(
|
# 使用 INSERT OR REPLACE 确保重复扫描能更新数据
|
||||||
"INSERT OR REPLACE INTO market_temperature "
|
stmt = text(
|
||||||
"(trade_date, up_count, down_count, limit_up_count, limit_down_count, "
|
"INSERT OR REPLACE INTO market_temperature "
|
||||||
"max_streak, broken_rate, temperature) "
|
"(trade_date, up_count, down_count, limit_up_count, limit_down_count, "
|
||||||
"VALUES (:td, :up, :down, :lu, :ld, :ms, :br, :temp)"
|
"max_streak, broken_rate, temperature) "
|
||||||
)
|
"VALUES (:td, :up, :down, :lu, :ld, :ms, :br, :temp)"
|
||||||
await db.execute(stmt, {
|
)
|
||||||
"td": mt.trade_date,
|
await db.execute(stmt, {
|
||||||
"up": mt.up_count,
|
"td": mt.trade_date,
|
||||||
"down": mt.down_count,
|
"up": mt.up_count,
|
||||||
"lu": mt.limit_up_count,
|
"down": mt.down_count,
|
||||||
"ld": mt.limit_down_count,
|
"lu": mt.limit_up_count,
|
||||||
"ms": mt.max_streak,
|
"ld": mt.limit_down_count,
|
||||||
"br": mt.broken_rate,
|
"ms": mt.max_streak,
|
||||||
"temp": mt.temperature,
|
"br": mt.broken_rate,
|
||||||
})
|
"temp": mt.temperature,
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
logger.warning(
|
||||||
|
"跳过无效市场温度快照: trade_date=%s temperature=%s up=%s down=%s",
|
||||||
|
mt.trade_date,
|
||||||
|
mt.temperature,
|
||||||
|
mt.up_count,
|
||||||
|
mt.down_count,
|
||||||
|
)
|
||||||
|
|
||||||
# 保存板块热度(先清除同一 trade_date 的旧数据,再批量插入)
|
# 保存板块热度(先清除同一 trade_date 的旧数据,再批量插入)
|
||||||
trade_date_val = mt.trade_date if mt else ""
|
trade_date_val = mt.trade_date if mt else ""
|
||||||
@ -769,7 +784,8 @@ async def _load_today_from_db() -> dict:
|
|||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
text(
|
text(
|
||||||
"SELECT * FROM market_temperature "
|
"SELECT * FROM market_temperature "
|
||||||
"ORDER BY REPLACE(trade_date, '-', '') DESC, id DESC LIMIT 1"
|
"ORDER BY CASE WHEN COALESCE(up_count, 0) + COALESCE(down_count, 0) > 0 THEN 0 ELSE 1 END, "
|
||||||
|
"REPLACE(trade_date, '-', '') DESC, id DESC LIMIT 1"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
mt_row = result.fetchone()
|
mt_row = result.fetchone()
|
||||||
|
|||||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user