Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop-loss order executed at a higher price than the market price #521

Open
dlwocks31 opened this issue Oct 31, 2021 · 1 comment
Open

Stop-loss order executed at a higher price than the market price #521

dlwocks31 opened this issue Oct 31, 2021 · 1 comment
Labels
bug Something isn't working

Comments

@dlwocks31
Copy link

Expected Behavior

Consider a stop-loss order placed at a stop-loss price p. When the opening price is way below the stop-loss price p, I would expect the stop-loss order to be executed at the opening price.

Actual Behavior

The stop-loss order is executed at the stop-loss price p, which is way higher than the opening price.

Steps to Reproduce

import pandas as pd
from backtesting import Strategy, Backtest

data = {
    'Open': [100, 100, 100, 50, 50],
    'High': [100, 100, 100, 50, 50],
    'Low': [100, 100, 100, 50, 50],
    'Close': [100, 100, 100, 50, 50],
}
dataframe = pd.DataFrame(data=data)

class BaseStrategy(Strategy):
    def init(self):
        pass
    def next(self):
        if self.data.Close[-1] == 100:
            self.buy(size=1, sl=90)
    
bt = Backtest(dataframe, BaseStrategy, cash=100, trade_on_close=True)
opt = bt.run()
bt.plot()
opt._trades['ExitPrice'][0] # Expected: 50, Actual: 90

image

Additional info

  • When the trade_on_close option is False, the code works as expected.
  • Backtesting version: 0.3.2
@thanassisKalv
Copy link

Not sure if there is active maintenance of the library, but this trade_on_close bug was really annoying and found no other place that's mentioned.
Just in case anyone has solved that properly or still searching about it, I write below my dirty patch.
After checking, my backtesting results seem normal now in terms of filling price for the SL orders.
On the other hand, I am competely ignorant if these extra lines could cause any harmful side effect, so it would be nice if someone that checks that can tell her/his opinion.

class _Broker:
...
    def _process_orders(self):
        data = self._data
        open, high, low = data.Open[-1], data.High[-1], data.Low[-1]
        prev_close = data.Close[-2]
...
            else:
                # Market-if-touched / market order
                price = prev_close if self._trade_on_close else open
                price = (max(price, stop_price or -np.inf)
                         if order.is_long else
                         min(price, stop_price or np.inf))
                ########################### [fix] use Open price ###############################
                if order.parent_trade and self._trade_on_close and stop_price:
                    if order.parent_trade.is_long and order.is_short:
                        if open < stop_price:
                            price = open
                    if order.parent_trade.is_short and order.is_long:
                        if open > stop_price:
                            price = open

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants