Source code for backtrader.filters.bsplitter
#!/usr/bin/env python
"""Bar Splitter Filter Module - Daily bar splitting.
This module provides the DaySplitterClose filter for splitting daily
bars into two parts for intraday replay simulation.
Classes:
DaySplitterClose: Splits daily bars into OHLX and CCCC ticks.
Example:
>>> data = bt.feeds.GenericCSVData(dataname='daily.csv')
>>> data.addfilter(bt.filters.DaySplitterClose())
>>> cerebro.adddata(data)
"""
import datetime
from backtrader.parameters import ParameterizedBase
__all__ = ["DaySplitterClose", "DaySplitter_Close"]
[docs]
class DaySplitterClose(ParameterizedBase):
"""
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 indicates 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
[docs]
def __init__(self, data, **kwargs):
"""Initialize the DaySplitterClose filter.
Args:
data: The data feed to apply the filter to.
**kwargs: Additional keyword arguments passed to parent class.
"""
super().__init__(**kwargs)
self.lastdt = None
[docs]
def __call__(self, data):
"""Process the data feed to split daily bars.
This method is called for each bar in the data feed. It splits the daily
bar into two parts - an OHLX tick and a CCCC tick - to simulate intraday
trading behavior.
Args:
data: The data feed containing the bar to process.
Returns:
bool: False if the initial tick can be further processed from stack.
"""
# 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
# Alias for backward compatibility
DaySplitter_Close = DaySplitterClose