You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法实例化含抽象方法的抽象类:Backtest策略代码报错求助

问题排查:无法实例化BuyAndHold策略类

问题重现

编写了继承自Strategy的BuyAndHold量化回测策略类:

import pandas as pd

class BuyAndHold(Strategy):
    def __init__(self, data, buy_percentage, keep_buying_percentage, sell_percentage):
        Strategy.__init__(self)
        self.data = data
        self.buy_percentage = buy_percentage
        self.keep_buying_percentage = keep_buying_percentage
        self.sell_percentage = sell_percentage
        self.portfolio_history = []
    
    def buy_more_quantity(self, current_price, initial_buy_price, last_quantity):
        return int(last_quantity * 2)

    def next(self, portfolio, current_price, initial_buy_price, last_quantity, cash):
        if portfolio is None:
            # Initial buy
            buy_price = initial_buy_price * (1 - self.buy_percentage)
            buy_quantity = int(cash / buy_price)
            portfolio = buy_price * buy_quantity
            cash -= portfolio
            self.portfolio_history.append(portfolio + cash)
            return portfolio, cash, buy_quantity

        sell_price = initial_buy_price * (1 + self.sell_percentage)
        if current_price >= sell_price:
            portfolio = current_price * last_quantity
            cash += portfolio
            self.portfolio_history.append(portfolio + cash)
            return None, cash, 0

        keep_buying_price = initial_buy_price * (1 - self.keep_buying_percentage)
        if current_price <= keep_buying_price:
            buy_price = current_price
            buy_quantity = self.buy_more_quantity(current_price, initial_buy_price, last_quantity)
            portfolio = buy_price * buy_quantity
            cash -= portfolio
            self.portfolio_history.append(portfolio + cash)
            return portfolio, cash, buy_quantity

        self.portfolio_history.append(portfolio + cash)
        return portfolio, cash, last_quantity
               
    def stop(self):
        portfolio_value = 0
        portfolio_history = []
        for i, p in enumerate(self.portfolio):
            if 'sell_price' in p:
                portfolio_value += p['sell_price'] * p['quantity']
            else:
                portfolio_value += self.data.close[-(len(self.portfolio) - i)] * p['quantity']
            portfolio_history.append(portfolio_value)
        self.portfolio_history = pd.Series(portfolio_history, index=self.data.index)

执行回测初始化语句时:

bt = Backtest(data['Close']['XLB'], BuyAndHold(data['Close']['XLB'], buy_percentage=0.1, keep_buying_percentage=0.05, sell_percentage=0.1))

抛出错误:"Can't instantiate abstract class with abstract methods"

错误原因

Python抽象基类(ABC)要求子类必须完全实现所有标记为抽象的方法,否则无法实例化。BuyAndHold类继承自Strategy抽象类,但存在以下问题:

  • 未实现Strategy中定义的部分抽象方法
  • 已实现的方法(如next)参数签名与抽象类定义不一致,导致Python判定未正确实现该抽象方法

解决方案

步骤1:确认Strategy的抽象方法列表

用inspect模块查看Strategy类中所有必须实现的抽象方法:

import inspect
# 列出Strategy类的所有抽象方法
abstract_methods = [name for name, _ in inspect.getmembers(Strategy, predicate=inspect.isabstractmethod)]
print("必须实现的抽象方法:", abstract_methods)

步骤2:补全或修正方法实现

根据输出的抽象方法列表,确保BuyAndHold类实现了每一个方法,且参数签名与抽象类定义完全一致:

  • 若Strategy的next方法定义为def next(self, data):,当前next的参数列表不符合要求,需调整参数和逻辑匹配框架规范
  • 检查stop方法的参数、返回值是否符合抽象类定义

步骤3:检查回测初始化方式(可选)

部分量化回测框架要求传入策略类而非已实例化的对象,正确初始化方式可能为:

bt = Backtest(data['Close']['XLB'], BuyAndHold, 
              params={"data": data['Close']['XLB'], 
                      "buy_percentage":0.1, 
                      "keep_buying_percentage":0.05, 
                      "sell_percentage":0.1})

具体需参照Backtest类的文档要求。

额外问题修复

stop方法中使用了self.portfolio但未在__init__中初始化,建议添加:

self.portfolio = []

内容的提问来源于stack exchange,提问作者Rajesh Nathani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 10:25:22