enzoampil / fastquant

fastquant — Backtest and optimize your ML trading strategies with only 3 lines of code!
MIT License
1.54k stars 239 forks source link

[BUG] Execution price does not fit between High and Close #384

Open jbdelmundo opened 3 years ago

jbdelmundo commented 3 years ago

Problem description

When setting custom buy/sell signals, the order was executed the following day. However the execution price was still based on the current day. The execution price can be impossible because it was trying to execute today's price that may not be available the following day.

dt open high low close entry_signal exit_signal type price
0 2017-01-03 00:00:00 730 733 722.5 727 1 0 nan nan
1 2017-01-04 00:00:00 735 760 735 760 0 0 buy 727
2 2017-01-05 00:00:00 767 790 760.5 790 0 0 nan nan
3 2017-01-06 00:00:00 780 794.5 780 786.5 0 0 nan nan
4 2017-01-09 00:00:00 786.5 790 770.5 784.5 0 0 nan nan
5 2017-01-10 00:00:00 787.5 797 784 793 0 1 nan nan
6 2017-01-11 00:00:00 794 797 787 796 0 0 sell 796
7 2017-01-12 00:00:00 796.5 799.5 790.5 793.5 0 0 nan nan
8 2017-01-13 00:00:00 793.5 797.5 790 792 0 0 nan nan
9 2017-01-16 00:00:00 795.5 795.5 773 786.5 0 0 nan nan

When the entry signal is generated at 2017-01-03, the closing price is 727 Then the order is executed the following day. However the price (727) is not within the bounds of high and low at 2017-01-04

Example

Expected behavior

It can be modified in strategies/base.py by specifying the exectype here: https://github.com/enzoampil/fastquant/blob/94d938397b7ee61aa82bf0f72875d6499458200c/python/fastquant/strategies/base.py#L358

# Explicitly setting exectype=bt.Order.Close will make the next day's closing the reference price
                    self.order = self.buy(size=final_size, exectype=bt.Order.Close)

Environment

jbdelmundo commented 3 years ago

Also, the size (or amount of shares) is determined on the day the signal is generated

However, if the size * price > cash, where price is based on the execution date and not on the signal day (exectype=bt.Order.Close), the buy order will fail (order.status == order.Margin)

This usually happens when BUY_PROP = 1

jpdeleon commented 2 years ago

@jbdelmundo what's your proposed fix?

mikeejazmines commented 2 years ago

@jpdeleon in a recent PR, enzo and i were looking at the execution type and making the execution type bt.Close caused issues in intraday. Removing it has then fixed the problem.

By default it reverts to bt.Market which gets the close of the day the signal was created.

In line 496 here https://github.com/enzoampil/fastquant/pull/396/commits/329fb5e01678dd5dc8a45fef358e035b571dc611 the exectype=bt.Order.Close was removed