mirror of
https://github.com/freqtrade/freqtrade.git
synced 2024-09-20 09:31:12 +00:00
Merge pull request #9298 from freqtrade/funding_fees
improve Funding fee behavior
This commit is contained in:
commit
fa174a392a
|
@ -132,7 +132,7 @@ class FreqtradeBot(LoggingMixin):
|
|||
# TODO: This would be more efficient if scheduled in utc time, and performed at each
|
||||
# TODO: funding interval, specified by funding_fee_times on the exchange classes
|
||||
for time_slot in range(0, 24):
|
||||
for minutes in [0, 15, 30, 45]:
|
||||
for minutes in [1, 31]:
|
||||
t = str(time(time_slot, minutes, 2))
|
||||
self._schedule.every().day.at(t).do(update)
|
||||
self.last_process: Optional[datetime] = None
|
||||
|
@ -199,6 +199,7 @@ class FreqtradeBot(LoggingMixin):
|
|||
# Only update open orders on startup
|
||||
# This will update the database after the initial migration
|
||||
self.startup_update_open_orders()
|
||||
self.update_funding_fees()
|
||||
|
||||
def process(self) -> None:
|
||||
"""
|
||||
|
@ -378,9 +379,6 @@ class FreqtradeBot(LoggingMixin):
|
|||
|
||||
logger.warning(f"Error updating Order {order.order_id} due to {e}")
|
||||
|
||||
if self.trading_mode == TradingMode.FUTURES:
|
||||
self._schedule.run_pending()
|
||||
|
||||
def update_trades_without_assigned_fees(self) -> None:
|
||||
"""
|
||||
Update closed trades without close fees assigned.
|
||||
|
|
|
@ -115,6 +115,7 @@ def migrate_trades_and_orders_table(
|
|||
# Futures Properties
|
||||
interest_rate = get_column_def(cols, 'interest_rate', '0.0')
|
||||
funding_fees = get_column_def(cols, 'funding_fees', '0.0')
|
||||
funding_fee_running = get_column_def(cols, 'funding_fee_running', 'null')
|
||||
max_stake_amount = get_column_def(cols, 'max_stake_amount', 'stake_amount')
|
||||
|
||||
# If ticker-interval existed use that, else null.
|
||||
|
@ -163,7 +164,7 @@ def migrate_trades_and_orders_table(
|
|||
max_rate, min_rate, exit_reason, exit_order_status, strategy, enter_tag,
|
||||
timeframe, open_trade_value, close_profit_abs,
|
||||
trading_mode, leverage, liquidation_price, is_short,
|
||||
interest_rate, funding_fees, realized_profit,
|
||||
interest_rate, funding_fees, funding_fee_running, realized_profit,
|
||||
amount_precision, price_precision, precision_mode, contract_size,
|
||||
max_stake_amount
|
||||
)
|
||||
|
@ -192,7 +193,8 @@ def migrate_trades_and_orders_table(
|
|||
{open_trade_value} open_trade_value, {close_profit_abs} close_profit_abs,
|
||||
{trading_mode} trading_mode, {leverage} leverage, {liquidation_price} liquidation_price,
|
||||
{is_short} is_short, {interest_rate} interest_rate,
|
||||
{funding_fees} funding_fees, {realized_profit} realized_profit,
|
||||
{funding_fees} funding_fees, {funding_fee_running} funding_fee_running,
|
||||
{realized_profit} realized_profit,
|
||||
{amount_precision} amount_precision, {price_precision} price_precision,
|
||||
{precision_mode} precision_mode, {contract_size} contract_size,
|
||||
{max_stake_amount} max_stake_amount
|
||||
|
@ -329,8 +331,8 @@ def check_migrate(engine, decl_base, previous_tables) -> None:
|
|||
# if ('orders' not in previous_tables
|
||||
# or not has_column(cols_orders, 'funding_fee')):
|
||||
migrating = False
|
||||
# if not has_column(cols_trades, 'is_stop_loss_trailing'):
|
||||
if not has_column(cols_orders, 'ft_cancel_reason'):
|
||||
# if not has_column(cols_orders, 'ft_cancel_reason'):
|
||||
if not has_column(cols_trades, 'funding_fee_running'):
|
||||
migrating = True
|
||||
logger.info(f"Running database migration for trades - "
|
||||
f"backup: {table_back_name}, {order_table_bak_name}")
|
||||
|
|
|
@ -246,7 +246,8 @@ class Order(ModelBase):
|
|||
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
|
||||
self.funding_fee = trade.funding_fee_running
|
||||
trade.funding_fee_running = 0.0
|
||||
|
||||
if (self.ft_order_side == trade.entry_side and self.price):
|
||||
trade.open_rate = self.price
|
||||
|
@ -393,6 +394,9 @@ class LocalTrade:
|
|||
|
||||
# Futures properties
|
||||
funding_fees: Optional[float] = None
|
||||
# Used to keep running funding fees - between the last filled order and now
|
||||
# Shall not be used for calculations!
|
||||
funding_fee_running: Optional[float] = None
|
||||
|
||||
@property
|
||||
def stoploss_or_liquidation(self) -> float:
|
||||
|
@ -664,7 +668,9 @@ class LocalTrade:
|
|||
"""
|
||||
if funding_fee is None:
|
||||
return
|
||||
self.funding_fees = funding_fee
|
||||
self.funding_fee_running = funding_fee
|
||||
prior_funding_fees = sum([o.funding_fee for o in self.orders if o.funding_fee])
|
||||
self.funding_fees = prior_funding_fees + funding_fee
|
||||
|
||||
def __set_stop_loss(self, stop_loss: float, percent: float):
|
||||
"""
|
||||
|
@ -747,7 +753,9 @@ class LocalTrade:
|
|||
|
||||
logger.info(f'Updating trade (id={self.id}) ...')
|
||||
if order.ft_order_side != 'stoploss':
|
||||
order.funding_fee = self.funding_fees
|
||||
order.funding_fee = self.funding_fee_running
|
||||
# Reset running funding fees
|
||||
self.funding_fee_running = 0.0
|
||||
|
||||
if order.ft_order_side == self.entry_side:
|
||||
# Update open rate and actual amount
|
||||
|
@ -1489,6 +1497,8 @@ class Trade(ModelBase, LocalTrade):
|
|||
# Futures properties
|
||||
funding_fees: Mapped[Optional[float]] = mapped_column(
|
||||
Float(), nullable=True, default=None) # type: ignore
|
||||
funding_fee_running: Mapped[Optional[float]] = mapped_column(
|
||||
Float(), nullable=True, default=None) # type: ignore
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
from_json = kwargs.pop('__FROM_JSON', None)
|
||||
|
|
|
@ -583,7 +583,7 @@ def test_calc_open_close_trade_price(
|
|||
oobj.update_from_ccxt_object(entry_order)
|
||||
trade.update_trade(oobj)
|
||||
|
||||
trade.funding_fees = funding_fees
|
||||
trade.funding_fee_running = funding_fees
|
||||
|
||||
oobj = Order.parse_from_ccxt_object(exit_order, 'ADA/USDT', trade.exit_side)
|
||||
oobj._trade_live = trade
|
||||
|
@ -591,7 +591,9 @@ def test_calc_open_close_trade_price(
|
|||
trade.update_trade(oobj)
|
||||
|
||||
assert trade.is_open is False
|
||||
# Funding fees transfer from funding_fee_running to funding_Fees
|
||||
assert trade.funding_fees == funding_fees
|
||||
assert trade.orders[-1].funding_fee == funding_fees
|
||||
|
||||
assert pytest.approx(trade._calc_open_trade_value(trade.amount, trade.open_rate)) == open_value
|
||||
assert pytest.approx(trade.calc_close_trade_value(trade.close_rate)) == close_value
|
||||
|
|
|
@ -5917,16 +5917,17 @@ def test_get_valid_price(mocker, default_conf_usdt) -> None:
|
|||
@pytest.mark.parametrize('trading_mode,calls,t1,t2', [
|
||||
('spot', 0, "2021-09-01 00:00:00", "2021-09-01 08:00:00"),
|
||||
('margin', 0, "2021-09-01 00:00:00", "2021-09-01 08:00:00"),
|
||||
('futures', 31, "2021-09-01 00:00:02", "2021-09-01 08:00:01"),
|
||||
('futures', 32, "2021-08-31 23:59:59", "2021-09-01 08:00:01"),
|
||||
('futures', 32, "2021-09-01 00:00:02", "2021-09-01 08:00:02"),
|
||||
('futures', 33, "2021-08-31 23:59:59", "2021-09-01 08:00:02"),
|
||||
('futures', 33, "2021-08-31 23:59:59", "2021-09-01 08:00:03"),
|
||||
('futures', 33, "2021-08-31 23:59:59", "2021-09-01 08:00:04"),
|
||||
('futures', 33, "2021-08-31 23:59:59", "2021-09-01 08:00:05"),
|
||||
('futures', 33, "2021-08-31 23:59:59", "2021-09-01 08:00:06"),
|
||||
('futures', 33, "2021-08-31 23:59:59", "2021-09-01 08:00:07"),
|
||||
('futures', 33, "2021-08-31 23:59:58", "2021-09-01 08:00:07"),
|
||||
('futures', 15, "2021-09-01 00:01:02", "2021-09-01 08:00:01"),
|
||||
('futures', 16, "2021-09-01 00:00:02", "2021-09-01 08:00:01"),
|
||||
('futures', 16, "2021-08-31 23:59:59", "2021-09-01 08:00:01"),
|
||||
('futures', 16, "2021-09-01 00:00:02", "2021-09-01 08:00:02"),
|
||||
('futures', 16, "2021-08-31 23:59:59", "2021-09-01 08:00:02"),
|
||||
('futures', 16, "2021-08-31 23:59:59", "2021-09-01 08:00:03"),
|
||||
('futures', 16, "2021-08-31 23:59:59", "2021-09-01 08:00:04"),
|
||||
('futures', 17, "2021-08-31 23:59:59", "2021-09-01 08:01:05"),
|
||||
('futures', 17, "2021-08-31 23:59:59", "2021-09-01 08:01:06"),
|
||||
('futures', 17, "2021-08-31 23:59:59", "2021-09-01 08:01:07"),
|
||||
('futures', 17, "2021-08-31 23:59:58", "2021-09-01 08:01:07"),
|
||||
])
|
||||
def test_update_funding_fees_schedule(mocker, default_conf, trading_mode, calls, time_machine,
|
||||
t1, t2):
|
||||
|
|
Loading…
Reference in New Issue
Block a user