Error with simple custom indicator
-
Hi all,
I'm looking for a way to eliminate opening trades when the EMA lines are flat, (indicating a sideway market.) I want to do that by checking how much the EMA line moved in the past x bars. (Suggestions on the strategy are always welcome!)
I created a custom indicator that does one simple thing:
Takes the high and Low of the last x number of periods and calculates the difference in percent. If too low, then no new positions get opened.
I can use the close data, or better, a moving average.
I get this error:TypeError: must be real number, not array.array
Can't figure it out for the life of me - thank you for the help.
Here's the indicator:
class PercentVariationInPeriod(bt.Indicator): lines = ('Variation',) params = ( ('period', 180), ) def __init__(self): ar = self.data.get(size=self.p.period) high = bt.Max(ar) low = bt.Min(ar) self.lines.Variation = (high - low)/low
And the call:
self.emaVariation = vol.PercentVariationInPeriod(self.ema_slow, plotname='EMA Variation', subplot=True)
(Note period=180 is in minutes...)
-
@hanaan said in Error with simple custom indicator:
self.emaVariation = vol.PercentVariationInPeriod(self.ema_slow, plotname='EMA Variation', subplot=True)
There a two built in indicators that make this a bit easier for you. Highest aka
MaxN
and Lowest akaMinN
.You can use them in your indicator like this:
class PercentVariationInPeriod(bt.Indicator): lines = ("Variation",) params = (("period", 180),) def __init__(self): high = bt.ind.MaxN(period=self.p.period) low = bt.ind.MinN(period=self.p.period) self.lines.Variation = (high - low) / low
-
Okay, thank you that worked perfectly.
Would you know what didn't work in my original code?
Did I use self.data.get(size=self.p.period) incorrectly? -
@hanaan Yes. You need to use get in
next
. It returns an array based on the parameterssize
andago
. -
@run-out Ah... get in next, not init. Got it.
-
@hanaan said in Error with simple custom indicator:
Hi all,
I'm looking for a way to eliminate opening trades when the EMA lines are flat, (indicating a sideway market.) I want to do that by checking how much the EMA line moved in the past x bars. (Suggestions on the strategy are always welcome!)In addition to previous solution, and for all those who may be looking at the same thing, you may want to check the "angle" of the moving average.
In Sierra Chart, there is study for this : https://www.sierrachart.com/index.php?page=doc/StudiesReference.php&ID=231
Implementing this code for a moving average in BT could be done that way (testing not complete - to be fully tested) :params = (('length', 10), ('period', 10), ('movav', MovAv.EMA), ('pointvalue', 1),) def __init__(self): self.ma = self.p.movav(self.data.close, period=self.p.period) def next(self): self.l.maangle[0] = math.atan((self.ma[0]-self.ma[-self.p.length])/(self.p.pointvalue * self.p.length)) *(180/math.pi)
-
@emr Interesting. Instead of angle isn't it easier to just check the percent change over a certain period?
I think it gives you the same indication of direction over time. -
@hanaan easier, maybe but yes it provides more or less the same information. Analysis of the resulting data and plotting (I use btplotting) may help to visualize the sometimes subtle differences.