After some further digging, it looks like that the stop orders were not expiring as expected. So, they were executed at much later than designed. My understanding of "valid" parameter is not exactly correct.... probably. Anyway, I explicitly specified the valid parameter to 1 day as such:
self.sell(data=d, size=self.pos[d], exectype = bt.Order.Stop, price = self.longTrailStop[d], valid = validTime)
where validTime is defined as:
validTime = self.data.datetime.date(0) + datetime.timedelta(days=self.params.valid)
After this change, the stop orderes are expiring as expected, see below:
### 2018-01-08 IH.CFE current positions: 143.66, trade length: 3, ATR: 41.765, trade high: 2943.39, trade low: 2901.99, close: 2934.186, longStop: 2901.622, shortStop: 2946.551
2018-01-09, Status Submitted: Ref: 275, Size: -143.66, Price: 2901.62178
2018-01-09, Status Accepted: Ref: 275, Size: -143.66, Price: 2901.62178
### 2018-01-09 IH.CFE current positions: 143.66, trade length: 4, ATR: 41.765, trade high: 2963.79, trade low: 2901.99, close: 2963.786, longStop: 2922.022, shortStop: 2946.551
2018-01-10, Status Submitted: Ref: 276, Size: -143.66, Price: 2922.02178
2018-01-10, Status Accepted: Ref: 276, Size: -143.66, Price: 2922.02178
2018-01-10, Status Expired: Ref: 275, Size: -143.66, Price: 2901.62178
### 2018-01-10 IH.CFE current positions: 143.66, trade length: 5, ATR: 41.765, trade high: 2987.39, trade low: 2901.99, close: 2984.386, longStop: 2945.622, shortStop: 2946.551
2018-01-11, Status Submitted: Ref: 277, Size: -143.66, Price: 2945.62178
2018-01-11, Status Accepted: Ref: 277, Size: -143.66, Price: 2945.62178
2018-01-11, Status Expired: Ref: 276, Size: -143.66, Price: 2922.02178
thanks all... !
You may want to create custom indicator with two lines up and down which has a CrossOver indicator inside. Something like this (not tested):
lines = ('up', 'down')
plotlines = dict(
up = bt.ind.CrossUp(smthng, smthng)
down = bt.ind.CrossDown(smthng, smthng)
I use Spyder and here is my solution (Some hack).
Change the spyder setting : "Preferences" -> "IPython console" -> "Graphics" tab -> "Graphics backend" -> "Backend" -> "Automatic"
Restart the current Console (The one inside spyder)
Import below in sequence
import matplotlib.pyplot as plt
import backtrader as bt
import backtrader.indicators as btind
import backtrader.analyzers as btanalyzers
import backtrader.feeds as btfeeds
import backtrader.strategies as btstrats
Plot with iplot = false
cerebro.plot(height= 30, iplot= False)
Run your code and you should see a separate windows pop up
Thanks for your input! Unfortunately, I don't know ahead of time which assets I would like to plot.
I would like to access something rank-able, such as returns of each asset, and make plotting decisions based on that (top-performing, mean, bottom-performing - for example).
Any ideas or tips on achieving that?
@scottz1 said in How to synchronize callbacks from strategy.stop:
I can avoid the python error by constructing the Lock object inside the strategy (then I guess it's the same process Backtrader uses)
Wrong guess. There is no synchronization of anything, because nothing communicates.
You are creating individual locks in sub-processes, and that's why there is no error ... and why there is no synchronization.
Your best bet is to follow the recommended approach, i.e.: gather the results as returned by cerebro.run and examine each instance as returned.