fix: 修复复盘计划失败问题

refactor3.0
Lxy 1 week ago
parent 0ee6a3dab7
commit f663435843

@ -7,9 +7,6 @@ from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, declarative_base
from datetime import datetime
from app.mysql_database import MySQLSessionLocal
from app.storage_manager import get_storage_manager
logger = logging.getLogger(__name__)
# 数据目录
@ -31,38 +28,14 @@ AnalysisBase = declarative_base()
def get_analysis_db():
"""获取期货智析数据库会话。
根据 MySQL 可用性动态选择后端
- MySQL 可用时返回 MySQL Session
- MySQL 不可用时返回 SQLite Session兜底
分析数据量较小复盘计划评分等始终使用 SQLite 以保证稳定性
AnalysisBase 绑定的是 analysis_engine (SQLite)ORM 模型均基于此定义
"""
storage = get_storage_manager()
if MySQLSessionLocal is not None and storage.check_mysql():
db = None
try:
db = MySQLSessionLocal()
yield db
except Exception as e:
logger.warning(f"创建 MySQL analysis session 失败,降级到 SQLite: {e}")
if db is not None:
try:
db.close()
except Exception:
pass
db = AnalysisSessionLocal()
yield db
finally:
if db is not None:
try:
db.close()
except Exception:
pass
else:
db = AnalysisSessionLocal()
try:
yield db
finally:
db.close()
db = AnalysisSessionLocal()
try:
yield db
finally:
db.close()
def init_analysis_db():

