@@ -835,6 +835,23 @@ def test_download_data_trades(mocker, caplog):
|
||||
start_download_data(pargs)
|
||||
|
||||
|
||||
def test_download_data_data_invalid(mocker):
|
||||
patch_exchange(mocker, id="kraken")
|
||||
mocker.patch(
|
||||
'freqtrade.exchange.Exchange.markets', PropertyMock(return_value={})
|
||||
)
|
||||
args = [
|
||||
"download-data",
|
||||
"--exchange", "kraken",
|
||||
"--pairs", "ETH/BTC", "XRP/BTC",
|
||||
"--days", "20",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
with pytest.raises(OperationalException, match=r"Historic klines not available for .*"):
|
||||
start_download_data(pargs)
|
||||
|
||||
|
||||
def test_start_convert_trades(mocker, caplog):
|
||||
convert_mock = mocker.patch('freqtrade.commands.data_commands.convert_trades_to_ohlcv',
|
||||
MagicMock(return_value=[]))
|
||||
|
@@ -13,6 +13,7 @@ import pytest
|
||||
|
||||
from freqtrade.enums import CandleType
|
||||
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_prev_date
|
||||
from freqtrade.exchange.exchange import timeframe_to_msecs
|
||||
from freqtrade.resolvers.exchange_resolver import ExchangeResolver
|
||||
from tests.conftest import get_default_conf_usdt
|
||||
|
||||
@@ -219,7 +220,7 @@ class TestCCXTExchange():
|
||||
assert len(l2['asks']) == next_limit
|
||||
assert len(l2['asks']) == next_limit
|
||||
|
||||
def test_fetch_ohlcv(self, exchange):
|
||||
def test_ccxt_fetch_ohlcv(self, exchange):
|
||||
exchange, exchangename = exchange
|
||||
pair = EXCHANGES[exchangename]['pair']
|
||||
timeframe = EXCHANGES[exchangename]['timeframe']
|
||||
@@ -231,11 +232,44 @@ class TestCCXTExchange():
|
||||
assert len(ohlcv[pair_tf]) == len(exchange.klines(pair_tf))
|
||||
# assert len(exchange.klines(pair_tf)) > 200
|
||||
# Assume 90% uptime ...
|
||||
assert len(exchange.klines(pair_tf)) > exchange.ohlcv_candle_limit(timeframe) * 0.90
|
||||
assert len(exchange.klines(pair_tf)) > exchange.ohlcv_candle_limit(
|
||||
timeframe, CandleType.SPOT) * 0.90
|
||||
# Check if last-timeframe is within the last 2 intervals
|
||||
now = datetime.now(timezone.utc) - timedelta(minutes=(timeframe_to_minutes(timeframe) * 2))
|
||||
assert exchange.klines(pair_tf).iloc[-1]['date'] >= timeframe_to_prev_date(timeframe, now)
|
||||
|
||||
def test_ccxt__async_get_candle_history(self, exchange):
|
||||
exchange, exchangename = exchange
|
||||
# For some weired reason, this test returns random lengths for bittrex.
|
||||
if not exchange._ft_has['ohlcv_has_history'] or exchangename == 'bittrex':
|
||||
return
|
||||
pair = EXCHANGES[exchangename]['pair']
|
||||
timeframe = EXCHANGES[exchangename]['timeframe']
|
||||
candle_type = CandleType.SPOT
|
||||
timeframe_ms = timeframe_to_msecs(timeframe)
|
||||
now = timeframe_to_prev_date(
|
||||
timeframe, datetime.now(timezone.utc))
|
||||
for offset in (360, 120, 30, 10, 5, 2):
|
||||
since = now - timedelta(days=offset)
|
||||
since_ms = int(since.timestamp() * 1000)
|
||||
|
||||
res = exchange.loop.run_until_complete(exchange._async_get_candle_history(
|
||||
pair=pair,
|
||||
timeframe=timeframe,
|
||||
since_ms=since_ms,
|
||||
candle_type=candle_type
|
||||
)
|
||||
)
|
||||
assert res
|
||||
assert res[0] == pair
|
||||
assert res[1] == timeframe
|
||||
assert res[2] == candle_type
|
||||
candles = res[3]
|
||||
candle_count = exchange.ohlcv_candle_limit(timeframe, candle_type, since_ms) * 0.9
|
||||
candle_count1 = (now.timestamp() * 1000 - since_ms) // timeframe_ms
|
||||
assert len(candles) >= min(candle_count, candle_count1)
|
||||
assert candles[0][0] == since_ms or (since_ms + timeframe_ms)
|
||||
|
||||
def test_ccxt_fetch_funding_rate_history(self, exchange_futures):
|
||||
exchange, exchangename = exchange_futures
|
||||
if not exchange:
|
||||
|
@@ -17,9 +17,9 @@ from freqtrade.exceptions import (DDosProtection, DependencyException, InvalidOr
|
||||
from freqtrade.exchange import Binance, Bittrex, Exchange, Kraken
|
||||
from freqtrade.exchange.common import (API_FETCH_ORDER_RETRY_COUNT, API_RETRY_COUNT,
|
||||
calculate_backoff, remove_credentials)
|
||||
from freqtrade.exchange.exchange import (market_is_active, timeframe_to_minutes, timeframe_to_msecs,
|
||||
timeframe_to_next_date, timeframe_to_prev_date,
|
||||
timeframe_to_seconds)
|
||||
from freqtrade.exchange.exchange import (date_minus_candles, market_is_active, timeframe_to_minutes,
|
||||
timeframe_to_msecs, timeframe_to_next_date,
|
||||
timeframe_to_prev_date, timeframe_to_seconds)
|
||||
from freqtrade.resolvers.exchange_resolver import ExchangeResolver
|
||||
from tests.conftest import get_mock_coro, get_patched_exchange, log_has, log_has_re, num_log_has_re
|
||||
|
||||
@@ -939,6 +939,7 @@ def test_validate_timeframes_emulated_ohlcvi_2(default_conf, mocker):
|
||||
|
||||
|
||||
def test_validate_timeframes_not_in_config(default_conf, mocker):
|
||||
# TODO: this test does not assert ...
|
||||
del default_conf["timeframe"]
|
||||
api_mock = MagicMock()
|
||||
id_mock = PropertyMock(return_value='test_exchange')
|
||||
@@ -954,6 +955,7 @@ def test_validate_timeframes_not_in_config(default_conf, mocker):
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_pairs')
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_stakecurrency')
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_pricing')
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_required_startup_candles')
|
||||
Exchange(default_conf)
|
||||
|
||||
|
||||
@@ -1084,6 +1086,13 @@ def test_validate_required_startup_candles(default_conf, mocker, caplog):
|
||||
with pytest.raises(OperationalException, match=r'This strategy requires 6000.*'):
|
||||
Exchange(default_conf)
|
||||
|
||||
# Emulate kraken mode
|
||||
ex._ft_has['ohlcv_has_history'] = False
|
||||
with pytest.raises(OperationalException,
|
||||
match=r'This strategy requires 2500.*, '
|
||||
r'which is more than the amount.*'):
|
||||
ex.validate_required_startup_candles(2500, '5m')
|
||||
|
||||
|
||||
def test_exchange_has(default_conf, mocker):
|
||||
exchange = get_patched_exchange(mocker, default_conf)
|
||||
@@ -1875,7 +1884,7 @@ def test_get_historic_ohlcv(default_conf, mocker, caplog, exchange_name, candle_
|
||||
exchange._async_get_candle_history = Mock(wraps=mock_candle_hist)
|
||||
# one_call calculation * 1.8 should do 2 calls
|
||||
|
||||
since = 5 * 60 * exchange.ohlcv_candle_limit('5m') * 1.8
|
||||
since = 5 * 60 * exchange.ohlcv_candle_limit('5m', CandleType.SPOT) * 1.8
|
||||
ret = exchange.get_historic_ohlcv(
|
||||
pair,
|
||||
"5m",
|
||||
@@ -1941,7 +1950,7 @@ def test_get_historic_ohlcv_as_df(default_conf, mocker, exchange_name, candle_ty
|
||||
exchange._async_get_candle_history = Mock(wraps=mock_candle_hist)
|
||||
# one_call calculation * 1.8 should do 2 calls
|
||||
|
||||
since = 5 * 60 * exchange.ohlcv_candle_limit('5m') * 1.8
|
||||
since = 5 * 60 * exchange.ohlcv_candle_limit('5m', CandleType.SPOT) * 1.8
|
||||
ret = exchange.get_historic_ohlcv_as_df(
|
||||
pair,
|
||||
"5m",
|
||||
@@ -1995,7 +2004,7 @@ async def test__async_get_historic_ohlcv(default_conf, mocker, caplog, exchange_
|
||||
)
|
||||
# Required candles
|
||||
candles = (end_ts - start_ts) / 300_000
|
||||
exp = candles // exchange.ohlcv_candle_limit('5m') + 1
|
||||
exp = candles // exchange.ohlcv_candle_limit('5m', CandleType.SPOT) + 1
|
||||
|
||||
# Depending on the exchange, this should be called between 1 and 6 times.
|
||||
assert exchange._api_async.fetch_ohlcv.call_count == exp
|
||||
@@ -3342,7 +3351,7 @@ def test_ohlcv_candle_limit(default_conf, mocker, exchange_name):
|
||||
expected = exchange._ft_has['ohlcv_candle_limit_per_timeframe'][timeframe]
|
||||
# This should only run for bittrex
|
||||
assert exchange_name == 'bittrex'
|
||||
assert exchange.ohlcv_candle_limit(timeframe) == expected
|
||||
assert exchange.ohlcv_candle_limit(timeframe, CandleType.SPOT) == expected
|
||||
|
||||
|
||||
def test_timeframe_to_minutes():
|
||||
@@ -3424,6 +3433,17 @@ def test_timeframe_to_next_date():
|
||||
assert timeframe_to_next_date("5m", date) == date + timedelta(minutes=5)
|
||||
|
||||
|
||||
def test_date_minus_candles():
|
||||
|
||||
date = datetime(2019, 8, 12, 13, 25, 0, tzinfo=timezone.utc)
|
||||
|
||||
assert date_minus_candles("5m", 3, date) == date - timedelta(minutes=15)
|
||||
assert date_minus_candles("5m", 5, date) == date - timedelta(minutes=25)
|
||||
assert date_minus_candles("1m", 6, date) == date - timedelta(minutes=6)
|
||||
assert date_minus_candles("1h", 3, date) == date - timedelta(hours=3, minutes=25)
|
||||
assert date_minus_candles("1h", 3) == timeframe_to_prev_date('1h') - timedelta(hours=3)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"market_symbol,base,quote,exchange,spot,margin,futures,trademode,add_dict,expected_result",
|
||||
[
|
||||
|
@@ -1,12 +1,42 @@
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from unittest.mock import MagicMock, PropertyMock
|
||||
|
||||
import pytest
|
||||
|
||||
from freqtrade.enums import MarginMode, TradingMode
|
||||
from freqtrade.enums.candletype import CandleType
|
||||
from freqtrade.exchange.exchange import timeframe_to_minutes
|
||||
from tests.conftest import get_patched_exchange
|
||||
from tests.exchange.test_exchange import ccxt_exceptionhandlers
|
||||
|
||||
|
||||
def test_okx_ohlcv_candle_limit(default_conf, mocker):
|
||||
exchange = get_patched_exchange(mocker, default_conf, id='okx')
|
||||
timeframes = ('1m', '5m', '1h')
|
||||
start_time = int(datetime(2021, 1, 1, tzinfo=timezone.utc).timestamp() * 1000)
|
||||
|
||||
for timeframe in timeframes:
|
||||
assert exchange.ohlcv_candle_limit(timeframe, CandleType.SPOT) == 300
|
||||
assert exchange.ohlcv_candle_limit(timeframe, CandleType.FUTURES) == 300
|
||||
assert exchange.ohlcv_candle_limit(timeframe, CandleType.MARK) == 100
|
||||
assert exchange.ohlcv_candle_limit(timeframe, CandleType.FUNDING_RATE) == 100
|
||||
|
||||
assert exchange.ohlcv_candle_limit(timeframe, CandleType.SPOT, start_time) == 100
|
||||
assert exchange.ohlcv_candle_limit(timeframe, CandleType.FUTURES, start_time) == 100
|
||||
assert exchange.ohlcv_candle_limit(timeframe, CandleType.MARK, start_time) == 100
|
||||
assert exchange.ohlcv_candle_limit(timeframe, CandleType.FUNDING_RATE, start_time) == 100
|
||||
one_call = int((datetime.now(timezone.utc) - timedelta(
|
||||
minutes=290 * timeframe_to_minutes(timeframe))).timestamp() * 1000)
|
||||
|
||||
assert exchange.ohlcv_candle_limit(timeframe, CandleType.SPOT, one_call) == 300
|
||||
assert exchange.ohlcv_candle_limit(timeframe, CandleType.FUTURES, one_call) == 300
|
||||
|
||||
one_call = int((datetime.now(timezone.utc) - timedelta(
|
||||
minutes=320 * timeframe_to_minutes(timeframe))).timestamp() * 1000)
|
||||
assert exchange.ohlcv_candle_limit(timeframe, CandleType.SPOT, one_call) == 100
|
||||
assert exchange.ohlcv_candle_limit(timeframe, CandleType.FUTURES, one_call) == 100
|
||||
|
||||
|
||||
def test_get_maintenance_ratio_and_amt_okx(
|
||||
default_conf,
|
||||
mocker,
|
||||
|
Reference in New Issue
Block a user