backtrader.observers.drawdown 源代码
#!/usr/bin/env python
"""DrawDown Observer Module - Drawdown tracking observer.
This module provides the DrawDown observer for tracking current and maximum
drawdown levels during backtesting.
Classes:
DrawDown: Observer that tracks drawdown and max drawdown levels.
Example:
>>> cerebro = bt.Cerebro()
>>> cerebro.addobserver(bt.observers.DrawDown)
"""
from ..analyzers import DrawDown as DrawDownAnalyzer
from ..observer import Observer
# Drawdown
[文档]
class DrawDown(Observer):
"""This observer keeps track of the current drawdown level (plotted) and
the maxdrawdown (not plotted) levels
Params:
- ``fund`` (default: ``None``)
If `None`, the actual mode of the broker (fundmode - True/False) will
be autodetected to decide if the returns are based on the total net
asset value or on the fund value. See ``set_fundmode`` in the broker
documentation
Set it to ``True`` or ``False`` for a specific behavior
"""
_stclock = True
params = (("fund", None),)
lines = (
"drawdown",
"maxdrawdown",
)
plotinfo = dict(plot=True, subplot=True)
plotlines = dict(
maxdrawdown=dict(
_plotskip=True,
)
)
def __init__(self):
"""Initialize the DrawDown observer.
Adds DrawDown analyzer to track drawdown levels.
"""
kwargs = self.p._getkwargs()
self._dd = self._owner._addanalyzer_slave(DrawDownAnalyzer, **kwargs)
[文档]
def next(self):
"""Update drawdown values for the current period.
Gets current and maximum drawdown from the analyzer.
"""
self.lines.drawdown[0] = self._dd.rets.drawdown # update drawdown
self.lines.maxdrawdown[0] = self._dd.rets.max.drawdown # update max
# Drawdown length
[文档]
class DrawDownLength(Observer):
"""This observer keeps track of the current drawdown length (plotted) and
the drawdown max length (not plotted)
Params: None
"""
_stclock = True
lines = (
"len",
"maxlen",
)
plotinfo = dict(plot=True, subplot=True)
plotlines = dict(
maxlength=dict(
_plotskip=True,
)
)
def __init__(self):
"""Initialize the DrawDownLength observer.
Adds DrawDown analyzer to track drawdown length.
"""
self._dd = self._owner._addanalyzer_slave(DrawDownAnalyzer)
[文档]
def next(self):
"""Update drawdown length values.
Gets current and maximum drawdown length from the analyzer.
"""
self.lines.len[0] = self._dd.rets.len # update drawdown length
self.lines.maxlen[0] = self._dd.rets.max.len # update max length
# Old method for max drawdown, calculated within this class instead of calling DrawDown from analyzers
[文档]
class DrawDownOld(Observer):
"""This observer keeps track of the current drawdown level (plotted) and
the maxdrawdown (not plotted) levels
Params: None
"""
_stclock = True
lines = (
"drawdown",
"maxdrawdown",
)
plotinfo = dict(plot=True, subplot=True)
plotlines = dict(
maxdrawdown=dict(
_plotskip="True",
)
)
def __init__(self):
"""Initialize the DrawDownOld observer.
Sets up peak and max drawdown tracking variables.
"""
super().__init__()
self.maxdd = 0.0
self.peak = float("-inf")
[文档]
def next(self):
"""Calculate and update drawdown values.
Computes drawdown from peak value and updates maximum.
"""
value = self._owner.broker.getvalue()
# update the maximum seen peak
if value > self.peak:
self.peak = value
# calculate the current drawdown
self.lines.drawdown[0] = dd = 100.0 * (self.peak - value) / self.peak
# update the maxdrawdown if needed
self.lines.maxdrawdown[0] = self.maxdd = max(self.maxdd, dd)