merge develop into RL
This commit is contained in:
@@ -30,7 +30,7 @@ def test_validate_is_int():
|
||||
assert not validate_is_int('-ee')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('exchange', ['bittrex', 'binance', 'kraken', 'ftx'])
|
||||
@pytest.mark.parametrize('exchange', ['bittrex', 'binance', 'kraken'])
|
||||
def test_start_new_config(mocker, caplog, exchange):
|
||||
wt_mock = mocker.patch.object(Path, "write_text", MagicMock())
|
||||
mocker.patch.object(Path, "exists", MagicMock(return_value=True))
|
||||
|
@@ -1748,28 +1748,7 @@ def limit_buy_order_canceled_empty(request):
|
||||
# https://docs.pytest.org/en/latest/example/parametrize.html#apply-indirect-on-particular-arguments
|
||||
|
||||
exchange_name = request.param
|
||||
if exchange_name == 'ftx':
|
||||
return {
|
||||
'info': {},
|
||||
'id': '1234512345',
|
||||
'clientOrderId': None,
|
||||
'timestamp': arrow.utcnow().shift(minutes=-601).int_timestamp * 1000,
|
||||
'datetime': arrow.utcnow().shift(minutes=-601).isoformat(),
|
||||
'lastTradeTimestamp': None,
|
||||
'symbol': 'LTC/USDT',
|
||||
'type': 'limit',
|
||||
'side': 'buy',
|
||||
'price': 34.3225,
|
||||
'amount': 0.55,
|
||||
'cost': 0.0,
|
||||
'average': None,
|
||||
'filled': 0.0,
|
||||
'remaining': 0.0,
|
||||
'status': 'closed',
|
||||
'fee': None,
|
||||
'trades': None
|
||||
}
|
||||
elif exchange_name == 'kraken':
|
||||
if exchange_name == 'kraken':
|
||||
return {
|
||||
'info': {},
|
||||
'id': 'AZNPFF-4AC4N-7MKTAT',
|
||||
|
@@ -3,18 +3,19 @@ import logging
|
||||
from pathlib import Path
|
||||
from shutil import copyfile
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from freqtrade.configuration.timerange import TimeRange
|
||||
from freqtrade.data.converter import (convert_ohlcv_format, convert_trades_format,
|
||||
ohlcv_fill_up_missing_data, ohlcv_to_dataframe,
|
||||
trades_dict_to_list, trades_remove_duplicates,
|
||||
trades_to_ohlcv, trim_dataframe)
|
||||
reduce_dataframe_footprint, trades_dict_to_list,
|
||||
trades_remove_duplicates, trades_to_ohlcv, trim_dataframe)
|
||||
from freqtrade.data.history import (get_timerange, load_data, load_pair_history,
|
||||
validate_backtest_data)
|
||||
from freqtrade.data.history.idatahandler import IDataHandler
|
||||
from freqtrade.enums import CandleType
|
||||
from tests.conftest import log_has, log_has_re
|
||||
from tests.conftest import generate_test_data, log_has, log_has_re
|
||||
from tests.data.test_history import _clean_test_file
|
||||
|
||||
|
||||
@@ -344,3 +345,33 @@ def test_convert_ohlcv_format(default_conf, testdatadir, tmpdir, file_base, cand
|
||||
assert file.exists()
|
||||
for file in (files_new):
|
||||
assert not file.exists()
|
||||
|
||||
|
||||
def test_reduce_dataframe_footprint():
|
||||
data = generate_test_data('15m', 40)
|
||||
|
||||
data['open_copy'] = data['open']
|
||||
data['close_copy'] = data['close']
|
||||
data['close_copy'] = data['close']
|
||||
|
||||
assert data['open'].dtype == np.float64
|
||||
assert data['open_copy'].dtype == np.float64
|
||||
assert data['close_copy'].dtype == np.float64
|
||||
|
||||
df2 = reduce_dataframe_footprint(data)
|
||||
|
||||
# Does not modify original dataframe
|
||||
assert data['open'].dtype == np.float64
|
||||
assert data['open_copy'].dtype == np.float64
|
||||
assert data['close_copy'].dtype == np.float64
|
||||
|
||||
# skips ohlcv columns
|
||||
assert df2['open'].dtype == np.float64
|
||||
assert df2['high'].dtype == np.float64
|
||||
assert df2['low'].dtype == np.float64
|
||||
assert df2['close'].dtype == np.float64
|
||||
assert df2['volume'].dtype == np.float64
|
||||
|
||||
# Changes dtype of returned dataframe
|
||||
assert df2['open_copy'].dtype == np.float32
|
||||
assert df2['close_copy'].dtype == np.float32
|
||||
|
@@ -70,7 +70,7 @@ def test_datahandler_ohlcv_regex(filename, pair, timeframe, candletype):
|
||||
('BTC_USDT_USDT', 'BTC/USDT:USDT'), # Futures
|
||||
('XRP_USDT_USDT', 'XRP/USDT:USDT'), # futures
|
||||
('BTC-PERP', 'BTC-PERP'),
|
||||
('BTC-PERP_USDT', 'BTC-PERP:USDT'), # potential FTX case
|
||||
('BTC-PERP_USDT', 'BTC-PERP:USDT'),
|
||||
('UNITTEST_USDT', 'UNITTEST/USDT'),
|
||||
])
|
||||
def test_rebuild_pair_from_filename(input, expected):
|
||||
|
@@ -45,16 +45,6 @@ EXCHANGES = {
|
||||
'leverage_tiers_public': False,
|
||||
'leverage_in_spot_market': True,
|
||||
},
|
||||
# 'ftx': {
|
||||
# 'pair': 'BTC/USD',
|
||||
# 'stake_currency': 'USD',
|
||||
# 'hasQuoteVolume': True,
|
||||
# 'timeframe': '5m',
|
||||
# 'futures_pair': 'BTC/USD:USD',
|
||||
# 'futures': False,
|
||||
# 'leverage_tiers_public': False, # TODO: Set to True once implemented on CCXT
|
||||
# 'leverage_in_spot_market': True,
|
||||
# },
|
||||
'kucoin': {
|
||||
'pair': 'XRP/USDT',
|
||||
'stake_currency': 'USDT',
|
||||
|
@@ -27,7 +27,7 @@ from tests.conftest import (generate_test_data_raw, get_mock_coro, get_patched_e
|
||||
|
||||
|
||||
# Make sure to always keep one exchange here which is NOT subclassed!!
|
||||
EXCHANGES = ['bittrex', 'binance', 'kraken', 'ftx', 'gateio']
|
||||
EXCHANGES = ['bittrex', 'binance', 'kraken', 'gateio']
|
||||
|
||||
get_entry_rate_data = [
|
||||
('other', 20, 19, 10, 0.0, 20), # Full ask side
|
||||
@@ -3162,19 +3162,16 @@ def test_cancel_stoploss_order(default_conf, mocker, exchange_name):
|
||||
def test_cancel_stoploss_order_with_result(default_conf, mocker, exchange_name):
|
||||
default_conf['dry_run'] = False
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_stoploss_order', return_value={'for': 123})
|
||||
mocker.patch('freqtrade.exchange.Ftx.fetch_stoploss_order', return_value={'for': 123})
|
||||
mocker.patch('freqtrade.exchange.Gateio.fetch_stoploss_order', return_value={'for': 123})
|
||||
exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
|
||||
|
||||
res = {'fee': {}, 'status': 'canceled', 'amount': 1234}
|
||||
mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order', return_value=res)
|
||||
mocker.patch('freqtrade.exchange.Ftx.cancel_stoploss_order', return_value=res)
|
||||
mocker.patch('freqtrade.exchange.Gateio.cancel_stoploss_order', return_value=res)
|
||||
co = exchange.cancel_stoploss_order_with_result(order_id='_', pair='TKN/BTC', amount=555)
|
||||
assert co == res
|
||||
|
||||
mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order', return_value='canceled')
|
||||
mocker.patch('freqtrade.exchange.Ftx.cancel_stoploss_order', return_value='canceled')
|
||||
mocker.patch('freqtrade.exchange.Gateio.cancel_stoploss_order', return_value='canceled')
|
||||
# Fall back to fetch_stoploss_order
|
||||
co = exchange.cancel_stoploss_order_with_result(order_id='_', pair='TKN/BTC', amount=555)
|
||||
@@ -3182,7 +3179,6 @@ def test_cancel_stoploss_order_with_result(default_conf, mocker, exchange_name):
|
||||
|
||||
exc = InvalidOrderException("")
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_stoploss_order', side_effect=exc)
|
||||
mocker.patch('freqtrade.exchange.Ftx.fetch_stoploss_order', side_effect=exc)
|
||||
mocker.patch('freqtrade.exchange.Gateio.fetch_stoploss_order', side_effect=exc)
|
||||
co = exchange.cancel_stoploss_order_with_result(order_id='_', pair='TKN/BTC', amount=555)
|
||||
assert co['amount'] == 555
|
||||
@@ -3191,7 +3187,6 @@ def test_cancel_stoploss_order_with_result(default_conf, mocker, exchange_name):
|
||||
with pytest.raises(InvalidOrderException):
|
||||
exc = InvalidOrderException("Did not find order")
|
||||
mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order', side_effect=exc)
|
||||
mocker.patch('freqtrade.exchange.Ftx.cancel_stoploss_order', side_effect=exc)
|
||||
mocker.patch('freqtrade.exchange.Gateio.cancel_stoploss_order', side_effect=exc)
|
||||
exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
|
||||
exchange.cancel_stoploss_order_with_result(order_id='_', pair='TKN/BTC', amount=123)
|
||||
@@ -3253,9 +3248,6 @@ def test_fetch_order(default_conf, mocker, exchange_name, caplog):
|
||||
@pytest.mark.usefixtures("init_persistence")
|
||||
@pytest.mark.parametrize("exchange_name", EXCHANGES)
|
||||
def test_fetch_stoploss_order(default_conf, mocker, exchange_name):
|
||||
# Don't test FTX here - that needs a separate test
|
||||
if exchange_name == 'ftx':
|
||||
return
|
||||
default_conf['dry_run'] = True
|
||||
order = MagicMock()
|
||||
order.myid = 123
|
||||
@@ -3699,16 +3691,6 @@ def test_date_minus_candles():
|
||||
# no darkpools
|
||||
("BTC/EUR.d", 'BTC', 'EUR', "kraken", True, False, False, 'spot',
|
||||
{"darkpool": True}, False),
|
||||
("BTC/USD", 'BTC', 'USD', "ftx", True, False, False, 'spot', {}, True),
|
||||
("USD/BTC", 'USD', 'BTC', "ftx", True, False, False, 'spot', {}, True),
|
||||
# Can only trade spot markets
|
||||
("BTC/USD", 'BTC', 'USD', "ftx", False, False, True, 'spot', {}, False),
|
||||
("BTC/USD", 'BTC', 'USD', "ftx", False, False, True, 'futures', {}, True),
|
||||
# Can only trade spot markets
|
||||
("BTC-PERP", 'BTC', 'USD', "ftx", False, False, True, 'spot', {}, False),
|
||||
("BTC-PERP", 'BTC', 'USD', "ftx", False, False, True, 'margin', {}, False),
|
||||
("BTC-PERP", 'BTC', 'USD', "ftx", False, False, True, 'futures', {}, True),
|
||||
|
||||
("BTC/USDT:USDT", 'BTC', 'USD', "okx", False, False, True, 'spot', {}, False),
|
||||
("BTC/USDT:USDT", 'BTC', 'USD', "okx", False, False, True, 'margin', {}, False),
|
||||
("BTC/USDT:USDT", 'BTC', 'USD', "okx", False, False, True, 'futures', {}, True),
|
||||
@@ -3841,7 +3823,7 @@ def test_calculate_backoff(retrycount, max_retries, expected):
|
||||
assert calculate_backoff(retrycount, max_retries) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("exchange_name", ['binance', 'ftx'])
|
||||
@pytest.mark.parametrize("exchange_name", ['binance'])
|
||||
def test__get_funding_fees_from_exchange(default_conf, mocker, exchange_name):
|
||||
api_mock = MagicMock()
|
||||
api_mock.fetch_funding_history = MagicMock(return_value=[
|
||||
@@ -3909,7 +3891,7 @@ def test__get_funding_fees_from_exchange(default_conf, mocker, exchange_name):
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('exchange', ['binance', 'kraken', 'ftx'])
|
||||
@pytest.mark.parametrize('exchange', ['binance', 'kraken'])
|
||||
@pytest.mark.parametrize('stake_amount,leverage,min_stake_with_lev', [
|
||||
(9.0, 3.0, 3.0),
|
||||
(20.0, 5.0, 4.0),
|
||||
@@ -3930,8 +3912,6 @@ def test_get_stake_amount_considering_leverage(
|
||||
|
||||
@pytest.mark.parametrize("exchange_name,trading_mode", [
|
||||
("binance", TradingMode.FUTURES),
|
||||
("ftx", TradingMode.MARGIN),
|
||||
("ftx", TradingMode.FUTURES)
|
||||
])
|
||||
def test__set_leverage(mocker, default_conf, exchange_name, trading_mode):
|
||||
|
||||
@@ -3982,9 +3962,6 @@ def test_set_margin_mode(mocker, default_conf, margin_mode):
|
||||
("kraken", TradingMode.SPOT, None, False),
|
||||
("kraken", TradingMode.MARGIN, MarginMode.ISOLATED, True),
|
||||
("kraken", TradingMode.FUTURES, MarginMode.ISOLATED, True),
|
||||
("ftx", TradingMode.SPOT, None, False),
|
||||
("ftx", TradingMode.MARGIN, MarginMode.ISOLATED, True),
|
||||
("ftx", TradingMode.FUTURES, MarginMode.ISOLATED, True),
|
||||
("bittrex", TradingMode.SPOT, None, False),
|
||||
("bittrex", TradingMode.MARGIN, MarginMode.CROSS, True),
|
||||
("bittrex", TradingMode.MARGIN, MarginMode.ISOLATED, True),
|
||||
@@ -4005,8 +3982,6 @@ def test_set_margin_mode(mocker, default_conf, margin_mode):
|
||||
("binance", TradingMode.FUTURES, MarginMode.CROSS, True),
|
||||
("kraken", TradingMode.MARGIN, MarginMode.CROSS, True),
|
||||
("kraken", TradingMode.FUTURES, MarginMode.CROSS, True),
|
||||
("ftx", TradingMode.MARGIN, MarginMode.CROSS, True),
|
||||
("ftx", TradingMode.FUTURES, MarginMode.CROSS, True),
|
||||
("gateio", TradingMode.MARGIN, MarginMode.CROSS, True),
|
||||
("gateio", TradingMode.FUTURES, MarginMode.CROSS, True),
|
||||
|
||||
@@ -4015,8 +3990,6 @@ def test_set_margin_mode(mocker, default_conf, margin_mode):
|
||||
# ("binance", TradingMode.FUTURES, MarginMode.CROSS, False),
|
||||
# ("kraken", TradingMode.MARGIN, MarginMode.CROSS, False),
|
||||
# ("kraken", TradingMode.FUTURES, MarginMode.CROSS, False),
|
||||
# ("ftx", TradingMode.MARGIN, MarginMode.CROSS, False),
|
||||
# ("ftx", TradingMode.FUTURES, MarginMode.CROSS, False),
|
||||
# ("gateio", TradingMode.MARGIN, MarginMode.CROSS, False),
|
||||
# ("gateio", TradingMode.FUTURES, MarginMode.CROSS, False),
|
||||
])
|
||||
@@ -4046,7 +4019,6 @@ def test_validate_trading_mode_and_margin_mode(
|
||||
("bibox", "futures", {"has": {"fetchCurrencies": False}, "options": {"defaultType": "swap"}}),
|
||||
("bybit", "spot", {"options": {"defaultType": "spot"}}),
|
||||
("bybit", "futures", {"options": {"defaultType": "linear"}}),
|
||||
("ftx", "futures", {"options": {"defaultType": "swap"}}),
|
||||
("gateio", "futures", {"options": {"defaultType": "swap"}}),
|
||||
("hitbtc", "futures", {"options": {"defaultType": "swap"}}),
|
||||
("kraken", "futures", {"options": {"defaultType": "swap"}}),
|
||||
@@ -4223,11 +4195,6 @@ def test_combine_funding_and_mark(
|
||||
# ('kraken', "2021-09-01 00:00:00", "2021-09-01 07:59:59", 30.0, -0.0012443999999999999),
|
||||
# ('kraken', "2021-09-01 00:00:00", "2021-09-01 12:00:00", 30.0, 0.0045759),
|
||||
# ('kraken', "2021-09-01 00:00:01", "2021-09-01 08:00:00", 30.0, -0.0008289),
|
||||
('ftx', 0, 2, "2021-09-01 00:10:00", "2021-09-01 00:30:00", 30.0, 0.0),
|
||||
('ftx', 0, 9, "2021-09-01 00:00:00", "2021-09-01 08:00:00", 30.0, 0.0010008),
|
||||
('ftx', 0, 13, "2021-09-01 00:00:00", "2021-09-01 12:00:00", 30.0, 0.0146691),
|
||||
('ftx', 0, 9, "2021-09-01 00:00:00", "2021-09-01 08:00:00", 50.0, 0.001668),
|
||||
('ftx', 1, 9, "2021-09-01 00:00:01", "2021-09-01 08:00:00", 30.0, 0.0019932),
|
||||
('gateio', 0, 2, "2021-09-01 00:10:00", "2021-09-01 04:00:00", 30.0, 0.0),
|
||||
('gateio', 0, 2, "2021-09-01 00:00:00", "2021-09-01 08:00:00", 30.0, -0.0009140999),
|
||||
('gateio', 0, 2, "2021-09-01 00:00:00", "2021-09-01 12:00:00", 30.0, -0.0009140999),
|
||||
@@ -4289,7 +4256,6 @@ def test__fetch_and_calculate_funding_fees(
|
||||
d2 = datetime.strptime(f"{d2} +0000", '%Y-%m-%d %H:%M:%S %z')
|
||||
funding_rate_history = {
|
||||
'binance': funding_rate_history_octohourly,
|
||||
'ftx': funding_rate_history_hourly,
|
||||
'gateio': funding_rate_history_octohourly,
|
||||
}[exchange][rate_start:rate_end]
|
||||
api_mock = MagicMock()
|
||||
@@ -5056,7 +5022,7 @@ def test_get_max_leverage_futures(default_conf, mocker, leverage_tiers):
|
||||
exchange.get_max_leverage("BTC/USDT", 1000000000.01)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("exchange_name", ['bittrex', 'binance', 'kraken', 'ftx', 'gateio', 'okx'])
|
||||
@pytest.mark.parametrize("exchange_name", ['bittrex', 'binance', 'kraken', 'gateio', 'okx'])
|
||||
def test__get_params(mocker, default_conf, exchange_name):
|
||||
api_mock = MagicMock()
|
||||
mocker.patch('freqtrade.exchange.Exchange.exchange_has', return_value=True)
|
||||
|
@@ -1,272 +0,0 @@
|
||||
from random import randint
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import ccxt
|
||||
import pytest
|
||||
|
||||
from freqtrade.exceptions import DependencyException, InvalidOrderException
|
||||
from freqtrade.exchange.common import API_FETCH_ORDER_RETRY_COUNT
|
||||
from tests.conftest import get_patched_exchange
|
||||
|
||||
from .test_exchange import ccxt_exceptionhandlers
|
||||
|
||||
|
||||
STOPLOSS_ORDERTYPE = 'stop'
|
||||
|
||||
|
||||
@pytest.mark.parametrize('order_price,exchangelimitratio,side', [
|
||||
(217.8, 1.05, "sell"),
|
||||
(222.2, 0.95, "buy"),
|
||||
])
|
||||
def test_stoploss_order_ftx(default_conf, mocker, order_price, exchangelimitratio, side):
|
||||
api_mock = MagicMock()
|
||||
order_id = 'test_prod_buy_{}'.format(randint(0, 10 ** 6))
|
||||
|
||||
api_mock.create_order = MagicMock(return_value={
|
||||
'id': order_id,
|
||||
'info': {
|
||||
'foo': 'bar'
|
||||
}
|
||||
})
|
||||
|
||||
default_conf['dry_run'] = False
|
||||
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
|
||||
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
|
||||
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'ftx')
|
||||
|
||||
# stoploss_on_exchange_limit_ratio is irrelevant for ftx market orders
|
||||
order = exchange.stoploss(
|
||||
pair='ETH/BTC',
|
||||
amount=1,
|
||||
stop_price=190,
|
||||
side=side,
|
||||
order_types={'stoploss_on_exchange_limit_ratio': exchangelimitratio},
|
||||
leverage=1.0
|
||||
)
|
||||
|
||||
assert api_mock.create_order.call_args_list[0][1]['symbol'] == 'ETH/BTC'
|
||||
assert api_mock.create_order.call_args_list[0][1]['type'] == STOPLOSS_ORDERTYPE
|
||||
assert api_mock.create_order.call_args_list[0][1]['side'] == side
|
||||
assert api_mock.create_order.call_args_list[0][1]['amount'] == 1
|
||||
assert 'orderPrice' not in api_mock.create_order.call_args_list[0][1]['params']
|
||||
assert 'stopPrice' in api_mock.create_order.call_args_list[0][1]['params']
|
||||
assert api_mock.create_order.call_args_list[0][1]['params']['stopPrice'] == 190
|
||||
|
||||
assert api_mock.create_order.call_count == 1
|
||||
|
||||
api_mock.create_order.reset_mock()
|
||||
|
||||
order = exchange.stoploss(
|
||||
pair='ETH/BTC',
|
||||
amount=1,
|
||||
stop_price=220,
|
||||
order_types={},
|
||||
side=side,
|
||||
leverage=1.0
|
||||
)
|
||||
|
||||
assert 'id' in order
|
||||
assert 'info' in order
|
||||
assert order['id'] == order_id
|
||||
assert api_mock.create_order.call_args_list[0][1]['symbol'] == 'ETH/BTC'
|
||||
assert api_mock.create_order.call_args_list[0][1]['type'] == STOPLOSS_ORDERTYPE
|
||||
assert api_mock.create_order.call_args_list[0][1]['side'] == side
|
||||
assert api_mock.create_order.call_args_list[0][1]['amount'] == 1
|
||||
assert 'orderPrice' not in api_mock.create_order.call_args_list[0][1]['params']
|
||||
assert api_mock.create_order.call_args_list[0][1]['params']['stopPrice'] == 220
|
||||
|
||||
api_mock.create_order.reset_mock()
|
||||
order = exchange.stoploss(
|
||||
pair='ETH/BTC',
|
||||
amount=1,
|
||||
stop_price=220,
|
||||
order_types={'stoploss': 'limit'}, side=side,
|
||||
leverage=1.0
|
||||
)
|
||||
|
||||
assert 'id' in order
|
||||
assert 'info' in order
|
||||
assert order['id'] == order_id
|
||||
assert api_mock.create_order.call_args_list[0][1]['symbol'] == 'ETH/BTC'
|
||||
assert api_mock.create_order.call_args_list[0][1]['type'] == STOPLOSS_ORDERTYPE
|
||||
assert api_mock.create_order.call_args_list[0][1]['side'] == side
|
||||
assert api_mock.create_order.call_args_list[0][1]['amount'] == 1
|
||||
assert 'orderPrice' in api_mock.create_order.call_args_list[0][1]['params']
|
||||
assert api_mock.create_order.call_args_list[0][1]['params']['orderPrice'] == order_price
|
||||
assert api_mock.create_order.call_args_list[0][1]['params']['stopPrice'] == 220
|
||||
|
||||
# test exception handling
|
||||
with pytest.raises(DependencyException):
|
||||
api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds("0 balance"))
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'ftx')
|
||||
exchange.stoploss(
|
||||
pair='ETH/BTC',
|
||||
amount=1,
|
||||
stop_price=220,
|
||||
order_types={},
|
||||
side=side,
|
||||
leverage=1.0
|
||||
)
|
||||
|
||||
with pytest.raises(InvalidOrderException):
|
||||
api_mock.create_order = MagicMock(
|
||||
side_effect=ccxt.InvalidOrder("ftx Order would trigger immediately."))
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'ftx')
|
||||
exchange.stoploss(
|
||||
pair='ETH/BTC',
|
||||
amount=1,
|
||||
stop_price=220,
|
||||
order_types={},
|
||||
side=side,
|
||||
leverage=1.0
|
||||
)
|
||||
|
||||
ccxt_exceptionhandlers(mocker, default_conf, api_mock, "ftx",
|
||||
"stoploss", "create_order", retries=1,
|
||||
pair='ETH/BTC', amount=1, stop_price=220, order_types={},
|
||||
side=side, leverage=1.0)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('side', [("sell"), ("buy")])
|
||||
def test_stoploss_order_dry_run_ftx(default_conf, mocker, side):
|
||||
api_mock = MagicMock()
|
||||
default_conf['dry_run'] = True
|
||||
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
|
||||
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
|
||||
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'ftx')
|
||||
|
||||
api_mock.create_order.reset_mock()
|
||||
|
||||
order = exchange.stoploss(
|
||||
pair='ETH/BTC',
|
||||
amount=1,
|
||||
stop_price=220,
|
||||
order_types={},
|
||||
side=side,
|
||||
leverage=1.0
|
||||
)
|
||||
|
||||
assert 'id' in order
|
||||
assert 'info' in order
|
||||
assert 'type' in order
|
||||
|
||||
assert order['type'] == STOPLOSS_ORDERTYPE
|
||||
assert order['price'] == 220
|
||||
assert order['amount'] == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize('sl1,sl2,sl3,side', [
|
||||
(1501, 1499, 1501, "sell"),
|
||||
(1499, 1501, 1499, "buy")
|
||||
])
|
||||
def test_stoploss_adjust_ftx(mocker, default_conf, sl1, sl2, sl3, side):
|
||||
exchange = get_patched_exchange(mocker, default_conf, id='ftx')
|
||||
order = {
|
||||
'type': STOPLOSS_ORDERTYPE,
|
||||
'price': 1500,
|
||||
}
|
||||
assert exchange.stoploss_adjust(sl1, order, side=side)
|
||||
assert not exchange.stoploss_adjust(sl2, order, side=side)
|
||||
# Test with invalid order case ...
|
||||
order['type'] = 'stop_loss_limit'
|
||||
assert not exchange.stoploss_adjust(sl3, order, side=side)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("init_persistence")
|
||||
def test_fetch_stoploss_order_ftx(default_conf, mocker, limit_sell_order, limit_buy_order):
|
||||
default_conf['dry_run'] = True
|
||||
order = MagicMock()
|
||||
order.myid = 123
|
||||
exchange = get_patched_exchange(mocker, default_conf, id='ftx')
|
||||
exchange._dry_run_open_orders['X'] = order
|
||||
assert exchange.fetch_stoploss_order('X', 'TKN/BTC').myid == 123
|
||||
|
||||
with pytest.raises(InvalidOrderException, match=r'Tried to get an invalid dry-run-order.*'):
|
||||
exchange.fetch_stoploss_order('Y', 'TKN/BTC')
|
||||
|
||||
default_conf['dry_run'] = False
|
||||
api_mock = MagicMock()
|
||||
api_mock.fetch_orders = MagicMock(return_value=[{'id': 'X', 'status': '456'}])
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id='ftx')
|
||||
assert exchange.fetch_stoploss_order('X', 'TKN/BTC')['status'] == '456'
|
||||
|
||||
api_mock.fetch_orders = MagicMock(return_value=[{'id': 'Y', 'status': '456'}])
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id='ftx')
|
||||
with pytest.raises(InvalidOrderException, match=r"Could not get stoploss order for id X"):
|
||||
exchange.fetch_stoploss_order('X', 'TKN/BTC')['status']
|
||||
|
||||
# stoploss Limit order
|
||||
api_mock.fetch_orders = MagicMock(return_value=[
|
||||
{'id': 'X', 'status': 'closed',
|
||||
'info': {
|
||||
'orderId': 'mocked_limit_sell',
|
||||
}}])
|
||||
api_mock.fetch_order = MagicMock(return_value=limit_sell_order.copy())
|
||||
|
||||
# No orderId field - no call to fetch_order
|
||||
resp = exchange.fetch_stoploss_order('X', 'TKN/BTC')
|
||||
assert resp
|
||||
assert api_mock.fetch_order.call_count == 1
|
||||
assert resp['id_stop'] == 'mocked_limit_sell'
|
||||
assert resp['id'] == 'X'
|
||||
assert resp['type'] == 'stop'
|
||||
assert resp['status_stop'] == 'triggered'
|
||||
|
||||
# Stoploss market order
|
||||
# Contains no new Order, but "average" instead
|
||||
order = {'id': 'X', 'status': 'closed', 'info': {'orderId': None}, 'average': 0.254}
|
||||
api_mock.fetch_orders = MagicMock(return_value=[order])
|
||||
api_mock.fetch_order.reset_mock()
|
||||
api_mock.privateGetConditionalOrdersConditionalOrderIdTriggers = MagicMock(
|
||||
return_value={'result': [
|
||||
{'orderId': 'mocked_market_sell', 'type': 'market', 'side': 'sell', 'price': 0.254}
|
||||
]})
|
||||
resp = exchange.fetch_stoploss_order('X', 'TKN/BTC')
|
||||
assert resp
|
||||
# fetch_order not called (no regular order ID)
|
||||
assert api_mock.fetch_order.call_count == 1
|
||||
api_mock.privateGetConditionalOrdersConditionalOrderIdTriggers.call_count == 1
|
||||
expected_resp = limit_sell_order.copy()
|
||||
expected_resp.update({
|
||||
'id_stop': 'X',
|
||||
'id': 'X',
|
||||
'type': 'stop',
|
||||
'status_stop': 'triggered',
|
||||
})
|
||||
assert expected_resp == resp
|
||||
|
||||
with pytest.raises(InvalidOrderException):
|
||||
api_mock.fetch_orders = MagicMock(side_effect=ccxt.InvalidOrder("Order not found"))
|
||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id='ftx')
|
||||
exchange.fetch_stoploss_order(order_id='_', pair='TKN/BTC')
|
||||
assert api_mock.fetch_orders.call_count == 1
|
||||
|
||||
ccxt_exceptionhandlers(mocker, default_conf, api_mock, 'ftx',
|
||||
'fetch_stoploss_order', 'fetch_orders',
|
||||
retries=API_FETCH_ORDER_RETRY_COUNT + 1,
|
||||
order_id='_', pair='TKN/BTC')
|
||||
|
||||
|
||||
def test_get_order_id(mocker, default_conf):
|
||||
exchange = get_patched_exchange(mocker, default_conf, id='ftx')
|
||||
order = {
|
||||
'type': STOPLOSS_ORDERTYPE,
|
||||
'price': 1500,
|
||||
'id': '1111',
|
||||
'id_stop': '1234',
|
||||
'info': {
|
||||
}
|
||||
}
|
||||
assert exchange.get_order_id_conditional(order) == '1234'
|
||||
|
||||
order = {
|
||||
'type': 'limit',
|
||||
'price': 1500,
|
||||
'id': '1111',
|
||||
'id_stop': '1234',
|
||||
'info': {
|
||||
}
|
||||
}
|
||||
assert exchange.get_order_id_conditional(order) == '1111'
|
@@ -27,16 +27,16 @@ def is_mac() -> bool:
|
||||
return "Darwin" in machine
|
||||
|
||||
|
||||
@pytest.mark.parametrize('model, pca, dbscan', [
|
||||
('LightGBMRegressor', True, False),
|
||||
('XGBoostRegressor', False, True),
|
||||
('XGBoostRFRegressor', False, False),
|
||||
('CatboostRegressor', False, False),
|
||||
('ReinforcementLearner', False, True),
|
||||
('ReinforcementLearner_multiproc', False, False),
|
||||
('ReinforcementLearner_test_4ac', False, False)
|
||||
@pytest.mark.parametrize('model, pca, dbscan, float32', [
|
||||
('LightGBMRegressor', True, False, True),
|
||||
('XGBoostRegressor', False, True, False),
|
||||
('XGBoostRFRegressor', False, False, False),
|
||||
('CatboostRegressor', False, False, False),
|
||||
('ReinforcementLearner', False, True, False),
|
||||
('ReinforcementLearner_multiproc', False, False, False),
|
||||
('ReinforcementLearner_test_4ac', False, False, False)
|
||||
])
|
||||
def test_extract_data_and_train_model_Standard(mocker, freqai_conf, model, pca, dbscan):
|
||||
def test_extract_data_and_train_model_Standard(mocker, freqai_conf, model, pca, dbscan, float32):
|
||||
if is_arm() and model == 'CatboostRegressor':
|
||||
pytest.skip("CatBoost is not supported on ARM")
|
||||
|
||||
@@ -49,6 +49,17 @@ def test_extract_data_and_train_model_Standard(mocker, freqai_conf, model, pca,
|
||||
freqai_conf.update({"strategy": "freqai_test_strat"})
|
||||
freqai_conf['freqai']['feature_parameters'].update({"principal_component_analysis": pca})
|
||||
freqai_conf['freqai']['feature_parameters'].update({"use_DBSCAN_to_remove_outliers": dbscan})
|
||||
freqai_conf.update({"reduce_df_footprint": float32})
|
||||
|
||||
if 'ReinforcementLearner' in model:
|
||||
model_save_ext = 'zip'
|
||||
freqai_conf = make_rl_config(freqai_conf)
|
||||
# test the RL guardrails
|
||||
freqai_conf['freqai']['feature_parameters'].update({"use_SVM_to_remove_outliers": True})
|
||||
freqai_conf['freqai']['data_split_parameters'].update({'shuffle': True})
|
||||
|
||||
if 'test_4ac' in model:
|
||||
freqai_conf["freqaimodel_path"] = str(Path(__file__).parents[1] / "freqai" / "test_models")
|
||||
|
||||
if 'ReinforcementLearner' in model:
|
||||
model_save_ext = 'zip'
|
||||
|
@@ -19,11 +19,6 @@ twentyfive_hours = FtPrecise(25.0)
|
||||
('kraken', 0.00025, ten_mins, 0.03),
|
||||
('kraken', 0.00025, five_hours, 0.045),
|
||||
('kraken', 0.00025, twentyfive_hours, 0.12),
|
||||
# FTX
|
||||
('ftx', 0.0005, ten_mins, 0.00125),
|
||||
('ftx', 0.00025, ten_mins, 0.000625),
|
||||
('ftx', 0.00025, five_hours, 0.003125),
|
||||
('ftx', 0.00025, twentyfive_hours, 0.015625),
|
||||
])
|
||||
def test_interest(exchange, interest_rate, hours, expected):
|
||||
borrowed = FtPrecise(60.0)
|
||||
|
@@ -612,9 +612,9 @@ def test_VolumePairList_whitelist_gen(mocker, whitelist_conf, shitcoinmarkets, t
|
||||
"lookback_timeframe": "1h", "lookback_period": 2, "refresh_period": 3600}],
|
||||
"BTC", "binance", ['ETH/BTC', 'LTC/BTC', 'NEO/BTC', 'TKN/BTC', 'XRP/BTC']),
|
||||
# ftx data is already in Quote currency, therefore won't require conversion
|
||||
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume",
|
||||
"lookback_timeframe": "1d", "lookback_period": 1, "refresh_period": 86400}],
|
||||
"BTC", "ftx", ['HOT/BTC', 'LTC/BTC', 'ETH/BTC', 'TKN/BTC', 'XRP/BTC']),
|
||||
# ([{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume",
|
||||
# "lookback_timeframe": "1d", "lookback_period": 1, "refresh_period": 86400}],
|
||||
# "BTC", "ftx", ['HOT/BTC', 'LTC/BTC', 'ETH/BTC', 'TKN/BTC', 'XRP/BTC']),
|
||||
])
|
||||
def test_VolumePairList_range(mocker, whitelist_conf, shitcoinmarkets, tickers, ohlcv_history,
|
||||
pairlists, base_currency, exchange, volumefilter_result) -> None:
|
||||
@@ -636,8 +636,6 @@ def test_VolumePairList_range(mocker, whitelist_conf, shitcoinmarkets, tickers,
|
||||
ohlcv_history_high_volume['high'] = ohlcv_history_high_volume.loc[:, 'high'] * 0.01
|
||||
ohlcv_history_high_volume['close'] = ohlcv_history_high_volume.loc[:, 'close'] * 0.01
|
||||
|
||||
mocker.patch('freqtrade.exchange.ftx.Ftx.market_is_tradable', return_value=True)
|
||||
|
||||
ohlcv_data = {
|
||||
('ETH/BTC', '1d', CandleType.SPOT): ohlcv_history,
|
||||
('TKN/BTC', '1d', CandleType.SPOT): ohlcv_history,
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# pragma pylint: disable=missing-docstring, C0103
|
||||
# pragma pylint: disable=invalid-sequence-index, invalid-name, too-many-arguments
|
||||
|
||||
from copy import deepcopy
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from unittest.mock import ANY, MagicMock, PropertyMock
|
||||
|
||||
@@ -28,27 +29,7 @@ def prec_satoshi(a, b) -> float:
|
||||
|
||||
# Unit tests
|
||||
def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker,
|
||||
get_fee=fee,
|
||||
)
|
||||
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||
patch_get_signal(freqtradebot)
|
||||
rpc = RPC(freqtradebot)
|
||||
|
||||
freqtradebot.state = State.RUNNING
|
||||
with pytest.raises(RPCException, match=r'.*no active trade*'):
|
||||
rpc._rpc_trade_status()
|
||||
|
||||
freqtradebot.enter_positions()
|
||||
trades = Trade.get_open_trades()
|
||||
freqtradebot.exit_positions(trades)
|
||||
|
||||
results = rpc._rpc_trade_status()
|
||||
assert results[0] == {
|
||||
gen_response = {
|
||||
'trade_id': 1,
|
||||
'pair': 'ETH/BTC',
|
||||
'base_currency': 'ETH',
|
||||
@@ -127,91 +108,103 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
|
||||
'remaining': ANY, 'status': ANY, 'ft_is_entry': True,
|
||||
}],
|
||||
}
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker,
|
||||
get_fee=fee,
|
||||
_is_dry_limit_order_filled=MagicMock(side_effect=[False, True]),
|
||||
)
|
||||
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||
patch_get_signal(freqtradebot)
|
||||
rpc = RPC(freqtradebot)
|
||||
|
||||
freqtradebot.state = State.RUNNING
|
||||
with pytest.raises(RPCException, match=r'.*no active trade*'):
|
||||
rpc._rpc_trade_status()
|
||||
|
||||
freqtradebot.enter_positions()
|
||||
|
||||
# Open order...
|
||||
results = rpc._rpc_trade_status()
|
||||
response_unfilled = deepcopy(gen_response)
|
||||
# Different from "filled" response:
|
||||
response_unfilled.update({
|
||||
'amount': 91.07468124,
|
||||
'profit_ratio': 0.0,
|
||||
'profit_pct': 0.0,
|
||||
'profit_abs': 0.0,
|
||||
'current_profit': 0.0,
|
||||
'current_profit_pct': 0.0,
|
||||
'current_profit_abs': 0.0,
|
||||
'stop_loss_abs': 0.0,
|
||||
'stop_loss_pct': None,
|
||||
'stop_loss_ratio': None,
|
||||
'stoploss_current_dist': -1.099e-05,
|
||||
'stoploss_current_dist_ratio': -1.0,
|
||||
'stoploss_current_dist_pct': pytest.approx(-100.0),
|
||||
'stoploss_entry_dist': -0.0010025,
|
||||
'stoploss_entry_dist_ratio': -1.0,
|
||||
'initial_stop_loss_abs': 0.0,
|
||||
'initial_stop_loss_pct': None,
|
||||
'initial_stop_loss_ratio': None,
|
||||
'open_order': '(limit buy rem=91.07468123)',
|
||||
})
|
||||
response_unfilled['orders'][0].update({
|
||||
'is_open': True,
|
||||
'filled': 0.0,
|
||||
'remaining': 91.07468123
|
||||
})
|
||||
assert results[0] == response_unfilled
|
||||
|
||||
# Open order without remaining
|
||||
trade = Trade.get_open_trades()[0]
|
||||
# kucoin case (no remaining set).
|
||||
trade.orders[0].remaining = None
|
||||
Trade.commit()
|
||||
|
||||
results = rpc._rpc_trade_status()
|
||||
# Reuse above object, only remaining changed.
|
||||
response_unfilled['orders'][0].update({
|
||||
'remaining': None
|
||||
})
|
||||
assert results[0] == response_unfilled
|
||||
|
||||
trade = Trade.get_open_trades()[0]
|
||||
trade.orders[0].remaining = trade.amount
|
||||
Trade.commit()
|
||||
|
||||
# Fill open order ...
|
||||
freqtradebot.manage_open_orders()
|
||||
trades = Trade.get_open_trades()
|
||||
freqtradebot.exit_positions(trades)
|
||||
|
||||
results = rpc._rpc_trade_status()
|
||||
|
||||
response = deepcopy(gen_response)
|
||||
assert results[0] == response
|
||||
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_rate',
|
||||
MagicMock(side_effect=ExchangeError("Pair 'ETH/BTC' not available")))
|
||||
results = rpc._rpc_trade_status()
|
||||
assert isnan(results[0]['current_profit'])
|
||||
assert isnan(results[0]['current_rate'])
|
||||
assert results[0] == {
|
||||
'trade_id': 1,
|
||||
'pair': 'ETH/BTC',
|
||||
'base_currency': 'ETH',
|
||||
'quote_currency': 'BTC',
|
||||
'open_date': ANY,
|
||||
'open_timestamp': ANY,
|
||||
'is_open': ANY,
|
||||
'fee_open': ANY,
|
||||
'fee_open_cost': ANY,
|
||||
'fee_open_currency': ANY,
|
||||
'fee_close': fee.return_value,
|
||||
'fee_close_cost': ANY,
|
||||
'fee_close_currency': ANY,
|
||||
'open_rate_requested': ANY,
|
||||
'open_trade_value': ANY,
|
||||
'close_rate_requested': ANY,
|
||||
'sell_reason': ANY,
|
||||
'exit_reason': ANY,
|
||||
'exit_order_status': ANY,
|
||||
'min_rate': ANY,
|
||||
'max_rate': ANY,
|
||||
'strategy': ANY,
|
||||
'buy_tag': ANY,
|
||||
'enter_tag': ANY,
|
||||
'timeframe': ANY,
|
||||
'open_order_id': ANY,
|
||||
'close_date': None,
|
||||
'close_timestamp': None,
|
||||
'open_rate': 1.098e-05,
|
||||
'close_rate': None,
|
||||
'current_rate': ANY,
|
||||
'amount': 91.07468123,
|
||||
'amount_requested': 91.07468124,
|
||||
'trade_duration': ANY,
|
||||
'trade_duration_s': ANY,
|
||||
'stake_amount': 0.001,
|
||||
'close_profit': None,
|
||||
'close_profit_pct': None,
|
||||
'close_profit_abs': None,
|
||||
'current_profit': ANY,
|
||||
'current_profit_pct': ANY,
|
||||
'current_profit_abs': ANY,
|
||||
'profit_ratio': ANY,
|
||||
'profit_pct': ANY,
|
||||
'profit_abs': ANY,
|
||||
'profit_fiat': ANY,
|
||||
'stop_loss_abs': 9.89e-06,
|
||||
'stop_loss_pct': -10.0,
|
||||
'stop_loss_ratio': -0.1,
|
||||
'stoploss_order_id': None,
|
||||
'stoploss_last_update': ANY,
|
||||
'stoploss_last_update_timestamp': ANY,
|
||||
'initial_stop_loss_abs': 9.89e-06,
|
||||
'initial_stop_loss_pct': -10.0,
|
||||
'initial_stop_loss_ratio': -0.1,
|
||||
response_norate = deepcopy(gen_response)
|
||||
# Update elements that are NaN when no rate is available.
|
||||
response_norate.update({
|
||||
'stoploss_current_dist': ANY,
|
||||
'stoploss_current_dist_ratio': ANY,
|
||||
'stoploss_current_dist_pct': ANY,
|
||||
'stoploss_entry_dist': -0.00010402,
|
||||
'stoploss_entry_dist_ratio': -0.10376381,
|
||||
'open_order': None,
|
||||
'exchange': 'binance',
|
||||
'realized_profit': 0.0,
|
||||
'leverage': 1.0,
|
||||
'interest_rate': 0.0,
|
||||
'liquidation_price': None,
|
||||
'is_short': False,
|
||||
'funding_fees': 0.0,
|
||||
'trading_mode': TradingMode.SPOT,
|
||||
'orders': [{
|
||||
'amount': 91.07468123, 'average': 1.098e-05, 'safe_price': 1.098e-05,
|
||||
'cost': 0.0009999999999054, 'filled': 91.07468123, 'ft_order_side': 'buy',
|
||||
'order_date': ANY, 'order_timestamp': ANY, 'order_filled_date': ANY,
|
||||
'order_filled_timestamp': ANY, 'order_type': 'limit', 'price': 1.098e-05,
|
||||
'is_open': False, 'pair': 'ETH/BTC', 'order_id': ANY,
|
||||
'remaining': ANY, 'status': ANY, 'ft_is_entry': True,
|
||||
}],
|
||||
}
|
||||
'profit_ratio': ANY,
|
||||
'profit_pct': ANY,
|
||||
'profit_abs': ANY,
|
||||
'current_profit_abs': ANY,
|
||||
'current_profit': ANY,
|
||||
'current_profit_pct': ANY,
|
||||
'current_rate': ANY,
|
||||
})
|
||||
assert results[0] == response_norate
|
||||
|
||||
|
||||
def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
|
||||
|
@@ -67,7 +67,7 @@ def botclient(default_conf, mocker):
|
||||
|
||||
def client_post(client, url, data={}):
|
||||
return client.post(url,
|
||||
data=data,
|
||||
content=data,
|
||||
headers={'Authorization': _basic_auth_str(_TEST_USER, _TEST_PASS),
|
||||
'Origin': 'http://example.com',
|
||||
'content-type': 'application/json'
|
||||
|
@@ -3036,7 +3036,7 @@ def test_handle_cancel_enter(mocker, caplog, default_conf_usdt, limit_order, is_
|
||||
|
||||
|
||||
@pytest.mark.parametrize("is_short", [False, True])
|
||||
@pytest.mark.parametrize("limit_buy_order_canceled_empty", ['binance', 'ftx', 'kraken', 'bittrex'],
|
||||
@pytest.mark.parametrize("limit_buy_order_canceled_empty", ['binance', 'kraken', 'bittrex'],
|
||||
indirect=['limit_buy_order_canceled_empty'])
|
||||
def test_handle_cancel_enter_exchanges(mocker, caplog, default_conf_usdt, is_short, fee,
|
||||
limit_buy_order_canceled_empty) -> None:
|
||||
|
@@ -1,4 +1,6 @@
|
||||
# pragma pylint: disable=missing-docstring, C0103
|
||||
from datetime import datetime, timezone
|
||||
|
||||
import arrow
|
||||
import pytest
|
||||
|
||||
@@ -8,16 +10,28 @@ from freqtrade.exceptions import OperationalException
|
||||
|
||||
def test_parse_timerange_incorrect():
|
||||
|
||||
assert TimeRange('date', None, 1274486400, 0) == TimeRange.parse_timerange('20100522-')
|
||||
assert TimeRange(None, 'date', 0, 1274486400) == TimeRange.parse_timerange('-20100522')
|
||||
timerange = TimeRange.parse_timerange('20100522-')
|
||||
assert TimeRange('date', None, 1274486400, 0) == timerange
|
||||
assert timerange.timerange_str == '20100522-'
|
||||
timerange = TimeRange.parse_timerange('-20100522')
|
||||
assert TimeRange(None, 'date', 0, 1274486400) == timerange
|
||||
assert timerange.timerange_str == '-20100522'
|
||||
timerange = TimeRange.parse_timerange('20100522-20150730')
|
||||
assert timerange == TimeRange('date', 'date', 1274486400, 1438214400)
|
||||
assert timerange.timerange_str == '20100522-20150730'
|
||||
assert timerange.start_fmt == '2010-05-22 00:00:00'
|
||||
assert timerange.stop_fmt == '2015-07-30 00:00:00'
|
||||
|
||||
# Added test for unix timestamp - BTC genesis date
|
||||
assert TimeRange('date', None, 1231006505, 0) == TimeRange.parse_timerange('1231006505-')
|
||||
assert TimeRange(None, 'date', 0, 1233360000) == TimeRange.parse_timerange('-1233360000')
|
||||
timerange = TimeRange.parse_timerange('1231006505-1233360000')
|
||||
assert TimeRange('date', 'date', 1231006505, 1233360000) == timerange
|
||||
assert isinstance(timerange.startdt, datetime)
|
||||
assert isinstance(timerange.stopdt, datetime)
|
||||
assert timerange.startdt == datetime.fromtimestamp(1231006505, tz=timezone.utc)
|
||||
assert timerange.stopdt == datetime.fromtimestamp(1233360000, tz=timezone.utc)
|
||||
assert timerange.timerange_str == '20090103-20090131'
|
||||
|
||||
timerange = TimeRange.parse_timerange('1231006505000-1233360000000')
|
||||
assert TimeRange('date', 'date', 1231006505, 1233360000) == timerange
|
||||
@@ -45,6 +59,7 @@ def test_subtract_start():
|
||||
x = TimeRange(None, 'date', 0, 1438214400)
|
||||
x.subtract_start(300)
|
||||
assert not x.startts
|
||||
assert not x.startdt
|
||||
|
||||
x = TimeRange('date', None, 1274486400, 0)
|
||||
x.subtract_start(300)
|
||||
|
Reference in New Issue
Block a user