老师好
在学习vnpy过程中,遇到组合策略出现创建策略失败,报找不到策略(策略是vnpy自带的),但是用cta策略(vnpy自带的)调试正常的。不知道组合策略哪里出问题了,麻烦有空帮忙解答下,谢谢!

老师好
在学习vnpy过程中,遇到组合策略出现创建策略失败,报找不到策略(策略是vnpy自带的),但是用cta策略(vnpy自带的)调试正常的。不知道组合策略哪里出问题了,麻烦有空帮忙解答下,谢谢!

老师好
1.用cta策略(vnpy自带的)调试正常的,意思就是用CTA引擎加载策略正常的

2.我换了个组合策略加载还是不行,这里得到空,导致找不到策略

从你图上看,portfolio_engine.init_engine后面好像没加括号
在使用组合策略vnpy_portfoliostrategy 也遇到了类似的问题,执行了init_engine 之后 self.strategies 仍然为空,策略添加一直失败:
def add_strategy(
self, class_name: str, strategy_name: str, vt_symbols: list, setting: dict
) -> None:
"""添加策略实例"""
if strategy_name in self.strategies:
self.writelog(("创建策略失败,存在重名{}").format(strategy_name))
return
strategy_class: type[StrategyTemplate] | None = self.classes.get(class_name, None)
if not strategy_class:
self.write_log(_("创建策略失败,找不到策略类{}").format(class_name)) **《==============这里找不到strategy_class**
return
反复排查之后发现,问题原因是策略文件中引入了一个自定义kline.py(和策略文件在同一目录下)文件:
from kline import TrendFlag, KLineType, KLine
该文件在回测时一直在使用,不存在语法或者编译问题,其中只定义了几个枚举类和K线类,对外部的依赖只有这行:from enum import IntEnum,把 kline.py 的代码复制到策略文件中就好了,暂时没想明白是什么原因。
恳请大佬解惑,也希望能帮到遇到类似问题的朋友们。
我来帮你分析这个问题。这涉及到 VeighNa 组合策略模块的策略加载机制。让我先查询相关文档和源代码。
这是一个非常典型且容易踩坑的问题!让我详细解释一下根本原因:
从 vnpy_portfoliostrategy 的引擎源代码(engine.py)可以看到策略加载的核心逻辑:
def load_strategy_class_from_module(self, module_name: str) -> None:
"""通过策略文件加载策略类"""
try:
module: ModuleType = importlib.import_module(module_name)
# ... 查找策略类并注册到 self.classes
except: # noqa
msg: str = _("策略文件{}加载失败,触发异常:\n{}").format(module_name, traceback.format_exc())
self.write_log(msg)
关键问题在这里:
当引擎使用 importlib.import_module() 加载策略文件时,Python 的模块搜索路径(sys.path)决定了能否找到依赖的模块。
你的目录结构大概是:
strategies/
├── your_strategy.py # 策略文件
└── kline.py # 自定义模块
在策略文件中你使用了:
from kline import TrendFlag, KLineType, KLine
问题场景:
| 场景 | 结果 |
|---|---|
| 回测时直接运行策略文件 | ✅ 正常,因为当前工作目录包含 strategies/ |
| 通过 VeighNa 引擎加载 | ❌ 失败,因为 importlib.import_module 的上下文不同 |
注意代码中的 except: # noqa,这会导致:
kline 模块失败ModuleNotFoundError 或 ImportErrorself.classes将 kline.py 的内容复制到策略文件中后:
kline 模块importlib 加载self.classes将相对导入改为绝对导入,并确保 strategies 目录在 Python 路径中:
在策略文件顶部添加:
import sys
from pathlib import Path
# 将当前目录添加到 Python 路径
sys.path.insert(0, str(Path(__file__).parent))
from kline import TrendFlag, KLineType, KLine
将 strategies 目录变为 Python 包:
strategies/
├── __init__.py # 空文件,标记为包
├── your_strategy.py
└── kline.py
然后在策略文件中使用相对导入:
from .kline import TrendFlag, KLineType, KLine
注意: 需要修改引擎代码支持从包中加载策略,或者使用 -m 参数运行。
将 kline.py 放到 VeighNa 能识别的位置,例如:
vnpy_portfoliostrategy/ 目录下在策略类内部延迟导入:
class YourStrategy(StrategyTemplate):
def on_init(self):
# 在初始化时才导入
from kline import TrendFlag, KLineType, KLine
# ...
如果你想确认具体的导入错误,可以临时修改引擎代码来查看详细错误信息:
# 在 engine.py 的 load_strategy_class_from_module 方法中
def load_strategy_class_from_module(self, module_name: str) -> None:
try:
module: ModuleType = importlib.import_module(module_name)
# ...
except Exception as e:
import traceback
print(f"=== 策略加载失败: {module_name} ===")
print(traceback.format_exc()) # 打印完整堆栈
msg: str = _("策略文件{}加载失败,触发异常:\n{}").format(module_name, traceback.format_exc())
self.write_log(msg)
| 问题原因 | 说明 |
|---|---|
| 模块搜索路径 | importlib.import_module 的上下文与直接运行不同 |
| 异常静默捕获 | 导入错误被 except: 捕获,只记录日志 |
| 策略类未注册 | 导入失败后,策略类无法被添加到 self.classes |
最佳实践建议:
sys.path 动态添加路径的方式希望这个分析能帮助你理解问题本质!