Plotting Number of stocks held over time
-
Hi,
I am hoping to plot the number of stocks held over time on my final output chart.Are there any examples of this already?
I believe I should create an observer, but not sure the best (/easiest) way to do this.
I am currently logging how many stocks are held in each
next()
statement under a variable "num_long" which I add 1 unit to whenever a stock iteration hasself.broker.getposition(d).size
.Any examples here would be much appreciated :)
Thank you!
-
First I would set the counter in the strategy
__init__()
as series object:self.num_long = bt.LineNum(0)
then in the strategy
next()
I would change value ofself.num_long[0]
based on the counting rules. And then the following observer can be implemented:class StockCounter(bt.Observer): lines = ('num_long',) plotinfo = dict(plot=True, subplot=True) def next(self): self.lines.num_long[0] = self._owner.num_long[0]
I think this should work.
-
That's a nice approach. A couple of variations on the topic
class MyStrategy(bt.Strategy): lines = ('numlong',) ...
which avoids using
LineNum
by integrating the line definition in the definition of the strategy.And
class StockCounter(bt.Observer): lines = ('num_long',) def __init__(self): self.lines.num_long = self._owner.lines.num_long
should also work by establishing a binding between the 2 lines.
The actual number of holding objects can be quickly calculated in the strategy with:
holding = len([1 for d, p in self.getpositions() if p.size])
-
With the latter also being possible as for example
holding = sum(bool(pos) for pos in self.getpositions().values())
# For 100% equivalence between Python2/3 from backtrader.utils.py3 import itervalues holding = sum(bool(pos) for pos in itervalues(self.getpositions()))
In practical terms it really shouldn't make a difference to use
.values()
even if that generates a copy in Python2, because the number of items being held is not going to have needed magnitude to matter.Updated
To change items to values -
Awesome thank you guys!
@backtrader, when I use my old counting method it works perfectly, however when I use
holding = sum(bool(pos) for pos in self.getpositions().items())
it always plots 200 as a flat line (i.e. it thinks I am holding every possible stock... so somehow this method is counting everything, not just those in market? Note: I am using Python 3.Thanks
-
Because
items
always returns a tuple and that evaluates toTrue
. It should have saidvalues
. The answer has been updated to avoid future miscopying.