Update funding_fee freqtradebot test
This commit is contained in:
parent
6948414e47
commit
17bd990053
@ -1851,7 +1851,9 @@ class Exchange:
|
|||||||
|
|
||||||
mark_comb: PairWithTimeframe = (
|
mark_comb: PairWithTimeframe = (
|
||||||
pair, '1h', CandleType.from_string(self._ft_has["mark_ohlcv_price"]))
|
pair, '1h', CandleType.from_string(self._ft_has["mark_ohlcv_price"]))
|
||||||
# TODO-lev: funding_rate downloading this way is not yet possible.
|
|
||||||
|
# TODO-lev: 1h seems arbitrary and generates a lot of "empty" lines
|
||||||
|
# TODO-lev: probably a exchange-adjusted parameter would make more sense
|
||||||
funding_comb: PairWithTimeframe = (pair, '1h', CandleType.FUNDING_RATE)
|
funding_comb: PairWithTimeframe = (pair, '1h', CandleType.FUNDING_RATE)
|
||||||
candle_histories = self.refresh_latest_ohlcv(
|
candle_histories = self.refresh_latest_ohlcv(
|
||||||
[mark_comb, funding_comb],
|
[mark_comb, funding_comb],
|
||||||
@ -1863,7 +1865,7 @@ class Exchange:
|
|||||||
mark_rates = candle_histories[mark_comb]
|
mark_rates = candle_histories[mark_comb]
|
||||||
|
|
||||||
df = funding_rates.merge(mark_rates, on='date', how="inner", suffixes=["_fund", "_mark"])
|
df = funding_rates.merge(mark_rates, on='date', how="inner", suffixes=["_fund", "_mark"])
|
||||||
# TODO-lev: filter for relevant timeperiod?
|
df = df[(df['date'] >= open_date) & (df['date'] <= close_date)]
|
||||||
fees = sum(df['open_fund'] * df['open_mark'] * amount)
|
fees = sum(df['open_fund'] * df['open_mark'] * amount)
|
||||||
|
|
||||||
return fees
|
return fees
|
||||||
|
@ -3498,7 +3498,7 @@ def test__calculate_funding_fees(
|
|||||||
|
|
||||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange)
|
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange)
|
||||||
funding_fees = exchange._calculate_funding_fees('ADA/USDT', amount, d1, d2)
|
funding_fees = exchange._calculate_funding_fees('ADA/USDT', amount, d1, d2)
|
||||||
assert pytest.approx(funding_fees, expected_fees)
|
assert pytest.approx(funding_fees) == expected_fees
|
||||||
|
|
||||||
|
|
||||||
@ pytest.mark.parametrize('exchange,expected_fees', [
|
@ pytest.mark.parametrize('exchange,expected_fees', [
|
||||||
|
@ -9,6 +9,7 @@ from unittest.mock import ANY, MagicMock, PropertyMock
|
|||||||
|
|
||||||
import arrow
|
import arrow
|
||||||
import pytest
|
import pytest
|
||||||
|
from pandas import DataFrame
|
||||||
|
|
||||||
from freqtrade.constants import CANCEL_REASON, MATH_CLOSE_PREC, UNLIMITED_STAKE_AMOUNT
|
from freqtrade.constants import CANCEL_REASON, MATH_CLOSE_PREC, UNLIMITED_STAKE_AMOUNT
|
||||||
from freqtrade.enums import CandleType, RPCMessageType, RunMode, SellType, SignalDirection, State
|
from freqtrade.enums import CandleType, RPCMessageType, RunMode, SellType, SignalDirection, State
|
||||||
@ -4802,60 +4803,67 @@ def test_update_funding_fees(
|
|||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
default_conf['trading_mode'] = 'futures'
|
default_conf['trading_mode'] = 'futures'
|
||||||
default_conf['collateral'] = 'isolated'
|
default_conf['collateral'] = 'isolated'
|
||||||
default_conf['dry_run'] = True
|
|
||||||
timestamp_midnight = 1630454400000
|
|
||||||
timestamp_eight = 1630483200000
|
|
||||||
funding_rates_midnight = {
|
|
||||||
"LTC/BTC": {
|
|
||||||
timestamp_midnight: 0.00032583,
|
|
||||||
},
|
|
||||||
"ETH/BTC": {
|
|
||||||
timestamp_midnight: 0.0001,
|
|
||||||
},
|
|
||||||
"XRP/BTC": {
|
|
||||||
timestamp_midnight: 0.00049426,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
funding_rates_eight = {
|
date_midnight = arrow.get('2021-09-01 00:00:00')
|
||||||
"LTC/BTC": {
|
date_eight = arrow.get('2021-09-01 08:00:00')
|
||||||
timestamp_midnight: 0.00032583,
|
date_sixteen = arrow.get('2021-09-01 16:00:00')
|
||||||
timestamp_eight: 0.00024472,
|
columns = ['date', 'open', 'high', 'low', 'close', 'volume']
|
||||||
},
|
# 16:00 entry is actually never used
|
||||||
"ETH/BTC": {
|
# But should be kept in the test to ensure we're filtering correctly.
|
||||||
timestamp_midnight: 0.0001,
|
funding_rates = {
|
||||||
timestamp_eight: 0.0001,
|
"LTC/BTC":
|
||||||
},
|
DataFrame([
|
||||||
"XRP/BTC": {
|
[date_midnight, 0.00032583, 0, 0, 0, 0],
|
||||||
timestamp_midnight: 0.00049426,
|
[date_eight, 0.00024472, 0, 0, 0, 0],
|
||||||
timestamp_eight: 0.00032715,
|
[date_sixteen, 0.00024472, 0, 0, 0, 0],
|
||||||
}
|
], columns=columns),
|
||||||
|
"ETH/BTC":
|
||||||
|
DataFrame([
|
||||||
|
[date_midnight, 0.0001, 0, 0, 0, 0],
|
||||||
|
[date_eight, 0.0001, 0, 0, 0, 0],
|
||||||
|
[date_sixteen, 0.0001, 0, 0, 0, 0],
|
||||||
|
], columns=columns),
|
||||||
|
"XRP/BTC":
|
||||||
|
DataFrame([
|
||||||
|
[date_midnight, 0.00049426, 0, 0, 0, 0],
|
||||||
|
[date_eight, 0.00032715, 0, 0, 0, 0],
|
||||||
|
[date_sixteen, 0.00032715, 0, 0, 0, 0],
|
||||||
|
], columns=columns)
|
||||||
}
|
}
|
||||||
|
|
||||||
mark_prices = {
|
mark_prices = {
|
||||||
"LTC/BTC": {
|
"LTC/BTC":
|
||||||
timestamp_midnight: 3.3,
|
DataFrame([
|
||||||
timestamp_eight: 3.2,
|
[date_midnight, 3.3, 0, 0, 0, 0],
|
||||||
},
|
[date_eight, 3.2, 0, 0, 0, 0],
|
||||||
"ETH/BTC": {
|
[date_sixteen, 3.2, 0, 0, 0, 0],
|
||||||
timestamp_midnight: 2.4,
|
], columns=columns),
|
||||||
timestamp_eight: 2.5,
|
"ETH/BTC":
|
||||||
},
|
DataFrame([
|
||||||
"XRP/BTC": {
|
[date_midnight, 2.4, 0, 0, 0, 0],
|
||||||
timestamp_midnight: 1.2,
|
[date_eight, 2.5, 0, 0, 0, 0],
|
||||||
timestamp_eight: 1.2,
|
[date_sixteen, 2.5, 0, 0, 0, 0],
|
||||||
}
|
], columns=columns),
|
||||||
|
"XRP/BTC":
|
||||||
|
DataFrame([
|
||||||
|
[date_midnight, 1.2, 0, 0, 0, 0],
|
||||||
|
[date_eight, 1.2, 0, 0, 0, 0],
|
||||||
|
[date_sixteen, 1.2, 0, 0, 0, 0],
|
||||||
|
], columns=columns)
|
||||||
}
|
}
|
||||||
|
|
||||||
mocker.patch(
|
def refresh_latest_ohlcv_mock(pairlist, **kwargs):
|
||||||
'freqtrade.exchange.Exchange._get_mark_price_history',
|
ret = {}
|
||||||
side_effect=lambda pair, since: mark_prices[pair]
|
for p, tf, ct in pairlist:
|
||||||
)
|
if ct == CandleType.MARK:
|
||||||
|
ret[(p, tf, ct)] = mark_prices[p]
|
||||||
|
else:
|
||||||
|
ret[(p, tf, ct)] = funding_rates[p]
|
||||||
|
|
||||||
mocker.patch(
|
return ret
|
||||||
'freqtrade.exchange.Exchange.get_funding_rate_history',
|
|
||||||
side_effect=lambda pair, since: funding_rates_midnight[pair]
|
mocker.patch('freqtrade.exchange.Exchange.refresh_latest_ohlcv',
|
||||||
)
|
side_effect=refresh_latest_ohlcv_mock)
|
||||||
|
|
||||||
mocker.patch.multiple(
|
mocker.patch.multiple(
|
||||||
'freqtrade.exchange.Exchange',
|
'freqtrade.exchange.Exchange',
|
||||||
@ -4880,38 +4888,33 @@ def test_update_funding_fees(
|
|||||||
trades = Trade.get_open_trades()
|
trades = Trade.get_open_trades()
|
||||||
assert len(trades) == 3
|
assert len(trades) == 3
|
||||||
for trade in trades:
|
for trade in trades:
|
||||||
assert trade.funding_fees == (
|
assert pytest.approx(trade.funding_fees) == (
|
||||||
trade.amount *
|
trade.amount *
|
||||||
mark_prices[trade.pair][timestamp_midnight] *
|
mark_prices[trade.pair].iloc[0]['open'] *
|
||||||
funding_rates_midnight[trade.pair][timestamp_midnight]
|
funding_rates[trade.pair].iloc[0]['open']
|
||||||
)
|
)
|
||||||
mocker.patch('freqtrade.exchange.Exchange.create_order', return_value=open_exit_order)
|
mocker.patch('freqtrade.exchange.Exchange.create_order', return_value=open_exit_order)
|
||||||
# create_mock_trades(fee, False)
|
|
||||||
time_machine.move_to("2021-09-01 08:00:00 +00:00")
|
time_machine.move_to("2021-09-01 08:00:00 +00:00")
|
||||||
mocker.patch(
|
|
||||||
'freqtrade.exchange.Exchange.get_funding_rate_history',
|
|
||||||
side_effect=lambda pair, since: funding_rates_eight[pair]
|
|
||||||
)
|
|
||||||
if schedule_off:
|
if schedule_off:
|
||||||
for trade in trades:
|
for trade in trades:
|
||||||
assert trade.funding_fees == (
|
|
||||||
trade.amount *
|
|
||||||
mark_prices[trade.pair][timestamp_midnight] *
|
|
||||||
funding_rates_eight[trade.pair][timestamp_midnight]
|
|
||||||
)
|
|
||||||
freqtrade.execute_trade_exit(
|
freqtrade.execute_trade_exit(
|
||||||
trade=trade,
|
trade=trade,
|
||||||
# The values of the next 2 params are irrelevant for this test
|
# The values of the next 2 params are irrelevant for this test
|
||||||
limit=ticker_usdt_sell_up()['bid'],
|
limit=ticker_usdt_sell_up()['bid'],
|
||||||
sell_reason=SellCheckTuple(sell_type=SellType.ROI)
|
sell_reason=SellCheckTuple(sell_type=SellType.ROI)
|
||||||
)
|
)
|
||||||
|
assert trade.funding_fees == pytest.approx(sum(
|
||||||
|
trade.amount *
|
||||||
|
mark_prices[trade.pair].iloc[0:2]['open'] *
|
||||||
|
funding_rates[trade.pair].iloc[0:2]['open']
|
||||||
|
))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
freqtrade._schedule.run_pending()
|
freqtrade._schedule.run_pending()
|
||||||
|
|
||||||
# Funding fees for 00:00 and 08:00
|
# Funding fees for 00:00 and 08:00
|
||||||
for trade in trades:
|
for trade in trades:
|
||||||
assert trade.funding_fees == sum([
|
assert trade.funding_fees == pytest.approx(sum(
|
||||||
trade.amount *
|
trade.amount *
|
||||||
mark_prices[trade.pair][time] *
|
mark_prices[trade.pair].iloc[0:2]['open'] * funding_rates[trade.pair].iloc[0:2]['open']
|
||||||
funding_rates_eight[trade.pair][time] for time in mark_prices[trade.pair].keys()
|
))
|
||||||
])
|
|
||||||
|
Loading…
Reference in New Issue
Block a user