kernc / backtesting.py

:mag_right: :chart_with_upwards_trend: :snake: :moneybag: Backtest trading strategies in Python.
https://kernc.github.io/backtesting.py/
GNU Affero General Public License v3.0
5.04k stars 987 forks source link

A single trade wipes out all the cash #1092

Open mrubin01 opened 7 months ago

mrubin01 commented 7 months ago

Strategy

It's a very simple, naive strategy based on MACD: it returns only one trade over a period of 6 months (BCH-USD).

Trade_1

Screenshot 2023-11-19 at 22 16 56

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

bigbenbeer commented 7 months ago

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''.

mrubin01 commented 6 months ago

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:

Screenshot 2023-12-07 at 19 24 46

Chichostyle commented 6 months ago

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):

imagen

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)

imagen

acse-ci223 commented 5 months ago

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()