title: 观察器 API description: 完整的观察器类 API 参考文档


观察器 API

Observer 类是用于监控策略执行和在回测期间收集数据的基类。观察器跟踪现金、价值、回撤、交易和其他绩效指标等指标。

与生成信号的指标不同,观察器主要用于记录和可视化策略状态。

类定义

class backtrader.Observer:
    """监控策略执行的基类。"""

```bash

## 核心属性

### `csv`

是否将观察器数据保存到 CSV 文件默认:`True`)。

```python
class MyObserver(bt.Observer):
    csv = True  # 包含在 CSV 输出中

```bash

### `plotinfo`

绘图配置字典

```python
plotinfo = dict(
    plot=True,       # 是否绘制此观察器
    subplot=True,    # 是否使用单独的子图
    plotname='',     # 图例中的名称

)

```bash

### `plotlines`

特定线条的绘图设置

```python
plotlines = dict(
    line1=dict(color='blue', linewidth=2),
    line2=dict(_plotskip=True),  # 跳过绘制此线条

)

```bash

### `_stclock`

控制时钟同步当为 `True` 观察器使用策略范围的时钟默认:`False`)。

### `_ltype`

线迭代器类型对于观察器设置为 `LineIterator.ObsType`(2)。

## 核心方法

### `__init__(self)`

在观察器初始化期间调用初始化跟踪变量并在需要时添加分析器

```python
def __init__(self):
    super().__init__()
    self._analyzers = list()

# 初始化跟踪变量
    self.peak = float('-inf')

```bash

### `start(self)`

在回测运行开始时调用

```python
def start(self):

# 在数据处理之前执行初始化
    self.initial_value = self._owner.broker.getvalue()

```bash

### `_start(self)`

内部方法确保在调用 `start()` 之前设置了所有者

### `prenext(self)`

在达到最小周期之前对每个 bar 调用默认情况下观察器在 prenext 期间调用 `next()`,以便从一开始跟踪所有 bar

```python
def prenext(self):
    self.next()  # 默认行为 - 处理每个 bar

```bash

### `next(self)`

对每个 bar 调用包含更新观察器值的主要逻辑

```python
def next(self):
    self.lines.cash[0] = self._owner.broker.getcash()

```bash

### `stop(self)`

回测结束后调用

### `_register_analyzer(self, analyzer)`

向此观察器注册一个分析器

## 线条系统

观察器使用与指标相同的线条系统

```python
class MyObserver(bt.Observer):
    lines = ('metric1', 'metric2')

    def next(self):
        self.lines.metric1[0] = calculate_metric1()
        self.lines.metric2[0] = calculate_metric2()

```bash

## 内置观察器

### 经纪商观察器

#### Cash

跟踪经纪商中的当前现金金额

```python
cerebro.addobserver(bt.observers.Cash)

```bash

- *线条**: `cash`

#### Value

跟踪包括现金在内的投资组合价值

```python
cerebro.addobserver(bt.observers.Value)

```bash

- *参数**:
- `fund`(默认:`None`)- 使用基金价值而非总价值

- *线条**: `value`

#### Broker

组合 Cash  Value 观察器

```python
cerebro.addobserver(bt.observers.Broker)

```bash

- *参数**:
- `fund`(默认:`None`)- 使用基金模式

- *线条**: `cash`, `value`

#### FundValue

跟踪类似基金的价值

- *线条**: `fundval`

#### FundShares

跟踪类似基金的份额

- *线条**: `fundshares`

### 回撤观察器

#### DrawDown

跟踪当前和最大回撤水平

```python
cerebro.addobserver(bt.observers.DrawDown)

```bash

- *参数**:
- `fund`(默认:`None`)- 使用基金模式计算收益

- *线条**:
- `drawdown` - 当前回撤百分比绘制
- `maxdrawdown` - 最大回撤不绘制

```python
class DrawDown(Observer):
    _stclock = True
    lines = ('drawdown', 'maxdrawdown')
    plotlines = dict(maxdrawdown=dict(_plotskip=True))

```bash

#### DrawDownLength

跟踪当前回撤长度和最大长度

- *线条**:
- `len` - 当前回撤长度
- `maxlen` - 最大回撤长度

### 交易观察器

#### Trades

跟踪已完成的交易并在交易关闭时绘制盈亏

```python
cerebro.addobserver(bt.observers.Trades)

```bash

- *参数**:
- `pnlcomm`(默认:`True`)- 显示扣除佣金后的净盈亏

- *线条**:
- `pnlplus` - 正盈亏值蓝色标记
- `pnlminus` - 负盈亏值红色标记

```python

# Trades 观察器跟踪:

# - 总交易计数

# - 多头/空头交易计数

# - 胜/负统计

# - 交易长度统计

```bash

#### DataTrades

分别跟踪多个数据源的盈亏

- *参数**:
- `usenames`(默认:`True`)- 使用数据名称作为标签

### BuySell 观察器

在图表上可视化买卖订单

```python
cerebro.addobserver(bt.observers.BuySell)

