# Trading a Day in StepsΒΆ

It seems that somewhere in the world there is an interest that can be summarized as follows:

• Introduce an order using daily bars but using the opening price

This comes from the conversations in tickets #105 Order execution logic with current day data and #101 Dynamic stake calculation

backtrader tries to remain as realistic as possible and the following premise applies when working with daily bars:

• When a daily bar is being evaluated, the bar is already over

It makes sense because all price (open/high/low/close) components are known. It would actually seem illogical to allow an action on the `open` price when the `close` price is already known.

The obvious approach to this is to use intraday data and enter when the opening prices is known. But it seems intraday data is not so widespread.

This is where adding a filter to a data feed can help. A filter that:

• Converts daily data into intraday-like data

Blistering barnacles!!! The curious reader will immediately point out that upsampling for example `Minutes` to `Days` is logical and works, but that downsampling `Days` to `Minutes` cannot be done.

And it is 100% right. The filter presented below will not try that, but a much humble and simpler goal:

• Break a daily bar in 2 parts
1. A bar with only the opening price and no volume
2. A 2nd bar which is a copy of the regular daily bar

This can still be held as a logical approach:

• Upon seeing the opening price, the trader can act
• The order is matched during the rest of the day (actually may or may not be matched depending on execution type and price constraints)

The full code is presented below. Let’s see a sample run with a well known data of `255` daily bars:

```\$ ./daysteps.py --data ../../datas/2006-day-001.txt
```

Output:

```Calls,Len Strat,Len Data,Datetime,Open,High,Low,Close,Volume,OpenInterest
0001,0001,0001,2006-01-02T23:59:59,3578.73,3578.73,3578.73,3578.73,0.00,0.00
- I could issue a buy order during the Opening
0002,0001,0001,2006-01-02T23:59:59,3578.73,3605.95,3578.73,3604.33,0.00,0.00
0003,0002,0002,2006-01-03T23:59:59,3604.08,3604.08,3604.08,3604.08,0.00,0.00
- I could issue a buy order during the Opening
0004,0002,0002,2006-01-03T23:59:59,3604.08,3638.42,3601.84,3614.34,0.00,0.00
0005,0003,0003,2006-01-04T23:59:59,3615.23,3615.23,3615.23,3615.23,0.00,0.00
- I could issue a buy order during the Opening
0006,0003,0003,2006-01-04T23:59:59,3615.23,3652.46,3615.23,3652.46,0.00,0.00
...
...
0505,0253,0253,2006-12-27T23:59:59,4079.70,4079.70,4079.70,4079.70,0.00,0.00
- I could issue a buy order during the Opening
0506,0253,0253,2006-12-27T23:59:59,4079.70,4134.86,4079.70,4134.86,0.00,0.00
0507,0254,0254,2006-12-28T23:59:59,4137.44,4137.44,4137.44,4137.44,0.00,0.00
- I could issue a buy order during the Opening
0508,0254,0254,2006-12-28T23:59:59,4137.44,4142.06,4125.14,4130.66,0.00,0.00
0509,0255,0255,2006-12-29T23:59:59,4130.12,4130.12,4130.12,4130.12,0.00,0.00
- I could issue a buy order during the Opening
0510,0255,0255,2006-12-29T23:59:59,4130.12,4142.01,4119.94,4119.94,0.00,0.00
```

The following happens:

• `next` is called: `510 times` which is `255 x 2`

• The `len` of the Strategy and that of the data reaches a total of `255`, which is the expected: the data has only those many bars

• Every time the `len` of the data increases, the 4 price components have the same value, namely the `open` price

Here a remark is printed out to indicate that during this opening phase action could be taken, like for example buying.

Effectively:

• The daily data feed is being replayed with 2 steps for each day, giving the option to act in between `open` and the rest of the price components

The filter will be added to the default distribution of backtrader in the next release.

The sample code including the filter.

```from __future__ import (absolute_import, division, print_function,
unicode_literals)

import argparse
from datetime import datetime, time

class DayStepsFilter(object):
def __init__(self, data):
self.pendingbar = None

def __call__(self, data):
# Make a copy of the new bar and remove it from stream
newbar = [data.lines[i][0] for i in range(data.size())]
data.backwards()  # remove the copied bar from stream

openbar = newbar[:]  # Make an open only bar
o = newbar[data.Open]
for field_idx in [data.High, data.Low, data.Close]:
openbar[field_idx] = o

# Nullify Volume/OpenInteres at the open
openbar[data.Volume] = 0.0
openbar[data.OpenInterest] = 0.0

# Overwrite the new data bar with our pending data - except start point
if self.pendingbar is not None:
data._updatebar(self.pendingbar)

self.pendingbar = newbar  # update the pending bar to the new bar

return False  # the length of the stream was not changed

def last(self, data):
'''Called when the data is no longer producing bars
Can be called multiple times. It has the chance to (for example)
produce extra bars'''
if self.pendingbar is not None:
data.backwards()  # remove delivered open bar
self.pendingbar = None  # No further action
return True  # something delivered

return False  # nothing delivered here

class St(bt.Strategy):
params = ()

def __init__(self):
pass

def start(self):
self.callcounter = 0
txtfields = list()
txtfields.append('Calls')
txtfields.append('Len Strat')
txtfields.append('Len Data')
txtfields.append('Datetime')
txtfields.append('Open')
txtfields.append('High')
txtfields.append('Low')
txtfields.append('Close')
txtfields.append('Volume')
txtfields.append('OpenInterest')
print(','.join(txtfields))

self.lcontrol = 0

def next(self):
self.callcounter += 1

txtfields = list()
txtfields.append('%04d' % self.callcounter)
txtfields.append('%04d' % len(self))
txtfields.append('%04d' % len(self.data0))
txtfields.append(self.data.datetime.datetime(0).isoformat())
txtfields.append('%.2f' % self.data0.open[0])
txtfields.append('%.2f' % self.data0.high[0])
txtfields.append('%.2f' % self.data0.low[0])
txtfields.append('%.2f' % self.data0.close[0])
txtfields.append('%.2f' % self.data0.volume[0])
txtfields.append('%.2f' % self.data0.openinterest[0])
print(','.join(txtfields))

if len(self.data) > self.lcontrol:
print('- I could issue a buy order during the Opening')

self.lcontrol = len(self.data)

def runstrat():
args = parse_args()

cerebro = bt.Cerebro()

if args.plot:
cerebro.plot(style='bar')

def parse_args():
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
description='Sample for pivot point and cross plotting')

default='../../datas/2005-2006-day-001.txt',