I apologize in advance for newbie confusion, but the code below that works as expected when fed only with a data0 (1-year of daily bars) line:
from __future__ import (absolute_import, division, print_function, unicode_literals)
import pandas as pd
from sqlalchemy import create_engine
import backtrader as bt
import backtrader.indicators as btind
# Create a Stratey
class SMA_CrossOver(bt.Strategy):
params = (('fast', 10), ('slow', 35))
def __init__(self):
sma_fast = btind.SMA(self.data0, period=self.p.fast)
sma_slow = btind.SMA(self.data0, period=self.p.slow)
self.buysig = btind.CrossOver(sma_fast, sma_slow)
def next(self):
if self.position.size:
if self.buysig < 0:
limit = self.data0.close[0] * 0.98
self.sell(data=self.data0, exectype=bt.Order.Limit, price=limit)
elif self.buysig > 0:
price = self.data0.close[0] * 1.02
limit = self.data0.close[0] * 1.04
self.buy(data=self.data0, exectype=bt.Order.StopLimit, price=price, plimit=limit)
def notify_order(self, order):
if order.status in [order.Submitted, order.Accepted]:
return
if order.status in [order.Completed]:
if order.isbuy():
txt = ','.join(
['BUY EXECUTED: ', '%04d' % len(self),
'%04d' % len(self.data0),
# '%04d' % len(self.data1),
self.data.datetime.date(0).isoformat(),
'%.2f' % self.data0.close[0],
'%.2f' % self.buysig[0]])
print(txt)
else: # sell
txt = ','.join(
['SELL EXECUTED: ', '%04d' % len(self),
'%04d' % len(self.data0),
# '%04d' % len(self.data1),
self.data.datetime.date(0).isoformat(),
'%.2f' % self.data0.close[0],
'%.2f' % self.buysig[0]])
print(txt)
elif order.status in [order.Canceled, order.Margin, order.Rejected]:
print('Order Canceled/Margin/Rejected')
self.order = None
if __name__ == '__main__':
# Connecting to PostgreSQL by providing a sqlachemy engine
DB_TYPE = 'postgresql'
DB_DRIVER = 'psycopg2'
DB_USER = 'postgres'
DB_PASS = 'XXXX'
DB_HOST = 'localhost'
DB_PORT = 'XXXX'
DB_NAME = 'tests'
POOL_SIZE = 50
TABLENAME = 'tests'
SQLALCHEMY_DATABASE_URI = '%s+%s://%s:%s@%s:%s/%s' % (DB_TYPE, DB_DRIVER, DB_USER,
DB_PASS, DB_HOST, DB_PORT, DB_NAME)
ENGINE = create_engine(SQLALCHEMY_DATABASE_URI, pool_size=POOL_SIZE, max_overflow=0)
# Create a cerebro entity
cerebro = bt.Cerebro()
# Add a strategy
cerebro.addstrategy(SMA_CrossOver)
# Get a pandas dataframe
PETR4i = pd.read_sql("select day_id, open, high, low, close, volume
from vista_minutes where instrument_id = 1571 order by day_id", con=ENGINE)
PETR4 = pd.read_sql("select day_id::timestamp , open, high, low, close, ntl_fin_vol
from bdins where instrument_id = 1571 order by day_id ", con=ENGINE)
# Pass it to the backtrader datafeed and add it to the cerebro
data1 = bt.feeds.PandasData(dataname=PETR4i,
datetime=0,
open=1,
high=2,
low=3,
close=4,
volume=5,
timeframe=bt.TimeFrame.Minutes
)
# Pass it to the backtrader datafeed and add it to the cerebro
data0 = bt.feeds.PandasData(dataname=PETR4,
datetime=0,
open=1,
high=2,
low=3,
close=4,
volume=5,
timeframe=bt.TimeFrame.Days
)
# Add the Data Feed to Cerebro
cerebro.adddata(data0)
# cerebro.adddata(data1)
# Set our desired cash start
cerebro.broker.setcash(100000.0)
cerebro.addsizer(bt.sizers.FixedSize, stake=100)
# Set the commission - 0.1% ... divide by 100 to remove the %
cerebro.broker.setcommission(commission=0.001)
# Print out the starting conditions
print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
# Run over everything
thestrats = cerebro.run(tradehistory=True)
thestrat = thestrats[0]
# Print out the final result
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
Producing:
Starting Portfolio Value: 100000.00
BUY EXECUTED: ,0089,0089,2017-05-12,15.45,1.00
SELL EXECUTED: ,0100,0100,2017-05-29,13.57,0.00
BUY EXECUTED: ,0146,0146,2017-08-02,13.51,0.00
BUY EXECUTED: ,0203,0203,2017-10-24,16.51,0.00
SELL EXECUTED: ,0222,0222,2017-11-23,16.19,0.00
Final Portfolio Value: 100018.86
when I add a second line data1 to the cerebro
cerebro.adddata(data0)
cerebro.adddata(data1)
and try to make the broker use data1 (1-year of 1-minute bars) to execute the orders:
def next(self):
if self.position.size:
if self.buysig < 0:
limit = self.data0.close[0] * 0.98
self.sell(data=self.data1, exectype=bt.Order.Limit, price=limit)
elif self.buysig > 0:
price = self.data0.close[0] * 1.02
limit = self.data0.close[0] * 1.04
self.buy(data=self.data1, exectype=bt.Order.StopLimit, price=price, plimit=limit)
the output is nowhere near as what I'd expect:
Starting Portfolio Value: 100000.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
BUY EXECUTED: ,39855,0089,2017-05-12,15.45,1.00
Order Canceled/Margin/Rejected
Order Canceled/Margin/Rejected
Order Canceled/Margin/Rejected
Order Canceled/Margin/Rejected
...
I am obviously missing something important here, but since I have both daily and intraday data feeds available at once, I'd like to have my swing trades strategies using the daily data0 and once the orders were generated, feed the intraday line to the broker to have the opportunity to issue then a couple hours after the usually volatile opening and more importantly, when using bracket orders, be able to know if I'll get stopped out or take my profit during the day. This is impossible to deduce having only daily OHLC.
Can I do that without having to resampledata() or replaydata() since I have both feeds at once? Do I need to use coupling, or prenext or something else that I am missing entirely to somehow to avoid the orders to be fired like crazy when I add a second intraday line?