backtrader.filters.calendardays 源代码
#!/usr/bin/env python
"""Calendar Days Filter Module - Calendar day filling.
This module provides the CalendarDays filter for adding missing
calendar days to trading day data.
Classes:
CalendarDays: Fills missing calendar days.
Example:
>>> data = bt.feeds.GenericCSVData(dataname='data.csv')
>>> data.addfilter(bt.filters.CalendarDays())
>>> cerebro.adddata(data)
"""
from datetime import date, datetime, timedelta
from ..parameters import ParameterizedBase
[文档]
class CalendarDays(ParameterizedBase):
"""
Bar Filler to add missing calendar days to trading days
Params:
- fill_price (def: None):
> 0: The given value to fill
0 or None: Use the last known closing price
-1: Use the midpoint of the last bar (High-Low average)
- fill_vol (def: float('NaN')):
Value to use to fill the missing volume
- fill_oi (def: float('NaN')):
Value to use to fill the missing Open Interest
"""
params = (
("fill_price", None),
("fill_vol", float("NaN")),
("fill_oi", float("NaN")),
)
ONEDAY = timedelta(days=1)
lastdt = date.max
[文档]
def __init__(self, data, **kwargs):
"""Initialize the CalendarDays filter.
Args:
data: The data feed to apply the filter to.
**kwargs: Additional keyword arguments passed to parent class.
"""
super().__init__(**kwargs)
[文档]
def __call__(self, data):
"""
If the data has a gap larger than 1 day amongst bars, the missing bars
are added to the stream.
Params:
- data: the data source to filter/process
Returns:
- False (always): this filter does not remove bars from the stream
"""
dt = data.datetime.date()
if (dt - self.lastdt) > self.ONEDAY: # gap in place
self._fillbars(data, dt, self.lastdt)
self.lastdt = dt
return False # no bar has been removed from the stream
def _fillbars(self, data, dt, lastdt):
"""
Fills one by one bars as needed from time_start to time_end
Invalidates the control dtime_prev if requested
"""
tm = data.datetime.time(0) # get time part
# Same price for all bars
if self.p.fill_price > 0:
price = self.p.fill_price
elif not self.p.fill_price:
price = data.close[-1]
elif self.p.fill_price == -1:
price = (data.high[-1] + data.low[-1]) / 2.0
while lastdt < dt:
lastdt += self.ONEDAY
# Prepare an array of the necessary size
bar = [float("Nan")] * data.size()
# Fill the datetime
bar[data.DateTime] = data.date2num(datetime.combine(lastdt, tm))
# Fill price fields
for pricetype in [data.Open, data.High, data.Low, data.Close]:
bar[pricetype] = price
# Fill volume and open interest
bar[data.Volume] = self.p.fill_vol
bar[data.OpenInterest] = self.p.fill_oi
# Fill extra lines the data feed may have defined beyond DateTime
for i in range(data.DateTime + 1, data.size()):
bar[i] = data.lines[i][0]
# Add this constructed bar to the stack of the stream
data._add2stack(bar)
# Save to stack the bar that signaled the gap
data._save2stack(erase=True)