Multi timeframe indicator plotted twice and in wrong timeframe
-
Hello backtrader community. I just started using backtrader to test a H1 strategy that uses a D1 indicator. The indicator gives two values at the beginning of the day that are valid for all H1 candles until the end of the day. Two horizontal lines (in the H1 TF) similar to a pivot.
The current implementation of this indicator does not works: it has these two problems:
- both the H1 and the D1 charts are shown. I only want the H1 chart.
- the indicator shows the right values in the D1 chart, but it is not plotted in the H1 chart (where I want it as a series of straight lines).
Here is a screenshot of the problem
See? No indicator in the H1 chart and a superfluous D1 chart.
As you can see in the following code, at the top level I first load the H1 data and then the D1 data. This should make H1 the default data source, right?
Then, in the strategy, I set up the indicator to use
self.data1
. This should link its calculations to the D1 timeframe, shouldn't it?Here is the code (simplified but working)
#!/usr/bin/env python import backtrader as bt import backtrader.indicators as btind class MyMA(bt.Indicator): lines = ('ma',) params = dict(period=30) def __init__(self): diff = self.data.high - self.data.open self.l.ma = btind.SMA(diff, period=self.p.period) class Levels(bt.Indicator): lines = ('last_close', 'adj_close') params = dict(period=30) def __init__(self): ma = MyMA(period=self.p.period) self.l.last_close = self.data.close(-1) self.l.adj_close = self.data.close(-1) - ma(-1) class LevelsDisplay(bt.Strategy): params = dict(period=30) def __init__(self): # data1 = D1 Timeframe self.levels = Levels(self.data1, period=self.p.period) self.levels.plotinfo.subplot = False csv_opts = dict( headers=True, separator=';', dtformat='%Y-%m-%d %H:%M:%S %z', openinterest=-1) h1_opts = dict(dataname='data-h1.csv', timeframe=bt.TimeFrame.Minutes, compression=60) d1_opts = dict(dataname='data-d1.csv', timeframe=bt.TimeFrame.Days) cerebro = bt.Cerebro(stdstats=False) data_h1 = bt.feeds.GenericCSVData(**{**csv_opts, **h1_opts}) data_d1 = bt.feeds.GenericCSVData(**{**csv_opts, **d1_opts}) cerebro.adddata(data_h1) cerebro.adddata(data_d1) cerebro.addstrategy(LevelsDisplay, period=3) cerebro.run(runonce=False) cerebro.plot(style='candle')
And this is
data-d1.csv
:TIME;OPEN;HIGH;LOW;CLOSE;VOLUMES 2019-02-01 01:00:00 +0100;11198;11218;11116;11180;104846000 2019-02-04 01:00:00 +0100;11180;11209;11100;11176;76459000 2019-02-05 01:00:00 +0100;11178;11371;11177;11367;92184000 2019-02-06 01:00:00 +0100;11337;11347;11297;11324;78242000 2019-02-07 01:00:00 +0100;11262;11286;11022;11022;111363000 2019-02-08 01:00:00 +0100;10991;11045;10864;10906;105464736
and
data-h1.csv
:TIME;OPEN;HIGH;LOW;CLOSE;VOLUMES 2019-02-01 09:00:00 +0100;11198;11218;11159;11197;13547140 2019-02-01 10:00:00 +0100;11197;11211;11166;11180;7988925 2019-02-01 11:00:00 +0100;11181;11187;11142;11161;7331403 2019-02-01 12:00:00 +0100;11161;11177;11147;11150;5334638 2019-02-01 13:00:00 +0100;11152;11160;11130;11134;6911563 2019-02-01 14:00:00 +0100;11135;11186;11135;11175;5151842 2019-02-01 15:00:00 +0100;11175;11181;11118;11119;9776934 2019-02-01 16:00:00 +0100;11117;11175;11116;11162;10919961 2019-02-01 17:00:00 +0100;11160;11186;11152;11180;37883752 2019-02-04 09:00:00 +0100;11180;11209;11131;11143;12075054 2019-02-04 10:00:00 +0100;11142;11197;11141;11186;6030952 ...
What am I doing wrong?
-
@fino said in Multi timeframe indicator plotted twice and in the timeframe:
The current implementation of this indicator does not works: it has these two problems:
Sorry, but it does work.
@fino said in Multi timeframe indicator plotted twice and in the timeframe:
- both the H1 and the D1 charts are shown. I only want the H1 chart.
You have not told the system that you only want the
H1
chart. It cannot be a problem. You have not configured things to work the way you want.See - Docs - Plotting and use
plotinfo.plot=False
for whatever you don't want plotted.@fino said in Multi timeframe indicator plotted twice and in the timeframe:
- the indicator shows the right values in the D1 chart, but it is not plotted in the H1 chart
@fino said in Multi timeframe indicator plotted twice and in the timeframe:
data_h1 = bt.feeds.GenericCSVData(**{**csv_opts, **h1_opts}) data_d1 = bt.feeds.GenericCSVData(**{**csv_opts, **d1_opts})
@fino said in Multi timeframe indicator plotted twice and in the timeframe:
self.levels = Levels(self.data1, period=self.p.period)
Well, you load
d1
as the second feed in the system (henceself.data1
) and you apply the indicator toself.data1
. It should be no surprise that the indicator plots ond1
and not onh1
. It would be a surprise if it did otherwise.Again. See - Docs - Plotting and use
plotinfo.plotmaster=YOUR_DESIRED_DATA
to plot on your chosen target.@fino said in Multi timeframe indicator plotted twice and in the timeframe:
See? No indicator in the H1 chart and a superfluous D1 chart.
See above. There is nothing superfluous. You have to configure what you want and what you don't want and where you want it and where you don't want it.
@fino said in Multi timeframe indicator plotted twice and in the timeframe:
As you can see in the following code, at the top level I first load the H1 data and then the D1 data. . This should make H1 the default data source, right?
No idea what you mean with "default data source". There is no such thing in backtrader. The only thing you have achieved is that
h1
can be referred asself.data0
orself.datas[0]
orself.data
. This is described here: Docs - Strategy in the section Member Attributes@fino said in Multi timeframe indicator plotted twice and in the timeframe:
Then, in the strategy, I set up the indicator to use self.data1. This should link its calculations to the D1 timeframe, shouldn't it?
Yes. And that's why the indicator obviously plots on
d1
-
@backtrader said in Multi timeframe indicator plotted twice and in wrong timeframe:
@fino said in Multi timeframe indicator plotted twice and in the timeframe:
The current implementation of this indicator does not works: it has these two problems:
Sorry, but it does work.
Hi @backtrader, thank you for your assistance. Yes, the code does work, but it does not do what I want it to do. Obviously the problem is that I'm giving the wrong instructions because I'm new to backtrader and still haven't understood most of it. So I thank you in advance for your help.
See - Docs - Plotting and use
plotinfo.plotmaster=YOUR_DESIRED_DATA
to plot on your chosen target.I tried with
self.levels.plotinfo.plotmaster = self.data0
but it failed with the following error:
ValueError: x and y must have same first dimension, but have shapes (54,) and (6,)
.I need to replicate the generated indicator values (6) for each H1 candle (9 * 6 = 56), don't I? What is the best way to do this?
-
Use coupling: Docs - Mixing Timeframes in Indicators
This functionality allows to calculate an indicator on a timeframe an automatically apply the indicator to another lower timeframe.
-
@backtrader said in Multi timeframe indicator plotted twice and in wrong timeframe:
Use coupling: Docs - Mixing Timeframes in Indicators
This functionality allows to calculate an indicator on a timeframe an automatically apply the indicator to another lower timeframe.
I tried coupling the D1 indicator with the following code as suggested by the guide, but I still get the same error:
ValueError: x and y must have same first dimension, but have shapes (54,) and (6,)
class LevelsDisplay(bt.Strategy): params = dict(period=30) def __init__(self): # self.data1 = D1 Timeframe levels = Levels(self.data1, period=self.p.period) self.levels = levels() self.levels.plotinfo.subplot = False self.levels.plotinfo.plotmaster = self.data0
I do not see any other places in the Strategy where I could couple.
The guide says
See how the
()
is executed with no arguments (in the background aNone
is being supplied). The following is happening:pivotpoint.s1()
is returning an internalLinesCoupler
object which follows the rhythm of the larger scope. This coupler fills itself with the latest delivered value from the reals1
(starting with a default value ofNaN
)How does the Cerebro know which timeframe is the "the larger scope"? Does it analyze all the added data?
BTW the Mixing Timeframes guide is where I started and it does not mention
plotmaster
at all. Maybe it could be useful for newbies if it was somehow mentioned. Just a suggestion.