Fix funding fee calculation for backtesting

This commit is contained in:
Matthias 2022-09-02 06:51:30 +02:00
parent 80b5f035ab
commit df50b1928d
2 changed files with 32 additions and 4 deletions

View File

@ -686,7 +686,7 @@ class Backtesting:
self.futures_data[trade.pair], self.futures_data[trade.pair],
amount=trade.amount, amount=trade.amount,
is_short=trade.is_short, is_short=trade.is_short,
open_date=trade.open_date_utc, open_date=trade.date_last_filled_utc,
close_date=exit_candle_time, close_date=exit_candle_time,
) )

View File

@ -65,6 +65,8 @@ class Order(_DECL_BASE):
order_filled_date = Column(DateTime, nullable=True) order_filled_date = Column(DateTime, nullable=True)
order_update_date = Column(DateTime, nullable=True) order_update_date = Column(DateTime, nullable=True)
funding_fee = Column(Float, nullable=True)
ft_fee_base = Column(Float, nullable=True) ft_fee_base = Column(Float, nullable=True)
@property @property
@ -72,6 +74,13 @@ class Order(_DECL_BASE):
""" Order-date with UTC timezoneinfo""" """ Order-date with UTC timezoneinfo"""
return self.order_date.replace(tzinfo=timezone.utc) return self.order_date.replace(tzinfo=timezone.utc)
@property
def order_filled_utc(self) -> Optional[datetime]:
""" last order-date with UTC timezoneinfo"""
return (
self.order_filled_date.replace(tzinfo=timezone.utc) if self.order_filled_date else None
)
@property @property
def safe_price(self) -> float: def safe_price(self) -> float:
return self.average or self.price return self.average or self.price
@ -179,6 +188,10 @@ class Order(_DECL_BASE):
self.remaining = 0 self.remaining = 0
self.status = 'closed' self.status = 'closed'
self.ft_is_open = False self.ft_is_open = False
# Assign funding fees to Order.
# Assumes backtesting will use date_last_filled_utc to calculate future funding fees.
self.funding_fee = trade.funding_fees
if (self.ft_order_side == trade.entry_side): if (self.ft_order_side == trade.entry_side):
trade.open_rate = self.price trade.open_rate = self.price
trade.recalc_trade_from_orders() trade.recalc_trade_from_orders()
@ -346,6 +359,12 @@ class LocalTrade():
else: else:
return self.amount return self.amount
@property
def date_last_filled_utc(self):
""" Date of the last filled order"""
return max([self.open_date_utc,
max(o.order_filled_utc for o in self.orders if o.filled and not o.ft_is_open)])
@property @property
def open_date_utc(self): def open_date_utc(self):
return self.open_date.replace(tzinfo=timezone.utc) return self.open_date.replace(tzinfo=timezone.utc)
@ -843,10 +862,14 @@ class LocalTrade():
close_profit = 0.0 close_profit = 0.0
close_profit_abs = 0.0 close_profit_abs = 0.0
profit = None profit = None
for o in self.orders: # Reset funding fees
self.funding_fees = 0.0
funding_fees = 0.0
ordercount = len(self.orders) - 1
for i, o in enumerate(self.orders):
if o.ft_is_open or not o.filled: if o.ft_is_open or not o.filled:
continue continue
funding_fees += (o.funding_fee or 0.0)
tmp_amount = FtPrecise(o.safe_amount_after_fee) tmp_amount = FtPrecise(o.safe_amount_after_fee)
tmp_price = FtPrecise(o.safe_price) tmp_price = FtPrecise(o.safe_price)
@ -861,7 +884,11 @@ class LocalTrade():
avg_price = current_stake / current_amount avg_price = current_stake / current_amount
if is_exit: if is_exit:
# Process partial exits # Process exits
if i == ordercount and is_closing:
# Apply funding fees only to the last order
self.funding_fees = funding_fees
exit_rate = o.safe_price exit_rate = o.safe_price
exit_amount = o.safe_amount_after_fee exit_amount = o.safe_amount_after_fee
profit = self.calc_profit(rate=exit_rate, amount=exit_amount, profit = self.calc_profit(rate=exit_rate, amount=exit_amount,
@ -871,6 +898,7 @@ class LocalTrade():
exit_rate, amount=exit_amount, open_rate=avg_price) exit_rate, amount=exit_amount, open_rate=avg_price)
else: else:
total_stake = total_stake + self._calc_open_trade_value(tmp_amount, price) total_stake = total_stake + self._calc_open_trade_value(tmp_amount, price)
self.funding_fees = funding_fees
if close_profit: if close_profit:
self.close_profit = close_profit self.close_profit = close_profit