```bash

- *参数**:
- `barplot`(默认:`False`)-  bar 极值处绘制信号
- `bardist`(默认:`0.015`)- 距离高低点的距离1.5%

- *线条**:
- `buy` - 买入标记绿色向上三角形
- `sell` - 卖出标记红色向下三角形

```python

# 自定义标记外观

cerebro.addobserver(bt.observers.BuySell, barplot=True, bardist=0.02)

```bash

### 收益观察器

#### TimeReturn

跟踪随时间段变化的策略收益

```python
cerebro.addobserver(bt.observers.TimeReturn, timeframe=bt.TimeFrame.Days)

```bash

- *参数**:
- `timeframe`(默认:`None`)- 时间聚合周期
- `compression`(默认:`None`)- 日内时间框架的压缩
- `fund`(默认:`None`)- 使用基金模式

- *线条**: `timereturn`

```python

# 跟踪每日收益

cerebro.addobserver(bt.observers.TimeReturn, timeframe=bt.TimeFrame.Days)

# 跟踪每周收益

cerebro.addobserver(bt.observers.TimeReturn, timeframe=bt.TimeFrame.Weeks)

```bash

#### LogReturns

跟踪策略的对数收益

```python
cerebro.addobserver(bt.observers.LogReturns)

```bash

- *参数**:
- `timeframe`(默认:`None`)- 时间聚合周期
- `compression`(默认:`None`)- 日内时间框架的压缩
- `fund`(默认:`None`)- 使用基金模式

- *线条**: `logret1`

#### LogReturns2

扩展 LogReturns 以显示两个工具

- *线条**: `logret1`, `logret2`

### Benchmark 观察器

将策略收益与参考资产进行比较

```python
data = bt.feeds.GenericCSVData(dataname='benchmark.csv')
cerebro.adddata(data)
cerebro.addobserver(bt.observers.Benchmark, data=data)

```bash

- *参数**:
- `data`(默认:`None`)- 参考数据源
- `_doprenext`(默认:`False`)- 从数据开始时跟踪
- `firstopen`(默认:`False`)- 使用开盘价进行第一次比较
- `fund`(默认:`None`)- 使用基金模式

- *线条**: `benchmark`

### TradeLogger

全面的日志记录观察器用于所有交易活动

```python
cerebro.addobserver(bt.observers.TradeLogger,
                    log_dir='./logs',
                    log_orders=True,
                    log_trades=True,
                    log_positions=True,
                    log_indicators=True,
                    log_signals=True)

```bash

- *参数**:
- `log_dir`(默认:`'./logs'`)- 日志文件目录
- `log_orders`(默认:`True`)- 记录订单状态变化
- `log_trades`(默认:`True`)- 记录交易开仓/平仓
- `log_positions`(默认:`True`)- 每个 bar 记录持仓
- `log_indicators`(默认:`True`)- 每个 bar 记录指标值
- `log_signals`(默认:`True`)- 记录买卖信号
- `log_position_snapshot`(默认:`True`)- 将持仓快照保存为 YAML
- `snapshot_file`(默认:`'current_position.yaml'`)- 快照文件名
- `log_format`(默认:`'json'`)- 日志格式'json'  'text'
- `log_to_console`(默认:`False`)- 同时打印到控制台
- `mysql_enabled`(默认:`False`)- 启用 MySQL 日志记录
- `mysql_host`(默认:`'localhost'`)- MySQL 主机
- `mysql_port`(默认:`3306`)- MySQL 端口
- `mysql_user`(默认:`'root'`)- MySQL 用户
- `mysql_password`(默认:`''`)- MySQL 密码
- `mysql_database`(默认:`'backtrader'`)- MySQL 数据库

- *生成的文件**:
- `order.log` - 订单状态变化
- `trade.log` - 交易开仓和平仓
- `position.log` - 每个 bar 的持仓值
- `indicator.log` - 每个 bar 的指标值
- `signal.log` - 买卖信号
- `current_position.yaml` - 持仓快照

## 自定义观察器开发

### 基本观察器

```python
import backtrader as bt

class CustomMetric(bt.Observer):
    """
    跟踪自定义指标的观察器。
    """
    _stclock = True  # 使用策略时钟

    lines = ('custom_value',)

    params = (
        ('period', 20),
    )

    plotinfo = dict(
        plot=True,
        subplot=True,
        plotname='自定义指标',
    )

    def __init__(self):
        super().__init__()
        self.high_watermark = float('-inf')

    def next(self):

# 计算自定义指标
        value = self._owner.broker.getvalue()

# 跟踪历史最高点
        if value > self.high_watermark:
            self.high_watermark = value

# 存储到线条中
        self.lines.custom_value[0] = value - self.high_watermark

```bash

### 使用分析器的观察器

```python
class SharpeRatioObserver(bt.Observer):
    """
    使用分析器跟踪夏普比率的观察器。
    """
    _stclock = True

    lines = ('sharpe',)

    params = (
        ('period', 252),  # 年化周期
        ('riskfreerate', 0.0),
    )

    plotinfo = dict(plot=True, subplot=True)

    def __init__(self):
        super().__init__()

# 将分析器添加为从属
        self._sharpe = self._owner._addanalyzer_slave(
            bt.analyzers.SharpeRatio,
            period=self.p.period,
            riskfreerate=self.p.riskfreerate
        )

    def next(self):

