title: Observers description: Monitor and log strategy behavior


Observers

Observers monitor and record strategy behavior during backtesting. Unlike analyzers, observers focus on data collection rather than calculation.

Basic Usage


# Add observer during cerebro setup

cerebro.addobserver(bt.observers.DrawDown)

# Or disable default observers

cerebro.run(stdstats=False)  # Disable default observers

```bash

## Built-in Observers

### DrawDown

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

# Access in strategy

class MyStrategy(bt.Strategy):
    def next(self):

# Access drawdown observer
        if hasattr(self, 'observers'):
            drawdown = self.observers.drawdown
            print(f'Drawdown: {drawdown.drawdown[0]:.2%}')

```bash

### Broker

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

# Tracks:

# - Cash balance

# - Portfolio value

# - Positions

```bash

### Trades

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

# Records each trade

# Entry/exit prices

# Trade profit/loss

```bash

### BuySell

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

# Marks buy and sell points on plots

```bash

### DataTrades

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

# Records trades per data feed

```bash

### DrawDown

```python

# Already added by default with stdstats=True

# Tracks:

# - Current drawdown

# - Maximum drawdown

# - Drawdown duration

```bash

### Benchmark

```python

# Add a benchmark data feed

data = bt.feeds.YahooFinanceData(dataname='AAPL', ...)
bench = bt.feeds.YahooFinanceData(dataname='SPY', ...)

cerebro.adddata(data)
cerebro.adddata(bench)

# Add benchmark observer

cerebro.addobserver(bt.observers.Benchmark, data=bench)

```bash

### LogReturns

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

# Logs returns over time

# Useful for analyzing return patterns

```bash

### TimeReturn

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

# Returns by time period

# Can specify timeframe

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

```bash

## Default Observers

When you run `cerebro.run()` without `stdstats=False`, these observers are added automatically:

| Observer | Purpose |

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

| `Broker` | Track broker state |

| `Trades` | Record all trades |

| `BuySell` | Mark buy/sell on plots |

| `DrawDown` | Track drawdown metrics |

## Custom Observer

Create your own observer:

```python
class TradeLogger(bt.Observer):
    """
    Custom observer that logs all trades.
    """
    _stclock = True  # Use system clock
    _ltype = 2        # Observer type
    lines = ('dummy',)  # Must have at least one line

    params = dict(enabled=True)

    def start(self):

# Register to lineiterators
        if hasattr(self, '_owner') and self._owner:
            if hasattr(self._owner, '_lineiterators'):
                if self._ltype in self._owner._lineiterators:
                    if self not in self._owner._lineiterators[self._ltype]:
                        self._owner._lineiterators[self._ltype].append(self)

    def next(self):
        self.lines.dummy[0] = 0  # Must set a value

# Add to cerebro

cerebro.addobserver(TradeLogger)

```bash

## Observer vs Analyzer

| Feature | Observer | Analyzer |

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

| **Purpose**| Data collection | Calculation |

|**When Called**| Every bar | After backtest |

|**Output**| Time series data | Summary statistics |

|**Plotting** | Can be plotted | Not plotted |

## Accessing Observer Data

### After Backtest

```python
strats = cerebro.run()
strat = strats[0]

# Access observer data

print(strat.observers.broker.getvalue())
print(strat.observers.drawdown.drawdown)

```bash

### In Strategy

```python
class MyStrategy(bt.Strategy):
    def next(self):

# Access observers if available
        if hasattr(self, 'observers'):
            if hasattr(self.observers, 'drawdown'):
                dd = self.observers.drawdown.drawdown[0]
                if dd > 0.10:  # 10% drawdown
                    self.log(f'High drawdown: {dd:.2%}')

```bash

## Disabling Observers

```python

# Disable default observers

cerebro.run(stdstats=False)

# Add specific observers

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

```bash

## Plotting with Observers

Observers automatically appear on plots:

```python
import matplotlib.pyplot as plt

cerebro.plot()
plt.show()

# Observers appear as subplots:

# - Drawdown

# - Trades

# - Buy/Sell markers

```bash

## Next Steps

- [Plotting](plotting.md) - Visualize results
- [Analyzers](analyzers.md) - Calculate performance metrics