first commit
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
"""前置策略匹配核心逻辑
|
||||
|
||||
本模块仅根据人工选择的大盘周期、阶段、趋势强弱,
|
||||
查询匹配绑定表并输出可用账户与策略。
|
||||
不做任何 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
|
||||
Reference in New Issue
Block a user