您的位置:  首页 » 量化交易与机器学习 » backtrader » 过滤器 – backtrader中文教程

Filters

This功能相对较晚除了backtrader而且必须是安装在现有的内部。这使得它是不灵活和100%功能全的希望,但它仍然可以达到目的在许多cases.

Although落实试图允许即插即用过滤器链接,此预先存在的内部,因此难以确保可能永远是实现。因此,一些过滤器可被链接和其他一些可以通过not.

Purpose

  • Transform提供的值的data feed以递送不同data
    feed

的实施开始,以简化这两个实施这可以通过cerebroAPI直接使用明显的过滤器。它们是:

  • Resamplingcerebro.resampledata

    的这里的滤波器变换timeframecompression的进入data feed。例如:

    (Seconds, 1) -> (Days, 1)
    

    这意味着,原始数据馈送是输送杆,分辨率的1 Second。在Resampling滤波器截取数据并对其进行缓冲直到它可以提供一个1 Day酒吧。这将发生在一个1 Second栏从第二天是seen.

  • Replayingcerebro.replaydata

    对于与上述相同的时间框架,所述过滤器将使用1 Second分辨率酒吧重建1 Daybar.

    That指1 Day栏提供多次1 Second酒吧都见过,更新,以包含最新的information.

    This模拟,例如,实际交易日如何有数据developed.

    Note

    The长度,len(data),因此长度策略只要保持不变的day不在work

Given change.

Filters一个现有的数据进料/源您使用的数据的addfilter方法饲料:

data = MyDataFeed(dataname=myname)
data.addfilter(filter, *args, **kwargs)
cerebro.addata(data)

而且,即使它正好是在重采样兼容/ replay过滤以下也可以做到:

data = MyDataFeed(dataname=myname)
data.addfilter(filter, *args, **kwargs)
cerebro.replaydata(data)

过滤Interface

Afilter必须符合给定的接口,是这样的:

  • 可调用它接受这个签名:
    callable(data, *args, **kwargs)
    

or

  • A类可以是instantiatedcalled
    • 在实例化__init__方法必须支持签名:
    def __init__(self, data, *args, **kwargs)
    
    • `的__call__方法证明了这签名:
    def __call__(self, data, *args, **kwargs)
    

    实例将被称为从data
    feed
    每个新进入的值。该\*args\*kwargs在相同的传递给__init__

    RETURN VALUES

    * `True`: the inner data fetching loop of the data feed must retry
      fetching data from the feed, becaue the length of the stream was
      manipulated
    
    * `False` even if data may have been edited (example: changed
      `close` price), the length of the stream has remain untouched
    

    在基于类滤波器的情况下2种附加的方法可以用下面的签名来implemented

    • last
    def last(self, data, *args, **kwargs)
    

    这将被调用的时候data feed结束后,允许过滤器提供它可能已例如缓冲的数据。一个典型的例子是resampling的,因为条被缓冲,直到数据从下一次期间看到。当数据料已经结束,没有推新数据缓冲的数据out.

    last提供推缓冲数据out.

Note

It的机会是显而易见的,如果filter在所有支持没有参数,无任何将被添加,所述签名可以被简化为在:

def __init__(self, data, *args, **kwargs) -> def __init__(self, data)

A样品Filter

A非常快速的过滤器实现:

class SessionFilter(object):
    def __init__(self, data):
        pass

    def __call__(self, data):
        if data.p.sessionstart <= data.datetime.time() <= data.p.sessionend:
            # bar is in the session
            return False  # tell outer data loop the bar can be processed

        # bar outside of the regular session times
        data.backwards()  # remove bar from data stack
        return True  # tell outer data loop to fetch a new bar

这个过滤器

  • `使用data.p.sessionstartdata.p.sessionend(标准数据馈送参数),以决定是否酒吧是在session.
  • Ifin-the-session返回值是False,表示什么也没有完成,并且当前条的处理可以continue
  • Ifnot-in-the-session,所述杆从所述流中除去和True是返回指示新栏必须fetched.

    Note

    Thedata.backwards()使得用途LineBuffer接口。这种深层挖掘到的backtrader.

使用这种过滤器的内部结构:

  • 有些数据馈送包含out of regular trading hours数据,这可能不有兴趣的商人。有了这个过滤器只in-session条将被considered.

Data伪API用于Filters

In它上面的例子已经示出了如何在过滤器所调用data.backwards(),以除去从流电流条。有用的电话从中意味着作为数据馈送对象pseudo-API for Filters是:

  • data.backwards(size=1, force=False):删除size从数据条流通过向后移动的逻辑指针(默认为1)。如果force=True,则物理存储也是removed.

    卸下物理存储是一个微妙的操作,并仅作为一个黑客内部operations.

  • data.forward(value=float("NaN"), size=1):移动size棒存储向前,增加物理存储,如果需要,可以并用填充value
  • data._addtostack(bar, stash=False):增加了bar到烟囱供以后处理。bar是含有尽可能多的值作为lines可迭代具有数据feed.

    Ifstash=False的栏添加到堆栈将被立即消耗通过该系统在下次iteration.

    如果stash=True栏将经历整个循环处理,包括潜在地重新解析由filters

  • data._save2stack(erase=False, force=False):保存当前数据栏到堆叠用于以后的处理。如果erase=True然后data.backwards将被调用和将接收参数force
  • data._updatebar(bar, forward=False, ago=0):使用在所述值可迭代bar覆盖数据流中的值ago位置。使用默认的ago=0当前栏将更新。同-1,以前one.

