For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/
IB Live Daily next() delivers twice
-
Hi there!
I have been testing a strategy successfully on lower timeframes but only when I test it on Daily timeframe, next() is executed twice... I just cannot find the reason for this.
Any help is highly appreciated! I have read the documentation and searched for possible issues, but I'm not an expert with cerebro unfortunately yet.
from __future__ import (absolute_import, division, print_function, unicode_literals) import datetime # importing the requests library import requests import json # Import the backtrader platform import backtrader as bt from datadog import initialize, statsd, api from datadog.api.constants import CheckStatus from datetime import date import time import random import os initialize(**options) # Create a Stratey class TestStrategy(bt.Strategy): params = ( ('rsiperiod', 2), ('atrperiod', 14), ('buylimit', 10), ('exitlimit', 85), ('atrdistance', 0.5), ('exitpercent', 0.05), ('risk', 0.05), ) def log(self, txt, dt=None): ''' Logging function fot this strategy''' dt = dt or self.datas[0].datetime.time(0) print('%s, %s' % (dt.isoformat(), txt)) def __init__(self): # Keep a reference to the "close" line in the data[0] dataseries self.dataclose = self.datas[0].close self.dataopen = self.datas[0].open self.datahigh = self.datas[0].high self.datalow = self.datas[0].low # To keep track of pending orders and buy price/commission self.order = None self.buyprice = None self.buycomm = None self.datastatus = None self.position_open = False self.tradevalue = 0 self.tradeduration = 0 self.lasttradeprice = 0 # Indicators for the plotting show self.rsi = bt.indicators.RSI_Safe(self.datas[0], period=self.params.rsiperiod) self.atr = bt.indicators.ATR(self.datas[0], period=self.params.atrperiod) #self.rsi2 = bt.indicators.RSI(self.datas[-2], period=self.params.rsiperiod) 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, Price: %.2f, Cost: %.2f, Comm %.2f' % (order.executed.price, order.executed.value, order.executed.comm)) self.buyprice = order.executed.price self.buycomm = order.executed.comm else: # Sell self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' % (order.executed.price, order.executed.value, order.executed.comm)) self.bar_executed = len(self) elif order.status in [order.Canceled, order.Margin, order.Rejected]: statsd.event('Order Canceled/Margin/Rejected!!', 'Could not execute order.', alert_type='error', tags=['strategy:DAX_RSI']) self.log('Order Canceled/Margin/Rejected') # Write down: no pending order self.order = None def notify_trade(self, trade): if trade.justopened: self.lasttradeprice = trade.price if trade.isclosed: self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' % (trade.pnl, trade.pnlcomm)) self.position_open = False def notify_data(self, data, status, *args, **kwargs): if status == data.LIVE: # the data has switched to live data self.datastatus = 'LIVE' self.log('WE ARE LIVE') if status == data.CONNBROKEN: # the data has switched to live data self.log('--------------- CONNECTION DISRUPTED, reconnecting... ---------------') if status == data.DISCONNECTED: # the data has switched to live data self.log('--------------- DISCONNECTED!! We are definitely offline. -----------') def next(self): if self.datastatus != 'LIVE': return # Simply log the closing price of the series from the reference self.log('Close, %.2f | OpenTrades: %.2f | Portfolio Value: %.2f | Cash Value: %.2f' % (self.dataclose[0],self.position.size, self.broker.getvalue(), self.broker.getcash())) statsd.event('New Bar', 'Close, %.2f | OpenTrades: %.2f | Portfolio Value: %.2f | Cash Value: %.2f' % (self.dataclose[0],self.position.size, self.broker.getvalue(), self.broker.getcash()), alert_type='info', tags=['strategy:DAX_RSI']) if self.lasttradeprice == 0: self.lasttradeprice = self.getposition(self.datas[0]).price portfolio_value = self.broker.getvalue() portfolio_cash = self.broker.getcash() vol = round((portfolio_cash * self.params.risk) / (self.params.exitpercent * self.dataclose[0]),0) vol = int(vol) #if vol < 1: vol = 1 # self.log('volume intended %.2f' % vol) # 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: self.position_open = False # Not yet ... we MIGHT BUY if ... if (self.rsi[0] < self.params.buylimit and self.dataclose[0] > self.dataopen) or (self.rsi[-1] < self.params.buylimit and self.dataclose[0] > self.dataopen) or (self.rsi[-2] < self.params.buylimit and self.dataclose[0] > self.dataopen): # BUY, BUY, BUY!!! (with all possible default parameters) #self.log('BUY CREATE, %.2f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.buy(exectype=bt.Order.Market, size=vol) else: if (self.rsi[0] < self.params.buylimit and self.dataclose[0] > self.dataopen and (self.getposition(self.datas[0]).price - self.dataclose) > (self.params.atrdistance * self.atr[0]) and (self.lasttradeprice - self.dataclose) > (self.params.atrdistance * self.atr[0])) or (self.rsi[-1] < self.params.buylimit and self.dataclose[0] > self.dataopen and (self.getposition(self.datas[0]).price - self.dataclose) > (self.params.atrdistance * self.atr[0]) and (self.lasttradeprice - self.dataclose) > (self.params.atrdistance * self.atr[0])) or (self.rsi[-2] < self.params.buylimit and self.dataclose[0] > self.dataopen and (self.getposition(self.datas[0]).price - self.dataclose) > (self.params.atrdistance * self.atr[0]) and (self.lasttradeprice - self.dataclose) > (self.params.atrdistance * self.atr[0])): # BUY, BUY, BUY!!! (with all possible default parameters) self.log('BUY FOLLOWUP, %.2f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.buy(exectype=bt.Order.Market, size=vol) elif (self.rsi[0] > self.params.exitlimit and self.dataclose < self.dataopen and self.dataclose > self.getposition(self.datas[0]).price) or (self.rsi[-1] > self.params.exitlimit and self.dataclose < self.dataopen and self.dataclose > self.getposition(self.datas[0]).price) or (self.rsi[-2] > self.params.exitlimit and self.dataclose < self.dataopen and self.dataclose > self.getposition(self.datas[0]).price): # SELL, SELL, SELL!!! (with all possible default parameters) # self.log('EXIT NORMAL, %.2f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.close() elif ((((self.getposition(self.datas[0]).price - self.dataclose) / self.getposition(self.datas[0]).price) * 100) >= (self.params.exitpercent * 100)): # SELL, SELL, SELL!!! (with all possible default parameters) self.log('EXIT STOP LOSS!!!! Closing ALL, %.2f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.close() if self.position: self.tradeduration += 1 self.tradevalue = self.dataclose[0] - self.getposition(self.datas[0]).price sl = self.getposition(self.datas[0]).price * (1.0-self.params.risk) if __name__ == '__main__': # Create a cerebro entity cerebro = bt.Cerebro() ibstore = bt.stores.IBStore(host='127.0.0.1', port=4002, clientId=35,reconnect=-1) cerebro.broker = ibstore.getbroker() # or cerebro.setbroker(...) data = ibstore.getdata(dataname='IBDE30-CFD-SMART-EUR') # cerebro.adddata(data) cerebro.resampledata(data, timeframe=bt.TimeFrame.Days, compression=1) cerebro.addstrategy(TestStrategy) cerebro.run()
-
@Nick-Gehrlein Anyone got an idea?
-
ab_trader? :)
-