"""前置策略匹配核心逻辑 本模块仅根据人工选择的大盘周期、阶段、趋势强弱, 查询匹配绑定表并输出可用账户与策略。 不做任何 K 线识别、箱体判断、点位计算或突破校验。 """ from sqlalchemy.orm import Session, joinedload from app.models import MarketRegime, RegimeMatch from app.schemas import MatchRequest, MatchResult, MatchAccountOut, MatchStrategyOut def run_match(db: Session, req: MatchRequest) -> MatchResult: """执行前置匹配""" regime = db.query(MarketRegime).filter(MarketRegime.id == req.market_regime_id).first() if not regime: return MatchResult( market_cycle=req.market_cycle, regime_name="未知", trade_type="", allow_direction="", trend_strength=req.trend_strength, status="disabled", message="大盘阶段不存在", ) base = dict( market_cycle=req.market_cycle, regime_name=regime.name, trade_type=regime.trade_type, allow_direction=regime.allow_direction, trend_strength=req.trend_strength, ) # 震荡 → 全部禁用 if req.trend_strength == "震荡": return MatchResult( **base, status="watch", message="趋势强弱为「震荡」,全部策略禁用,建议观望", ) # 宽幅震荡阶段 → 观望 if regime.trade_type == "观望" or regime.allow_direction == "禁止": return MatchResult( **base, status="watch", message=f"大盘阶段「{regime.name}」为观望阶段,禁止交易", ) # 查询匹配绑定 matches = ( db.query(RegimeMatch) .options( joinedload(RegimeMatch.account), joinedload(RegimeMatch.strategy), ) .filter( RegimeMatch.market_regime_id == req.market_regime_id, RegimeMatch.market_cycle == req.market_cycle, RegimeMatch.trend_strength == req.trend_strength, ) .all() ) if not matches: return MatchResult( **base, status="disabled", message="未找到匹配的账户/策略绑定,请在配置中心添加匹配规则", ) # 过滤:仅保留已启用账户 accounts_out = [] strategies_out = [] seen_acc = set() seen_strat = set() for m in matches: if not m.account or m.account.enable != 1: continue # 趋势强弱过滤(双重保险) strat = m.strategy if not strat: continue if not _strength_compatible(req.trend_strength, strat.fit_trend_strength): continue direction = m.force_direction or regime.allow_direction if m.account_id not in seen_acc: seen_acc.add(m.account_id) accounts_out.append(MatchAccountOut( id=m.account.id, account_name=m.account.account_name, total_capital=m.account.total_capital, trade_cycle=m.account.trade_cycle, risk_ratio=m.account.risk_ratio, force_direction=direction, )) if m.strategy_id not in seen_strat: seen_strat.add(m.strategy_id) strategies_out.append(MatchStrategyOut( id=strat.id, strategy_name=strat.strategy_name, fit_cycle=strat.fit_cycle, strategy_rule=strat.strategy_rule, force_direction=direction, )) if not accounts_out: return MatchResult( **base, status="disabled", message="无可用账户(可能全部被禁用或不匹配当前趋势强弱)", ) return MatchResult( **base, status="ok", message="匹配成功,以下为前置策略匹配结果(箱体/点位/突破条件需人工确认)", accounts=accounts_out, strategies=strategies_out, ) def _strength_compatible(selected: str, fit: str) -> bool: """判断趋势强弱是否与策略适配""" if fit == "全部": return True if selected == "强" and fit == "强": return True if selected == "弱" and fit == "弱": return True return False