I am using a strategy which is using 2 time frames (Daily and Weekly) and supposed to generate a buy/sell order on daily time frame whenever condition using daily time frame and weekly time frames are met. I saw that my code executes next() in strategy twice and execute order twice one for daily and one for weekly time frame. How should I control this and make system to generate only on daily time frame when condition with daily and weekly time frames are met.
Below is my strategy:
from future import (absolute_import, division, print_function, unicode_literals)
import backtrader as bt
import backtrader.indicators as btind
import datetime # For datetime objects
import os.path # To manage paths
import sys # To find out the script name (in argv[0])
import pandas as pd
from backtrader.indicators.supertrend import
class supertrend(bt.Strategy):
params = dict(
onlydaily = False
)
def printdata(self,data):
print(data)
def log(self, txt, dt=None):
''' Logging function fot this strategy'''
dt = dt or self.datas[0].datetime.date(0)
print('%s, %s' % (dt.isoformat(), txt))
def init(self):
# Keep a reference to the "close" line in the data[0] dataseries
self.dataopen = self.datas[0].open
self.datahigh = self.datas[0].high
self.datalow = self.datas[0].low
self.dataclose = self.datas[0].close
self.dataopen2 = self.datas[1].open
self.datahigh2 = self.datas[1].high
self.datalow2 = self.datas[1].low
self.dataclose2 = self.datas[1].close
self.supertrend = SuperTrend(self.data, period = 10, multiplier = 3)
if not self.p.onlydaily:
self.supertrend2 = SuperTrend(self.data1, period= 10, multiplier = 1)
self.crossup = btind.CrossUp(self.dataclose, self.supertrend)
self.crossdown = btind.CrossDown(self.dataclose, self.supertrend)
# To keep track of pending orders
self.order = None
def notify_order(self, order):
if order.status in [order.Submitted, order.Accepted]:
# Buy/Sell order submitted/accepted to/by broker - Nothing to do
return
# Check if an order has been completed
# Attention: broker could reject order if not enough cash
if order.status in [order.Completed]:
if order.isbuy():
self.log('BUY EXECUTED, %.2f' % order.executed.price)
elif order.issell():
self.log('SELL EXECUTED, %.2f' % order.executed.price)
self.bar_executed = len(self)
elif order.status in [order.Canceled, order.Margin, order.Rejected]:
self.log('Order Canceled/Margin/Rejected')
# Write down: no pending order
self.order = None
def next(self):
# Check if an order is pending ... if yes, we cannot send a 2nd one
#if self.order:
# return
# Check if we are in the market
if not self.position:
if self.crossup[0] == 1: #(self.dataclose[0] > self.supertrend[0]): # and (self.dataclose2[0] > self.supertrend2[0]):
print('Entry trade')
self.buy()
else:
# Pattern Long exit
if self.position.size > 0:
if self.crossdown[0] == 1: #(self.dataclose[0] > self.supertrend[0]):# and (self.dataclose2[0] < self.supertrend2[0]):
print('Exit trade')
self.sell()
`
Below are the trades, it generates:
Entry trade
Entry trade
2008-04-28, BUY EXECUTED, 5112.50
2008-04-28, BUY EXECUTED, 5112.50
Exit trade
2008-05-27, SELL EXECUTED, 4877.15
Exit trade
2008-08-29, SELL EXECUTED, 4230.60
Entry trade
2008-11-05, BUY EXECUTED, 3155.75
Exit trade
2009-01-13, SELL EXECUTED, 2775.00
Entry trade
2009-03-24, BUY EXECUTED, 2923.80
Exit trade
2009-07-07, SELL EXECUTED, 4166.00
Entry trade
Entry trade
2009-07-20, BUY EXECUTED, 4377.90
2009-07-20, BUY EXECUTED, 4377.90
Exit trade
2009-10-28, SELL EXECUTED, 4846.55
Exit trade
Exit trade
2010-01-25, SELL EXECUTED, 5034.55
2010-01-25, SELL EXECUTED, 5034.55
Final Portfolio Value: -573182.64
The buy() and sell() methods have a 'data' parameter where you can specifically point for which dataset you want to create the order. It is advisable to always use this feature when working with multiple timeframes to avoid confusion.