backtesting.py
backtesting.py copied to clipboard
A single trade wipes out all the cash
Strategy
It's a very simple, naive strategy based on MACD: it returns only one trade over a period of 6 months (BCH-USD).
Actual Behavior
The issue is that, even if the order size is 0.1 that single trade wipes out all my capital (10,000). Indeed, in the stats I see Return=-100%. How can a single trade return -100% with an order size of 0.1? Any idea why this happens?
order_size = 0.1
fastperiod = 12
slowperiod = 26
signalperiod = 9
def init(self):
close = self.data.Close
self.macd = self.I(talib.MACD, close, self.fastperiod, self.slowperiod, self.signalperiod)
self.ema_slow = self.I(talib.EMA, close, self.slowperiod)
self.ema_fast = self.I(talib.EMA, close, self.fastperiod)
def next(self):
price = self.data.Close[-1]
if self.macd[0] > 0 and self.macd[1] > 0 and crossover(self.ema_fast, self.ema_slow):
self.sell()
elif self.macd[0] < 0 and self.macd[1] < 0 and crossover(self.ema_slow, self.ema_fast):
self.buy(size=self.order_size, limit=None, stop=None)
full_data_macd = full_data.copy()
bt_macd = Backtest(full_data_macd, MACD_Strategy, cash=10000, commission=.00008, exclusive_orders=True)
stats_macd = bt_macd.run()
Additional info
- Backtesting version: 0.3.3
-
bokeh.__version__
: 3.3.0 - OS: MacOS Monterey
I suspect the error is in the following lines of code, specifically your indexes:
if self.macd[0] > 0 and self.macd[1] > 0 and crossover(self.ema_fast, self.ema_slow):
self.sell()
elif self.macd[0] < 0 and self.macd[1] < 0 and crossover(self.ema_slow, self.ema_fast):
self.buy(size=self.order_size, limit=None, stop=None)
An index of -1
denotes the current candle, so by setting an index of 0
and 1
you are trying to ``look forward''.
Thanks for your reply. Initially I thought you were right, but then I've checked better: self.macd[0] and self.macd[1] refer to the first two values in the MACD indicator, the MACD line and the signal line. It's correct what I copied. Indeed, if I need the current candle I use self.data.Close[-1]. Anyway, even if I replace [0] and [1] with [-1] and [-2] nothing really changes, there is still 1 trade that wipes all the cash out:
i believe thats still an index problem for example using your original code with index 0 and 1 i get (low # trades with and maybe too long of a trade):
but when i use -1 and 0 i get this (more trades):
like this:
if self.macd[-1] > 0 and self.macd[0] > 0 and crossover(self.ema_fast, self.ema_slow):
self.sell()
elif self.macd[-1] < 0 and self.macd[0] < 0 and crossover(self.ema_slow, self.ema_fast):
self.buy(size=self.order_size, limit=None, stop=None)
late reply, but in:
if self.macd[0] > 0 and self.macd[1] > 0 and crossover(self.ema_fast, self.ema_slow):
self.sell()
elif self.macd[0] < 0 and self.macd[1] < 0 and crossover(self.ema_slow, self.ema_fast):
self.buy(size=self.order_size, limit=None, stop=None)
your size is not set for self.sell()
. You only set it for self.buy()