I'm trying to use btrun, and code a generic strategy which I can control with btrun. My data is typically minute bars, however, in the strategy, I would like to use a 10-day indicator. How can I do this in the strategy? Or btrun options?
If the only data feed in the strategy is has a Minutes/x timeframe/compression specification, you cannot have an indicator calculating in days.
An Order instance (let's call it order) carries an attribute data which is the asset on which the order has been issued. The ticker name should be available as: order.data._name (where _name is the name you have assigned when using adddata)
Names are actually a late addition to backtrader, because one of the underlying design concepts is that the development of a trading idea should, ideally, not be bound to a specific asset.
A signal / indicator has (like a Strategy) receives an array of the available data feeds in the environment in which they are instantiated (an Indicator can be instantiated inside a Strategy or inside another Indicator)
If your Strategy has 4 data feeds, the indicator will default to receiving 4 data feeds, which will be available in the iterable self.datas and as self.data0, ..., self.data3. Most indicators actually only use 1 data feed. One can actually declare that a given indicator must receive more than 1 data feed.
The outer SMA receives the inner SMA as data feed. And this data feed carries no name, even if it's calculating the simple moving average of self.data1. We still don't know what self.data1 is. It could be an RSI for example. See:
MyInd2 passes 2 data feeds, one is the main data feed received (which can be anythin) and the 2nd is the RSI. As such MyInd1 receives an RSI instance as self.data1, but it doesn't know it. It simply does an SMA on it and then a 2nd SMA
If your signal is going to be name-bound, it will be limited to real data feeds which carry a _name attribute and will fail to be generic for any kind of actual data feed, like in the examples above.
lines = ('name_bound',)
if self.data0._name == 'my-preferred-name':
self.lines.name_bound = bt.ind.SMA(self.data3)
self.lines.name_bound = bt.ind.SMA(self.data2)
At least data0 must be a real data feed with a name in that example.
Shifting is implemented with the (x) operators in lines objects.
See: Docs - Concepts and look for delayed. The use of the term delayed was meant to indicate that looking into the future is not possible. But it is possible for indicators to project values into the future (like Ichimoku does), although it is seldom used.
newline = self.rsi + self.rsi(-1)
Notice how the first term doesn't use the (x) notation and with it it simply takes the current value. One could of course also do it formally as:
newline = self.rsi(0) + self.rsi(-1)
which is functionally 100% equivalent but not 100% memory equivalent because self.rsi(0) will create an extra buffer for the copies of itself.
RSI has a single line, so there is not much need to address the specific lines and by simply using the indicator itself the 1st line in the indicator is automatically used.
But for indicators with multiple lines like a MACD, one can also do things like:
newline = self.macd + self.macd(-1) # 1st line
newline = self.macd.lines.macd + self.macd.lines.macd(-1) # the 1st line is also called macd
newline = self.macd + self.macd.lines.signal(-1) # sum of present 1st line + delayed line "signal"
New changes have only uncovered a typo in the ta-lib integration by which auto-generated wrappers had the module itself in the __module__ attribute instead of the module name. Corrected in the development branch
The final implementation, already pushed to the development branch, respects the original implementation by Ehlers and rather than expecting the price component to have high and low it takes simply self.data (which unless changed is the close from regular data feeds)
The advantage of not having specifics like high and low in the code is that the LRSI can be calculated for anything which is a data feed or descendant of ... you could create the LRSI of a SimpleMovingAverage