美文网首页
10.1 Observers and Statistics

10.1 Observers and Statistics

作者: wanggs66 | 来源:发表于2020-04-28 22:18 被阅读0次

Observers 是backtrader中通过手机相关信息用于统计目的观察变量,可以在plot中展示,常见的plot中通常包含3类Observers :

  • Cash and Value (what’s happening with the money in the broker)

  • Trades (aka Operations)

  • Buy/Sell Orders

在Cerebro中将stdstats 设置为True时,plot会自动添加这三类Observers

Example:

import backtrader as bt

...

cerebro = bt.Cerebro()  # default kwarg: stdstats=True

cerebro.addobserver(bt.observers.Broker)
cerebro.addobserver(bt.observers.Trades)
cerebro.addobserver(bt.observers.BuySell)

Accessing the Observers

可以通过self.stats.observers的方式访问

Observer Implementation

The implementation is very similar to that of an Indicator:

class Broker(Observer):
    alias = ('CashValue',)
    lines = ('cash', 'value')

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

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

Steps:

  • Derive from Observer (and not from Indicator)

  • Declare lines and params as needed (Broker has 2 lines but no params)

  • There will be an automatic attribute _owner which is the strategy holding the observer

Observers come in action:

  • After all Indicators have been calculated

  • After the Strategy next method has been executed

  • That means: at the end of the cycle … they observe what has happened 在其他操作执行结束之后, Observers 观察记录发生了什么

In the Broker case it’s simply blindly recording the broker cash and portfolio values at each point in time.

Developing Observers

To produce a meaningful observer, the implementation can use the following information:

  • self._owner is the currently strategy being executed

As such anything within the strategy is available to the observer

  • Default internal things available in the strategy which may be useful:
    • broker -> attribute giving access to the broker instance the strategy creates order against

As seen in Broker, cash and portfolio values are collected by invoking the methods getcash and getvalue

  • _orderspending -> list orders created by the strategy and for which the broker has notified an event to the strategy.
    The BuySell observer traverses the list looking for orders which have executed (totally or partially) to create an average execution price for the given point in time (index 0)

  • _tradespending -> list of trades (a set of completed buy/sell or sell/buy pairs) which is compiled from the buy/sell orders

An Observer can obviously access other observers over the self._owner.stats path.

Example: Custom OrderObserver

import math

import backtrader as bt


class OrderObserver(bt.observer.Observer):
    lines = ('created', 'expired',)

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

    plotlines = dict(
        created=dict(marker='*', markersize=8.0, color='lime', fillstyle='full'),
        expired=dict(marker='s', markersize=8.0, color='red', fillstyle='full')
)

    def next(self):
        for order in self._owner._orderspending:
            if order.data is not self.data:
                continue

            if not order.isbuy():
                continue

            # Only interested in "buy" orders, because the sell orders
            # in the strategy are Market orders and will be immediately
            # executed

            if order.status in   [bt.Order.Accepted, bt.Order.Submitted]:
                self.lines.created[0] = order.created.price

            elif order.status in [bt.Order.Expired]:
                self.lines.expired[0] = order.created.price

Saving/Keeping the statistics

As of now backtrader has not implemented any mechanism to track the values of observers storing them into files. The best way to do it:

  • Open a file in the start method of the strategy

  • Write the values down in the next method of the strategy

Considering the DrawDown observer, it could be done like this

class MyStrategy(bt.Strategy):

    def start(self):

        self.mystats = open('mystats.csv', 'wb')
        self.mystats.write('datetime,drawdown, maxdrawdown\n')

    def next(self):
            self.mystats.write(self.data.datetime.date(0).strftime('%Y-%m-%d'))
        self.mystats.write(',%.2f' % self.stats.drawdown.drawdown[-1])
        self.mystats.write(',%.2f' % self.stats.drawdown.maxdrawdown-1])
        self.mystats.write('\n')

相关文章

网友评论

      本文标题:10.1 Observers and Statistics

      本文链接:https://www.haomeiwen.com/subject/bqavwhtx.html