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.16k stars 1.01k forks source link

Why don't use adjusted_price when close a trade ? #149

Open albertwh1te opened 3 years ago

albertwh1te commented 3 years ago

Expected Behavior

I think the exit_price in trades should be the adjusted_price. https://github.com/kernc/backtesting.py/blob/b456400e73c55afc66907013359b546b762050d4/backtesting/backtesting.py#L873

                    # Order size greater than this opposite-directed existing trade,
                    # so it will be closed completely
                    if abs(need_size) >= abs(trade.size):
                        # I think we shoud use adjusted_price 
                        self._close_trade(trade, adjusted_price, time_index)
                        need_size += trade.size
                    else:
                        # The existing trade is larger than the new order,
                        # so it will only be closed partially
                        self._reduce_trade(trade, adjusted_price, need_size, time_index)
                        need_size = 0
                        break

Actual Behavior

We are using the price right now. :)

Steps to Reproduce

  1. Just run a simple strategy
  2. check the exit_price in stats._trades
  3. compare with close price at the same
kernc commented 3 years ago

The adjusted_price is only used when opening new trades: https://github.com/kernc/backtesting.py/blob/b456400e73c55afc66907013359b546b762050d4/backtesting/backtesting.py#L887-L889 Thus, the spread/commissions are accounted for already at trade entry time (the broker ain't gonna wait for its share). If we were to use adjusted_price also when reducing/closing existing trades, the spread/commissions would be accounted for twice!

albertwh1te commented 3 years ago

the spread/commissions would be accounted for twice!

In fact, it should be... for some exchange

A client goes long 1 lot of USDCAD. The client is a ‘Silver’ account holder, so is charged $4 per $100,000 per side.

Therefore, USD volume of 1 lot of USDCAD = $100,000

So, commission charged for this trade (open and close) = $4 x 2 (all commission charged and debited on the opening of the trade)

Total commission = $8 Link is here

kernc commented 3 years ago

I see. :astonished: :sweat_smile:

Disregarding the irrelevance of this broker, since this is a commission on currency conversion, I guess they can charge it twice. (You convert EUR to GBP; here's our 0.004%. You convert GBP to EUR; here's our 0.004%.) It might be the same with some stock brokers. But, then again, this is certainly different from bid-ask spread charged by most spot brokers. :thinking:

I think I'd prefer the commission applied once per round-trip, but certainly with a documentation note of the fact. And a suggestion to pass Backtest(..., commission=2*commission_pct) if so required ...

albertwh1te commented 3 years ago

Thank you for your prompt reply. 👍 I think Backtest(..., commission=2*commission_pct) may have a little problem. For example: I opened long GBP with price at 40000 USD open_commison = 40000 0.0004 = 16
I closed order GBP with price at 20000 USD open_commison = 20000
0.0004 = 8

Currently, I am going to change the price to adjusted_price in almost every close_trade function and use my hacked version as a workaround to finished my work now. Maybe we need a param in the backtest for this scenario. https://github.com/kernc/backtesting.py/blob/b456400e73c55afc66907013359b546b762050d4/backtesting/backtesting.py#L830

But indeed, this is a very rare case. I think we should spend more time on this issue if someone else met the same problem.

kernc commented 3 years ago

I opened long GBP with price at 40000 USD open_commison = 40000 0.0004 = 16 I closed order GBP with price at 20000 USD open_commison = 20000 0.0004 = 8

Are you referring to price fluctuation or the different volume? If the volume, the total commissions should even out by the time the whole position is closed, whereas the price fluctuation (specifically in currency) shouldn't be so large that it greatly affects commission percent (e.g. I count EURUSD spread ratio up to 0.00015 whenever I look).

I guess there are cases where this is a valid point. Similarly to https://github.com/kernc/backtesting.py/issues/113. Much rather than support every possible fee structure, I'd like to keep it simple, though. :sweat_smile:

albertwh1te commented 3 years ago

I am referring to price fluctuation.

Much rather than support every possible fee structure, I'd like to keep it simple, though.

I respect your idea. I think maybe we should close this issue.

Clifford-Yen commented 2 years ago

Is it possible to reopen this issue? I also encounter the same problem. In fact, not only the currency conversion has this issue, stock markets in other countries also charge the commission on both entry and exit.

And also, is it possible to have the capability to define different commissions for entry?

adradr commented 1 year ago

I am facing the same issue here. Trying to backtest a delta neutral hedging strategy with continuous rebalancing of an initial short position. On my exchange I am paying fee for every executed trade in both buy/sell at the actual market price of the execution.

Another feature I think would be useful is to include the accrued fees in the final tear sheet.