@ -626,121 +626,126 @@ def save_plan_to_db(db: Session, plan_data: dict) -> int:
review_date_str = plan_data["review_date"]
week_day = plan_data["week_day"]
# 清理旧数据
existing = db.query(ReviewPlanV2).filter_by(review_date=review_date_str).first()
if existing:
review_plan_id = existing.id
# 清理关联数据
db.query(SymbolScoreV2).filter_by(review_date_id=review_plan_id).delete()
db.query(TradingPlanV2).filter_by(review_date_id=review_plan_id).delete()
db.query(SectorHeat).filter_by(review_date_id=review_plan_id).delete()
# 更新元数据
existing.week_day = week_day
existing.data_basis = plan_data.get("data_basis")
existing.core_conclusion = plan_data.get("core_conclusion")
existing.bull_count = plan_data.get("bull_count")
existing.bear_count = plan_data.get("bear_count")
existing.neutral_count = plan_data.get("neutral_count")
existing.opportunity_count = plan_data.get("opportunity_count")
existing.risk_warnings = plan_data.get("risk_warnings")
existing.actual_data_date = plan_data.get("actual_data_date")
existing.data_date_matches = 1 if plan_data.get("data_date_matches") else 0
else:
review_plan = ReviewPlanV2(
review_date=review_date_str,
week_day=week_day,
data_basis=plan_data.get("data_basis"),
core_conclusion=plan_data.get("core_conclusion"),
bull_count=plan_data.get("bull_count"),
bear_count=plan_data.get("bear_count"),
neutral_count=plan_data.get("neutral_count"),
opportunity_count=plan_data.get("opportunity_count"),
risk_warnings=plan_data.get("risk_warnings"),
actual_data_date=plan_data.get("actual_data_date"),
data_date_matches=1 if plan_data.get("data_date_matches") else 0,
)
db.add(review_plan)
db.flush()
review_plan_id = review_plan.id
# 保存评分数据
for s in plan_data.get("scores", []):
pivots = s.get("pivots", {})
score_record = SymbolScoreV2(
review_date_id=review_plan_id,
symbol=s["symbol"],
name=s["name"],
close_price=s.get("close_price"),
prev_close=s.get("prev_close"),
high_price=s.get("high_price"),
low_price=s.get("low_price"),
volume=s.get("volume"),
avg_volume_5=s.get("avg_volume_5"),
amplitude_score=s.get("amplitude_score"),
volume_score=s.get("volume_score"),
change_score=s.get("change_score"),
trend_score=s.get("trend_score"),
activity_score=s.get("activity_score"),
composite_score=s.get("composite_score"),
amplitude_pct=s.get("amplitude_pct"),
change_pct=s.get("change_pct"),
volume_ratio=s.get("volume_ratio"),
trend_60m=s.get("trend_60m"),
trend_15m=s.get("trend_15m"),
trend_5m=s.get("trend_5m"),
direction=s.get("direction"),
direction_tag=s.get("direction_tag"),
category=s.get("category"),
pivot=pivots.get("pivot"),
r1=pivots.get("r1"),
r2=pivots.get("r2"),
s1=pivots.get("s1"),
s2=pivots.get("s2"),
rank=s.get("rank"),
data_date=s.get("data_date"),
)
db.add(score_record)
# 保存交易计划
for p in plan_data.get("plans", []):
plan_record = TradingPlanV2(
review_date_id=review_plan_id,
symbol=p["symbol"],
name=p["name"],
direction=p["direction"],
composite_score=p.get("composite_score"),
entry_low=p.get("entry_low"),
entry_high=p.get("entry_high"),
stop_loss=p.get("stop_loss"),
target1=p.get("target1"),
target2=p.get("target2"),
trigger=p.get("trigger"),
amplitude_score=p.get("amplitude_score"),
volume_score=p.get("volume_score"),
trend_score=p.get("trend_score"),
activity_score=p.get("activity_score"),
category=p.get("category"),
)
db.add(plan_record)
# 保存板块热度
for sec in plan_data.get("sectors", []):
sector_record = SectorHeat(
review_date_id=review_plan_id,
sector_name=sec["sector_name"],
avg_score=sec.get("avg_score"),
avg_trend=sec.get("avg_trend"),
direction=sec.get("direction"),
heat_level=sec.get("heat_level"),
leader_symbol=sec.get("leader_symbol"),
leader_score=sec.get("leader_score"),
members=sec.get("members"),
)
db.add(sector_record)
db.commit()
logger.info(f"交易计划已保存: {review_date_str}, ID={review_plan_id}")
return review_plan_id
try:
# 清理旧数据
existing = db.query(ReviewPlanV2).filter_by(review_date=review_date_str).first()
if existing:
review_plan_id = existing.id
# 清理关联数据
db.query(SymbolScoreV2).filter_by(review_date_id=review_plan_id).delete()
db.query(TradingPlanV2).filter_by(review_date_id=review_plan_id).delete()
db.query(SectorHeat).filter_by(review_date_id=review_plan_id).delete()
# 更新元数据
existing.week_day = week_day
existing.data_basis = plan_data.get("data_basis")
existing.core_conclusion = plan_data.get("core_conclusion")
existing.bull_count = plan_data.get("bull_count")
existing.bear_count = plan_data.get("bear_count")
existing.neutral_count = plan_data.get("neutral_count")
existing.opportunity_count = plan_data.get("opportunity_count")
existing.risk_warnings = plan_data.get("risk_warnings")
existing.actual_data_date = plan_data.get("actual_data_date")
existing.data_date_matches = 1 if plan_data.get("data_date_matches") else 0
else:
review_plan = ReviewPlanV2(
review_date=review_date_str,
week_day=week_day,
data_basis=plan_data.get("data_basis"),
core_conclusion=plan_data.get("core_conclusion"),
bull_count=plan_data.get("bull_count"),
bear_count=plan_data.get("bear_count"),
neutral_count=plan_data.get("neutral_count"),
opportunity_count=plan_data.get("opportunity_count"),
risk_warnings=plan_data.get("risk_warnings"),
actual_data_date=plan_data.get("actual_data_date"),
data_date_matches=1 if plan_data.get("data_date_matches") else 0,
)
db.add(review_plan)
db.flush()
review_plan_id = review_plan.id
# 保存评分数据
for s in plan_data.get("scores", []):
pivots = s.get("pivots", {})
score_record = SymbolScoreV2(
review_date_id=review_plan_id,
symbol=s["symbol"],
name=s["name"],
close_price=s.get("close_price"),
prev_close=s.get("prev_close"),
high_price=s.get("high_price"),
low_price=s.get("low_price"),
volume=s.get("volume"),
avg_volume_5=s.get("avg_volume_5"),
amplitude_score=s.get("amplitude_score"),
volume_score=s.get("volume_score"),
change_score=s.get("change_score"),
trend_score=s.get("trend_score"),
activity_score=s.get("activity_score"),
composite_score=s.get("composite_score"),
amplitude_pct=s.get("amplitude_pct"),
change_pct=s.get("change_pct"),
volume_ratio=s.get("volume_ratio"),
trend_60m=s.get("trend_60m"),
trend_15m=s.get("trend_15m"),
trend_5m=s.get("trend_5m"),
direction=s.get("direction"),
direction_tag=s.get("direction_tag"),
category=s.get("category"),
pivot=pivots.get("pivot"),
r1=pivots.get("r1"),
r2=pivots.get("r2"),
s1=pivots.get("s1"),
s2=pivots.get("s2"),
rank=s.get("rank"),
data_date=s.get("data_date"),
)
db.add(score_record)
# 保存交易计划
for p in plan_data.get("plans", []):
plan_record = TradingPlanV2(
review_date_id=review_plan_id,
symbol=p["symbol"],
name=p["name"],
direction=p["direction"],
composite_score=p.get("composite_score"),
entry_low=p.get("entry_low"),
entry_high=p.get("entry_high"),
stop_loss=p.get("stop_loss"),
target1=p.get("target1"),
target2=p.get("target2"),
trigger=p.get("trigger"),
amplitude_score=p.get("amplitude_score"),
volume_score=p.get("volume_score"),
trend_score=p.get("trend_score"),
activity_score=p.get("activity_score"),
category=p.get("category"),
)
db.add(plan_record)
# 保存板块热度
for sec in plan_data.get("sectors", []):
sector_record = SectorHeat(
review_date_id=review_plan_id,
sector_name=sec["sector_name"],
avg_score=sec.get("avg_score"),
avg_trend=sec.get("avg_trend"),
direction=sec.get("direction"),
heat_level=sec.get("heat_level"),
leader_symbol=sec.get("leader_symbol"),
leader_score=sec.get("leader_score"),
members=sec.get("members"),
)
db.add(sector_record)
db.commit()
logger.info(f"交易计划已保存: {review_date_str}, ID={review_plan_id}")
return review_plan_id
except Exception as e:
db.rollback()
logger.exception(f"保存交易计划失败: {e}")
raise
def get_plan_data(db: Session, review_plan_id: int) -> Optional[dict]:

Binary file not shown.
Loading…
Cancel
Save