diff --git a/application/rebalance_service.py b/application/rebalance_service.py index b289778..a09e63d 100644 --- a/application/rebalance_service.py +++ b/application/rebalance_service.py @@ -16,84 +16,17 @@ from notifications.events import NotificationPublisher from notifications import renderers as notification_renderers from quant_platform_kit.common.models import PortfolioSnapshot, Position +from quant_platform_kit.common.notification_localization import ( + localize_notification_text as _base_localize_notification_text, + translator_uses_zh as _base_translator_uses_zh, +) from quant_platform_kit.common.port_adapters import CallableNotificationPort, CallablePortfolioPort -_ZH_REASON_REPLACEMENTS = ( - ("feature snapshot guard blocked execution", "特征快照校验阻止执行"), - ("feature snapshot required", "需要特征快照"), - ("feature snapshot compute failed", "特征快照计算失败"), - ("feature_snapshot_download_failed", "特征快照下载失败"), - ("feature_snapshot_compute_failed", "特征快照计算失败"), - ("feature_snapshot_path_missing", "缺少特征快照路径"), - ("feature_snapshot_missing", "特征快照不存在"), - ("feature_snapshot_stale", "特征快照过旧"), - ("feature_snapshot_manifest_missing", "缺少快照清单"), - ("feature_snapshot_profile_mismatch", "快照策略名不匹配"), - ("feature_snapshot_config_name_mismatch", "快照配置名不匹配"), - ("feature_snapshot_config_path_mismatch", "快照配置路径不匹配"), - ("feature_snapshot_contract_version_mismatch", "快照契约版本不匹配"), - ("soxl_soxx_trend_income", "SOXL/SOXX 半导体趋势收益"), - ("tqqq_growth_income", "TQQQ 增长收益"), - ("global_etf_rotation", "全球 ETF 轮动"), - ("russell_1000_multi_factor_defensive", "罗素1000多因子"), - ("tech_communication_pullback_enhancement", "科技通信回调增强"), - ("qqq_tech_enhancement", "科技通信回调增强"), - ("mega_cap_leader_rotation_aggressive", "Mega Cap 激进龙头轮动"), - ("mega_cap_leader_rotation_dynamic_top20", "Mega Cap 动态 Top20 龙头轮动"), - ("mega_cap_leader_rotation_top50_balanced", "Mega Cap Top50 平衡龙头轮动"), - ("dynamic_mega_leveraged_pullback", "Mega Cap 2x 回调策略"), - ("outside_monthly_execution_window", "当前不在月度执行窗口"), - ("no_execution_window_after_snapshot", "快照后没有可用执行窗口"), - ("no-op", "不执行"), - ("monthly snapshot cadence", "月度快照节奏"), - ("waiting inside execution window", "等待进入执行窗口"), - ("small_account_warning=true", "小账户提示=是"), - ("portfolio_equity=", "净值="), - ("min_recommended_equity=", "建议最低净值="), - ( - "integer_shares_min_position_value_may_prevent_backtest_replication", - "整数股和最小仓位限制可能导致实盘无法完全复现回测", - ), - ( - "integer-share minimum position sizing may prevent backtest replication", - "整数股和最小仓位限制可能导致实盘无法完全复现回测", - ), - ("small account warning: portfolio equity", "小账户提示:净值"), - ("small account warning", "小账户提示"), - ("is below the recommended", "低于建议"), - ("is below recommended", "低于建议"), - ("snapshot_as_of=", "快照日期="), - ("snapshot=", "快照日期="), - ("allowed=", "允许日期="), - ("", "未知"), - ("", "无"), - ("RISK-ON", "风险开启"), - ("DE-LEVER", "降杠杆"), - ("regime=hard_defense", "市场阶段=强防御"), - ("regime=soft_defense", "市场阶段=软防御"), - ("regime=risk_on", "市场阶段=进攻"), - ("benchmark_trend=down", "基准趋势=向下"), - ("benchmark_trend=up", "基准趋势=向上"), - ("benchmark=down", "基准趋势=向下"), - ("benchmark=up", "基准趋势=向上"), - ("breadth=", "市场宽度="), - ("target_stock=", "目标股票仓位="), - ("realized_stock=", "实际股票仓位="), - ("stock_exposure=", "股票目标仓位="), - ("safe_haven=", "避险仓位="), - ("selected=", "入选标的数="), - ("top=", "前排标的="), - ("no_selection", "无入选标的"), - ("outside_execution_window", "当前不在执行窗口"), +_EXTRA_ZH_REASON_REPLACEMENTS = ( ("pending_orders_detected", "检测到未完成订单"), ("same_day_execution_locked", "当日执行锁已存在"), ("same_day_fills_detected", "检测到当日成交"), - ("insufficient_buying_power", "购买力不足"), - ("missing_price", "缺少报价"), - ("no_equity", "无净值"), - ("fail_closed", "关闭执行"), - ("reason=", "原因="), ("fail_reason=", "失败原因="), ("decision=", "决策="), ) @@ -117,18 +50,15 @@ def _format_symbol_preview(symbols, *, limit: int = 3) -> str: def _translator_uses_zh(translator) -> bool: - sample = str(translator("no_trades")) - return any("\u4e00" <= ch <= "\u9fff" for ch in sample) + return _base_translator_uses_zh(translator) def _localize_notification_text(text: str, *, translator) -> str: - value = str(text or "").strip() - if not value or not _translator_uses_zh(translator): - return value - localized = value - for source, target in _ZH_REASON_REPLACEMENTS: - localized = localized.replace(source, target) - return localized + return _base_localize_notification_text( + text, + translator=translator, + extra_replacements=_EXTRA_ZH_REASON_REPLACEMENTS, + ) def _render_notification_context_text( diff --git a/notifications/renderers.py b/notifications/renderers.py index 21b7548..7de5b59 100644 --- a/notifications/renderers.py +++ b/notifications/renderers.py @@ -6,83 +6,15 @@ import re from notifications.events import RenderedNotification +from quant_platform_kit.common.notification_localization import ( + localize_notification_text as _base_localize_notification_text, + translator_uses_zh as _base_translator_uses_zh, +) - -_ZH_REASON_REPLACEMENTS = ( - ("feature snapshot guard blocked execution", "特征快照校验阻止执行"), - ("feature snapshot required", "需要特征快照"), - ("feature snapshot compute failed", "特征快照计算失败"), - ("feature_snapshot_download_failed", "特征快照下载失败"), - ("feature_snapshot_compute_failed", "特征快照计算失败"), - ("feature_snapshot_path_missing", "缺少特征快照路径"), - ("feature_snapshot_missing", "特征快照不存在"), - ("feature_snapshot_stale", "特征快照过旧"), - ("feature_snapshot_manifest_missing", "缺少快照清单"), - ("feature_snapshot_profile_mismatch", "快照策略名不匹配"), - ("feature_snapshot_config_name_mismatch", "快照配置名不匹配"), - ("feature_snapshot_config_path_mismatch", "快照配置路径不匹配"), - ("feature_snapshot_contract_version_mismatch", "快照契约版本不匹配"), - ("soxl_soxx_trend_income", "SOXL/SOXX 半导体趋势收益"), - ("tqqq_growth_income", "TQQQ 增长收益"), - ("global_etf_rotation", "全球 ETF 轮动"), - ("russell_1000_multi_factor_defensive", "罗素1000多因子"), - ("tech_communication_pullback_enhancement", "科技通信回调增强"), - ("qqq_tech_enhancement", "科技通信回调增强"), - ("mega_cap_leader_rotation_aggressive", "Mega Cap 激进龙头轮动"), - ("mega_cap_leader_rotation_dynamic_top20", "Mega Cap 动态 Top20 龙头轮动"), - ("mega_cap_leader_rotation_top50_balanced", "Mega Cap Top50 平衡龙头轮动"), - ("dynamic_mega_leveraged_pullback", "Mega Cap 2x 回调策略"), - ("outside_monthly_execution_window", "当前不在月度执行窗口"), - ("no_execution_window_after_snapshot", "快照后没有可用执行窗口"), - ("no-op", "不执行"), - ("monthly snapshot cadence", "月度快照节奏"), - ("waiting inside execution window", "等待进入执行窗口"), - ("small_account_warning=true", "小账户提示=是"), - ("portfolio_equity=", "净值="), - ("min_recommended_equity=", "建议最低净值="), - ( - "integer_shares_min_position_value_may_prevent_backtest_replication", - "整数股和最小仓位限制可能导致实盘无法完全复现回测", - ), - ( - "integer-share minimum position sizing may prevent backtest replication", - "整数股和最小仓位限制可能导致实盘无法完全复现回测", - ), - ("small account warning: portfolio equity", "小账户提示:净值"), - ("small account warning", "小账户提示"), - ("is below the recommended", "低于建议"), - ("is below recommended", "低于建议"), - ("snapshot_as_of=", "快照日期="), - ("snapshot=", "快照日期="), - ("allowed=", "允许日期="), - ("", "未知"), - ("", "无"), - ("RISK-ON", "风险开启"), - ("DE-LEVER", "降杠杆"), - ("regime=hard_defense", "市场阶段=强防御"), - ("regime=soft_defense", "市场阶段=软防御"), - ("regime=risk_on", "市场阶段=进攻"), - ("benchmark_trend=down", "基准趋势=向下"), - ("benchmark_trend=up", "基准趋势=向上"), - ("benchmark=down", "基准趋势=向下"), - ("benchmark=up", "基准趋势=向上"), - ("breadth=", "市场宽度="), - ("target_stock=", "目标股票仓位="), - ("realized_stock=", "实际股票仓位="), - ("stock_exposure=", "股票目标仓位="), - ("safe_haven=", "避险仓位="), - ("selected=", "入选标的数="), - ("top=", "前排标的="), - ("no_selection", "无入选标的"), - ("outside_execution_window", "当前不在执行窗口"), +_EXTRA_ZH_REASON_REPLACEMENTS = ( ("pending_orders_detected", "检测到未完成订单"), ("same_day_execution_locked", "当日执行锁已存在"), ("same_day_fills_detected", "检测到当日成交"), - ("insufficient_buying_power", "购买力不足"), - ("missing_price", "缺少报价"), - ("no_equity", "无净值"), - ("fail_closed", "关闭执行"), - ("reason=", "原因="), ("fail_reason=", "失败原因="), ("decision=", "决策="), ) @@ -106,18 +38,15 @@ def _format_symbol_preview(symbols, *, limit: int = 3) -> str: def _translator_uses_zh(translator) -> bool: - sample = str(translator("no_trades")) - return any("\u4e00" <= ch <= "\u9fff" for ch in sample) + return _base_translator_uses_zh(translator) def _localize_notification_text(text: str, *, translator) -> str: - value = str(text or "").strip() - if not value or not _translator_uses_zh(translator): - return value - localized = value - for source, target in _ZH_REASON_REPLACEMENTS: - localized = localized.replace(source, target) - return localized + return _base_localize_notification_text( + text, + translator=translator, + extra_replacements=_EXTRA_ZH_REASON_REPLACEMENTS, + ) def _split_detail_segment(text: str) -> list[str]: diff --git a/requirements.txt b/requirements.txt index ae849a5..4b1cbff 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ flask gunicorn -quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@ac550fee3ca33bbf28c8a886848dede4e4e09a1b +quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@c24d4c52e84c8c696006532590b15e9be92c8d89 us-equity-strategies @ git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@9f55c58b6854ae700c47a684262eec10e763306a pandas numpy