Another例如:Pinkfish Filter

这是可以被链接的过滤器的一个例子,并且是指这样,到另一个过滤器,即replay filter。该Pinkfish名字是从图书馆它描述了在其主页的想法:利用每天的数据来执行操作,这些操作将只可能与盘中data.

To达到的效果:

  • 每日栏将在2个COMPONENTES被打破:OHL然后C.
  • 那些2片链与replay有以下情况发生在流:
    With Len X     -> OHL
    With Len X     -> OHLC
    With Len X + 1 -> OHL
    With Len X + 1 -> OHLC
    With Len X + 2 -> OHL
    With Len X + 2 -> OHLC
    ...
    

逻辑:

  • OHLC接收杆它被拷贝到一个interable和破到成为:
    • `的OHL栏。因为这个概念实际上并不存在的closing价格被替换为opening价格真正形成一个OHLObar.
    • AnC栏whic也并不存在。现实情况是,这将是递送像蜱CCCC
    • 如果分布在2 parts
    • The电流棒之间从stream
    • TheOHLO除去一部分被放置到该卷堆栈立即processing
    • TheCCCC部分在下一round
    • Because投入藏匿处理堆栈有适合立即处理过滤器可以返回False指示it.

This过滤器的工作原理连同:

  • `的replay过滤器,拼OHLOCCCC部分最终实现了OHLCbar.

The使用情况:

  • 看到的东西一样,如果今天最大的是在最高最大过去的20届签发了Close而它与执行的顺序2nd tick.

The代码:

class DaySplitter_Close(bt.with_metaclass(bt.MetaParams, object)):
    """
    Splits a daily bar in two parts simulating 2 ticks which will be used to
    replay the data:

      - First tick: ``OHLX``

        The ``Close`` will be replaced by the *average* of ``Open``, ``High``
        and ``Low``

        The session opening time is used for this tick

      and

      - Second tick: ``CCCC``

        The ``Close`` price will be used for the four components of the price

        The session closing time is used for this tick

    The volume will be split amongst the 2 ticks using the parameters:

      - ``closevol`` (default: ``0.5``) The value indicate which percentage, in
        absolute terms from 0.0 to 1.0, has to be assigned to the *closing*
        tick. The rest will be assigned to the ``OHLX`` tick.

    **This filter is meant to be used together with** ``cerebro.replaydata``

    """
    params = (
        ("closevol", 0.5),  # 0 -> 1 amount of volume to keep for close
    )

    # replaying = True

    def __init__(self, data):
        self.lastdt = None

    def __call__(self, data):
        # Make a copy of the new bar and remove it from stream
        datadt = data.datetime.date()  # keep the date

        if self.lastdt == datadt:
            return False  # skip bars that come again in the filter

        self.lastdt = datadt  # keep ref to last seen bar

        # Make a copy of current data for ohlbar
        ohlbar = [data.lines[i][0] for i in range(data.size())]
        closebar = ohlbar[:]  # Make a copy for the close

        # replace close price with o-h-l average
        ohlprice = ohlbar[data.Open] + ohlbar[data.High] + ohlbar[data.Low]
        ohlbar[data.Close] = ohlprice / 3.0

        vol = ohlbar[data.Volume]  # adjust volume
        ohlbar[data.Volume] = vohl = int(vol * (1.0 - self.p.closevol))

        oi = ohlbar[data.OpenInterest]  # adjust open interst
        ohlbar[data.OpenInterest] = 0

        # Adjust times
        dt = datetime.datetime.combine(datadt, data.p.sessionstart)
        ohlbar[data.DateTime] = data.date2num(dt)

        # Ajust closebar to generate a single tick -> close price
        closebar[data.Open] = cprice = closebar[data.Close]
        closebar[data.High] = cprice
        closebar[data.Low] = cprice
        closebar[data.Volume] = vol - vohl
        ohlbar[data.OpenInterest] = oi

        # Adjust times
        dt = datetime.datetime.combine(datadt, data.p.sessionend)
        closebar[data.DateTime] = data.date2num(dt)

        # Update stream
        data.backwards(force=True)  # remove the copied bar from stream
        data._add2stack(ohlbar)  # add ohlbar to stack
        # Add 2nd part to stash to delay processing to next round
        data._add2stack(closebar, stash=True)

        return False  # initial tick can be further processed from stack

发表评论

电子邮件地址不会被公开。 必填项已用*标注