2023-08-31 06:14:14 +00:00
|
|
|
from datetime import datetime, timedelta, timezone
|
2022-12-30 06:47:00 +00:00
|
|
|
from unittest.mock import MagicMock
|
|
|
|
|
2023-01-26 18:58:42 +00:00
|
|
|
from freqtrade.enums.marginmode import MarginMode
|
|
|
|
from freqtrade.enums.tradingmode import TradingMode
|
2023-08-31 06:14:14 +00:00
|
|
|
from tests.conftest import EXMS, get_mock_coro, get_patched_exchange
|
2023-01-26 18:58:42 +00:00
|
|
|
from tests.exchange.test_exchange import ccxt_exceptionhandlers
|
|
|
|
|
|
|
|
|
|
|
|
def test_additional_exchange_init_bybit(default_conf, mocker):
|
|
|
|
default_conf['dry_run'] = False
|
|
|
|
default_conf['trading_mode'] = TradingMode.FUTURES
|
|
|
|
default_conf['margin_mode'] = MarginMode.ISOLATED
|
|
|
|
api_mock = MagicMock()
|
|
|
|
api_mock.set_position_mode = MagicMock(return_value={"dualSidePosition": False})
|
|
|
|
get_patched_exchange(mocker, default_conf, id="bybit", api_mock=api_mock)
|
|
|
|
assert api_mock.set_position_mode.call_count == 1
|
|
|
|
ccxt_exceptionhandlers(mocker, default_conf, api_mock, 'bybit',
|
|
|
|
"additional_exchange_init", "set_position_mode")
|
2022-12-30 06:47:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_bybit_fetch_funding_rate(default_conf, mocker):
|
|
|
|
default_conf['trading_mode'] = 'futures'
|
|
|
|
default_conf['margin_mode'] = 'isolated'
|
|
|
|
api_mock = MagicMock()
|
|
|
|
api_mock.fetch_funding_rate_history = get_mock_coro(return_value=[])
|
|
|
|
exchange = get_patched_exchange(mocker, default_conf, id='bybit', api_mock=api_mock)
|
2023-08-08 18:23:01 +00:00
|
|
|
limit = 200
|
2022-12-30 06:47:00 +00:00
|
|
|
# Test fetch_funding_rate_history (current data)
|
|
|
|
await exchange._fetch_funding_rate_history(
|
|
|
|
pair='BTC/USDT:USDT',
|
|
|
|
timeframe='4h',
|
|
|
|
limit=limit,
|
|
|
|
)
|
|
|
|
|
|
|
|
assert api_mock.fetch_funding_rate_history.call_count == 1
|
|
|
|
assert api_mock.fetch_funding_rate_history.call_args_list[0][0][0] == 'BTC/USDT:USDT'
|
|
|
|
kwargs = api_mock.fetch_funding_rate_history.call_args_list[0][1]
|
|
|
|
assert kwargs['since'] is None
|
|
|
|
|
|
|
|
api_mock.fetch_funding_rate_history.reset_mock()
|
|
|
|
since_ms = 1610000000000
|
|
|
|
# Test fetch_funding_rate_history (current data)
|
|
|
|
await exchange._fetch_funding_rate_history(
|
|
|
|
pair='BTC/USDT:USDT',
|
|
|
|
timeframe='4h',
|
|
|
|
limit=limit,
|
|
|
|
since_ms=since_ms,
|
|
|
|
)
|
|
|
|
|
|
|
|
assert api_mock.fetch_funding_rate_history.call_count == 1
|
|
|
|
assert api_mock.fetch_funding_rate_history.call_args_list[0][0][0] == 'BTC/USDT:USDT'
|
|
|
|
kwargs = api_mock.fetch_funding_rate_history.call_args_list[0][1]
|
|
|
|
assert kwargs['since'] == since_ms
|
2023-02-26 14:41:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_bybit_get_funding_fees(default_conf, mocker):
|
|
|
|
now = datetime.now(timezone.utc)
|
|
|
|
exchange = get_patched_exchange(mocker, default_conf, id='bybit')
|
|
|
|
exchange._fetch_and_calculate_funding_fees = MagicMock()
|
|
|
|
exchange.get_funding_fees('BTC/USDT:USDT', 1, False, now)
|
|
|
|
assert exchange._fetch_and_calculate_funding_fees.call_count == 0
|
|
|
|
|
|
|
|
default_conf['trading_mode'] = 'futures'
|
|
|
|
default_conf['margin_mode'] = 'isolated'
|
|
|
|
exchange = get_patched_exchange(mocker, default_conf, id='bybit')
|
|
|
|
exchange._fetch_and_calculate_funding_fees = MagicMock()
|
|
|
|
exchange.get_funding_fees('BTC/USDT:USDT', 1, False, now)
|
|
|
|
|
|
|
|
assert exchange._fetch_and_calculate_funding_fees.call_count == 1
|
2023-08-31 06:14:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_bybit_fetch_orders(default_conf, mocker, limit_order):
|
|
|
|
|
|
|
|
api_mock = MagicMock()
|
|
|
|
api_mock.fetch_orders = MagicMock(return_value=[
|
|
|
|
limit_order['buy'],
|
|
|
|
limit_order['sell'],
|
|
|
|
])
|
|
|
|
api_mock.fetch_open_orders = MagicMock(return_value=[limit_order['buy']])
|
|
|
|
api_mock.fetch_closed_orders = MagicMock(return_value=[limit_order['buy']])
|
|
|
|
|
|
|
|
mocker.patch(f'{EXMS}.exchange_has', return_value=True)
|
|
|
|
start_time = datetime.now(timezone.utc) - timedelta(days=20)
|
|
|
|
|
|
|
|
exchange = get_patched_exchange(mocker, default_conf, api_mock, id='bybit')
|
|
|
|
# Not available in dry-run
|
|
|
|
assert exchange.fetch_orders('mocked', start_time) == []
|
|
|
|
assert api_mock.fetch_orders.call_count == 0
|
|
|
|
default_conf['dry_run'] = False
|
|
|
|
|
|
|
|
exchange = get_patched_exchange(mocker, default_conf, api_mock, id='bybit')
|
|
|
|
res = exchange.fetch_orders('mocked', start_time)
|
|
|
|
# Bybit will call the endpoint 3 times, as it has a limit of 7 days per call
|
|
|
|
assert api_mock.fetch_orders.call_count == 3
|
|
|
|
assert api_mock.fetch_open_orders.call_count == 0
|
|
|
|
assert api_mock.fetch_closed_orders.call_count == 0
|
|
|
|
assert len(res) == 2 * 3
|