# 从分析器获取当前夏普比率
        if hasattr(self._sharpe, 'rets') and self._sharpe.rets:
            self.lines.sharpe[0] = self._sharpe.rets.get('sharperatio', float('NaN'))

```bash

### 多线条观察器

```python
class PortfolioStats(bt.Observer):
    """
    跟踪多个投资组合统计指标的观察器。
    """
    _stclock = True

    lines = (
        'exposure',      # 敞口
        'leverage',      # 杠杆
        'cash_ratio',    # 现金比例
    )

    plotinfo = dict(plot=True, subplot=True)

    plotlines = dict(
        exposure=dict(color='blue'),
        leverage=dict(color='orange'),
        cash_ratio=dict(color='green'),
    )

    def next(self):
        portfolio_value = self._owner.broker.getvalue()
        cash = self._owner.broker.getcash()

# 计算指标
        self.lines.cash_ratio[0] = cash / portfolio_value if portfolio_value else 0
        self.lines.exposure[0] = 1 - self.lines.cash_ratio[0]

# 计算杠杆(总持仓价值 / 投资组合价值)
        total_position = 0
        for data in self._owner.datas:
            position = self._owner.getposition(data)
            total_position += abs(position.size) * data.close[0]

        self.lines.leverage[0] = total_position / portfolio_value if portfolio_value else 0

```bash

## 注册流程

观察器通过 `cerebro.addobserver()` 添加时自动注册

```python

# 观察器注册

cerebro.addobserver(bt.observers.DrawDown)

# 带参数

cerebro.addobserver(bt.observers.DrawDown, fund=True)

# 多个实例

cerebro.addobserver(bt.observers.DrawDown)
cerebro.addobserver(bt.observers.Trades)

```bash
注册流程

1. 创建观察器实例
2. `_ltype` 设置为 `LineIterator.ObsType`(2
3. 观察器被添加到策略的 `_lineiterators[ObsType]` 列表
4. 执行期间调用 `prenext()`、`next()`、`stop()`

## 观察器 vs 指标

| 特性 | 观察器 | 指标 |

|------|--------|------|

| 用途 | 监控和记录 | 生成信号 |

| `_ltype` | `ObsType` (2) | `IndType` (0) |

| `_stclock` | 通常为 `True` | 通常为 `False` |

| 默认 `prenext` | 调用 `next()` | 不执行任何操作 |

| 绘图 | 默认使用子图 | 叠加在数据上 |

| 线条计算 | 外部经纪商/交易 | 内部计算 |

## 绘图配置

### 禁用绘图

```python

# 单个观察器

cerebro.addobserver(bt.observers.DrawDown, _plot=False)

# 或修改 plotinfo

class MyObserver(bt.Observer):
    plotinfo = dict(plot=False)

```bash

### 子图配置

```python
class MyObserver(bt.Observer):
    plotinfo = dict(
        plot=True,
        subplot=True,      # 单独子图
        plotlinelabels=True,
        plotymargin=0.10,  # Y 轴边距
        plothlines=[0.0],  # 水平线
    )

```bash

### 线条样式

```python
class MyObserver(bt.Observer):
    plotlines = dict(
        metric1=dict(
            color='blue',
            linewidth=2,
            linestyle='-',
            marker='o',
            markersize=4,
        ),
        metric2=dict(
            color='red',
            _plotskip=True,  # 不绘制
        ),
    )

```bash

## 完整示例

```python
import backtrader as bt

class MyStrategy(bt.Strategy):
    params = (
        ('sma_period', 20),
    )

    def __init__(self):
        self.sma = bt.indicators.SMA(self.data.close, period=self.p.sma_period)

    def next(self):
        if not self.position:
            if self.data.close[0] > self.sma[0]:
                self.buy()
        else:
            if self.data.close[0] < self.sma[0]:
                self.sell()

# 创建 cerebro

cerebro = bt.Cerebro()

# 添加策略

cerebro.addstrategy(MyStrategy)

# 添加数据

data = bt.feeds.YahooFinanceData(dataname='AAPL', fromdate='2020-01-01', todate='2023-12-31')
cerebro.adddata(data)

# 添加观察器

cerebro.addobserver(bt.observers.Broker)        # 现金和价值

cerebro.addobserver(bt.observers.DrawDown)      # 回撤跟踪

cerebro.addobserver(bt.observers.Trades)        # 交易盈亏

cerebro.addobserver(bt.observers.BuySell)       # 买卖标记

# 添加自定义观察器

class PositionSize(bt.Observer):
    _stclock = True
    lines = ('possize',)
    plotinfo = dict(plot=True, subplot=True, plotname='持仓数量')

    def next(self):
        self.lines.possize[0] = self._owner.getposition().size

cerebro.addobserver(PositionSize)

# 运行

cerebro.run()

# 绘图

cerebro.plot()

```bash

## 下一步

- [策略 API](strategy_zh.md) - 策略开发
- [分析器 API](analyzer_zh.md) - 绩效分析
- [指标 API](indicator_zh.md) - 自定义指标