Merge branch 'develop' into arrow_deprecation_timestamp
This commit is contained in:
@@ -1150,7 +1150,7 @@ def test_start_list_data(testdatadir, capsys):
|
||||
|
||||
@pytest.mark.usefixtures("init_persistence")
|
||||
def test_show_trades(mocker, fee, capsys, caplog):
|
||||
mocker.patch("freqtrade.persistence.init")
|
||||
mocker.patch("freqtrade.persistence.init_db")
|
||||
create_mock_trades(fee)
|
||||
args = [
|
||||
"show-trades",
|
||||
|
@@ -13,13 +13,13 @@ import numpy as np
|
||||
import pytest
|
||||
from telegram import Chat, Message, Update
|
||||
|
||||
from freqtrade import constants, persistence
|
||||
from freqtrade import constants
|
||||
from freqtrade.commands import Arguments
|
||||
from freqtrade.data.converter import ohlcv_to_dataframe
|
||||
from freqtrade.edge import Edge, PairInfo
|
||||
from freqtrade.exchange import Exchange
|
||||
from freqtrade.freqtradebot import FreqtradeBot
|
||||
from freqtrade.persistence import Trade
|
||||
from freqtrade.persistence import Trade, init_db
|
||||
from freqtrade.resolvers import ExchangeResolver
|
||||
from freqtrade.worker import Worker
|
||||
from tests.conftest_trades import (mock_trade_1, mock_trade_2, mock_trade_3, mock_trade_4,
|
||||
@@ -131,7 +131,7 @@ def patch_freqtradebot(mocker, config) -> None:
|
||||
:return: None
|
||||
"""
|
||||
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
|
||||
persistence.init(config['db_url'])
|
||||
init_db(config['db_url'])
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.freqtradebot.RPCManager._init', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.RPCManager.send_msg', MagicMock())
|
||||
@@ -219,7 +219,7 @@ def patch_coingekko(mocker) -> None:
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def init_persistence(default_conf):
|
||||
persistence.init(default_conf['db_url'], default_conf['dry_run'])
|
||||
init_db(default_conf['db_url'], default_conf['dry_run'])
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
@@ -297,7 +297,7 @@ def default_conf(testdatadir):
|
||||
@pytest.fixture
|
||||
def update():
|
||||
_update = Update(0)
|
||||
_update.message = Message(0, 0, datetime.utcnow(), Chat(0, 0))
|
||||
_update.message = Message(0, datetime.utcnow(), Chat(0, 0))
|
||||
return _update
|
||||
|
||||
|
||||
|
@@ -114,7 +114,7 @@ def test_load_trades_from_db(default_conf, fee, mocker):
|
||||
|
||||
create_mock_trades(fee)
|
||||
# remove init so it does not init again
|
||||
init_mock = mocker.patch('freqtrade.persistence.init', MagicMock())
|
||||
init_mock = mocker.patch('freqtrade.data.btanalysis.init_db', MagicMock())
|
||||
|
||||
trades = load_trades_from_db(db_url=default_conf['db_url'])
|
||||
assert init_mock.call_count == 1
|
||||
|
@@ -132,7 +132,7 @@ def test_orderbook(mocker, default_conf, order_book_l2):
|
||||
res = dp.orderbook('ETH/BTC', 5)
|
||||
assert order_book_l2.call_count == 1
|
||||
assert order_book_l2.call_args_list[0][0][0] == 'ETH/BTC'
|
||||
assert order_book_l2.call_args_list[0][0][1] == 5
|
||||
assert order_book_l2.call_args_list[0][0][1] >= 5
|
||||
|
||||
assert type(res) is dict
|
||||
assert 'bids' in res
|
||||
|
@@ -11,7 +11,7 @@ from pandas import DataFrame
|
||||
|
||||
from freqtrade.exceptions import (DDosProtection, DependencyException, InvalidOrderException,
|
||||
OperationalException, TemporaryError)
|
||||
from freqtrade.exchange import Binance, Exchange, Kraken
|
||||
from freqtrade.exchange import Binance, Bittrex, Exchange, Kraken
|
||||
from freqtrade.exchange.common import (API_FETCH_ORDER_RETRY_COUNT, API_RETRY_COUNT,
|
||||
calculate_backoff)
|
||||
from freqtrade.exchange.exchange import (market_is_active, timeframe_to_minutes, timeframe_to_msecs,
|
||||
@@ -148,11 +148,19 @@ def test_exchange_resolver(default_conf, mocker, caplog):
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_pairs')
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes')
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_stakecurrency')
|
||||
exchange = ExchangeResolver.load_exchange('Bittrex', default_conf)
|
||||
|
||||
exchange = ExchangeResolver.load_exchange('huobi', default_conf)
|
||||
assert isinstance(exchange, Exchange)
|
||||
assert log_has_re(r"No .* specific subclass found. Using the generic class instead.", caplog)
|
||||
caplog.clear()
|
||||
|
||||
exchange = ExchangeResolver.load_exchange('Bittrex', default_conf)
|
||||
assert isinstance(exchange, Exchange)
|
||||
assert isinstance(exchange, Bittrex)
|
||||
assert not log_has_re(r"No .* specific subclass found. Using the generic class instead.",
|
||||
caplog)
|
||||
caplog.clear()
|
||||
|
||||
exchange = ExchangeResolver.load_exchange('kraken', default_conf)
|
||||
assert isinstance(exchange, Exchange)
|
||||
assert isinstance(exchange, Kraken)
|
||||
@@ -1439,6 +1447,27 @@ def test_refresh_latest_ohlcv_inv_result(default_conf, mocker, caplog):
|
||||
assert log_has("Async code raised an exception: TypeError", caplog)
|
||||
|
||||
|
||||
def test_get_next_limit_in_list():
|
||||
limit_range = [5, 10, 20, 50, 100, 500, 1000]
|
||||
assert Exchange.get_next_limit_in_list(1, limit_range) == 5
|
||||
assert Exchange.get_next_limit_in_list(5, limit_range) == 5
|
||||
assert Exchange.get_next_limit_in_list(6, limit_range) == 10
|
||||
assert Exchange.get_next_limit_in_list(9, limit_range) == 10
|
||||
assert Exchange.get_next_limit_in_list(10, limit_range) == 10
|
||||
assert Exchange.get_next_limit_in_list(11, limit_range) == 20
|
||||
assert Exchange.get_next_limit_in_list(19, limit_range) == 20
|
||||
assert Exchange.get_next_limit_in_list(21, limit_range) == 50
|
||||
assert Exchange.get_next_limit_in_list(51, limit_range) == 100
|
||||
assert Exchange.get_next_limit_in_list(1000, limit_range) == 1000
|
||||
# Going over the limit ...
|
||||
assert Exchange.get_next_limit_in_list(1001, limit_range) == 1000
|
||||
assert Exchange.get_next_limit_in_list(2000, limit_range) == 1000
|
||||
|
||||
assert Exchange.get_next_limit_in_list(21, None) == 21
|
||||
assert Exchange.get_next_limit_in_list(100, None) == 100
|
||||
assert Exchange.get_next_limit_in_list(1000, None) == 1000
|
||||
|
||||
|
||||
@pytest.mark.parametrize("exchange_name", EXCHANGES)
|
||||
def test_fetch_l2_order_book(default_conf, mocker, order_book_l2, exchange_name):
|
||||
default_conf['exchange']['name'] = exchange_name
|
||||
@@ -1451,6 +1480,19 @@ def test_fetch_l2_order_book(default_conf, mocker, order_book_l2, exchange_name)
|
||||
assert 'asks' in order_book
|
||||
assert len(order_book['bids']) == 10
|
||||
assert len(order_book['asks']) == 10
|
||||
assert api_mock.fetch_l2_order_book.call_args_list[0][0][0] == 'ETH/BTC'
|
||||
|
||||
for val in [1, 5, 10, 12, 20, 50, 100]:
|
||||
api_mock.fetch_l2_order_book.reset_mock()
|
||||
|
||||
order_book = exchange.fetch_l2_order_book(pair='ETH/BTC', limit=val)
|
||||
assert api_mock.fetch_l2_order_book.call_args_list[0][0][0] == 'ETH/BTC'
|
||||
# Not all exchanges support all limits for orderbook
|
||||
if not exchange._ft_has['l2_limit_range'] or val in exchange._ft_has['l2_limit_range']:
|
||||
assert api_mock.fetch_l2_order_book.call_args_list[0][0][1] == val
|
||||
else:
|
||||
next_limit = exchange.get_next_limit_in_list(val, exchange._ft_has['l2_limit_range'])
|
||||
assert api_mock.fetch_l2_order_book.call_args_list[0][0][1] == next_limit
|
||||
|
||||
|
||||
@pytest.mark.parametrize("exchange_name", EXCHANGES)
|
||||
|
@@ -82,7 +82,7 @@ def test_telegram_init(default_conf, mocker, caplog) -> None:
|
||||
assert log_has(message_str, caplog)
|
||||
|
||||
|
||||
def test_cleanup(default_conf, mocker) -> None:
|
||||
def test_cleanup(default_conf, mocker, ) -> None:
|
||||
updater_mock = MagicMock()
|
||||
updater_mock.stop = MagicMock()
|
||||
mocker.patch('freqtrade.rpc.telegram.Updater', updater_mock)
|
||||
@@ -92,13 +92,9 @@ def test_cleanup(default_conf, mocker) -> None:
|
||||
assert telegram._updater.stop.call_count == 1
|
||||
|
||||
|
||||
def test_authorized_only(default_conf, mocker, caplog) -> None:
|
||||
def test_authorized_only(default_conf, mocker, caplog, update) -> None:
|
||||
patch_exchange(mocker)
|
||||
|
||||
chat = Chat(0, 0)
|
||||
update = Update(randint(1, 100))
|
||||
update.message = Message(randint(1, 100), 0, datetime.utcnow(), chat)
|
||||
|
||||
default_conf['telegram']['enabled'] = False
|
||||
bot = FreqtradeBot(default_conf)
|
||||
patch_get_signal(bot, (True, False))
|
||||
@@ -114,7 +110,7 @@ def test_authorized_only_unauthorized(default_conf, mocker, caplog) -> None:
|
||||
patch_exchange(mocker)
|
||||
chat = Chat(0xdeadbeef, 0)
|
||||
update = Update(randint(1, 100))
|
||||
update.message = Message(randint(1, 100), 0, datetime.utcnow(), chat)
|
||||
update.message = Message(randint(1, 100), datetime.utcnow(), chat)
|
||||
|
||||
default_conf['telegram']['enabled'] = False
|
||||
bot = FreqtradeBot(default_conf)
|
||||
@@ -127,12 +123,9 @@ def test_authorized_only_unauthorized(default_conf, mocker, caplog) -> None:
|
||||
assert not log_has('Exception occurred within Telegram module', caplog)
|
||||
|
||||
|
||||
def test_authorized_only_exception(default_conf, mocker, caplog) -> None:
|
||||
def test_authorized_only_exception(default_conf, mocker, caplog, update) -> None:
|
||||
patch_exchange(mocker)
|
||||
|
||||
update = Update(randint(1, 100))
|
||||
update.message = Message(randint(1, 100), 0, datetime.utcnow(), Chat(0, 0))
|
||||
|
||||
default_conf['telegram']['enabled'] = False
|
||||
|
||||
bot = FreqtradeBot(default_conf)
|
||||
@@ -146,7 +139,7 @@ def test_authorized_only_exception(default_conf, mocker, caplog) -> None:
|
||||
assert log_has('Exception occurred within Telegram module', caplog)
|
||||
|
||||
|
||||
def test_telegram_status(default_conf, update, mocker, fee, ticker,) -> None:
|
||||
def test_telegram_status(default_conf, update, mocker) -> None:
|
||||
update.message.chat.id = "123"
|
||||
default_conf['telegram']['enabled'] = False
|
||||
default_conf['telegram']['chat_id'] = "123"
|
||||
|
@@ -15,8 +15,7 @@ from freqtrade.exceptions import (DependencyException, ExchangeError, Insufficie
|
||||
InvalidOrderException, OperationalException, PricingError,
|
||||
TemporaryError)
|
||||
from freqtrade.freqtradebot import FreqtradeBot
|
||||
from freqtrade.persistence import Trade
|
||||
from freqtrade.persistence.models import Order
|
||||
from freqtrade.persistence import Order, Trade
|
||||
from freqtrade.rpc import RPCMessageType
|
||||
from freqtrade.state import RunMode, State
|
||||
from freqtrade.strategy.interface import SellCheckTuple, SellType
|
||||
@@ -66,7 +65,7 @@ def test_process_stopped(mocker, default_conf) -> None:
|
||||
|
||||
|
||||
def test_bot_cleanup(mocker, default_conf, caplog) -> None:
|
||||
mock_cleanup = mocker.patch('freqtrade.persistence.cleanup')
|
||||
mock_cleanup = mocker.patch('freqtrade.freqtradebot.cleanup_db')
|
||||
coo_mock = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.cancel_all_open_orders')
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
||||
freqtrade.cleanup()
|
||||
|
@@ -65,7 +65,7 @@ def test_main_fatal_exception(mocker, default_conf, caplog) -> None:
|
||||
mocker.patch('freqtrade.worker.Worker._worker', MagicMock(side_effect=Exception))
|
||||
patched_configuration_load_config_file(mocker, default_conf)
|
||||
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())
|
||||
|
||||
args = ['trade', '-c', 'config.json.example']
|
||||
|
||||
@@ -83,7 +83,7 @@ def test_main_keyboard_interrupt(mocker, default_conf, caplog) -> None:
|
||||
patched_configuration_load_config_file(mocker, default_conf)
|
||||
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
|
||||
mocker.patch('freqtrade.wallets.Wallets.update', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())
|
||||
|
||||
args = ['trade', '-c', 'config.json.example']
|
||||
|
||||
@@ -104,7 +104,7 @@ def test_main_operational_exception(mocker, default_conf, caplog) -> None:
|
||||
patched_configuration_load_config_file(mocker, default_conf)
|
||||
mocker.patch('freqtrade.wallets.Wallets.update', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())
|
||||
|
||||
args = ['trade', '-c', 'config.json.example']
|
||||
|
||||
@@ -155,7 +155,7 @@ def test_main_reload_config(mocker, default_conf, caplog) -> None:
|
||||
reconfigure_mock = mocker.patch('freqtrade.worker.Worker._reconfigure', MagicMock())
|
||||
|
||||
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())
|
||||
|
||||
args = Arguments(['trade', '-c', 'config.json.example']).get_parsed_arg()
|
||||
worker = Worker(args=args, config=default_conf)
|
||||
@@ -178,7 +178,7 @@ def test_reconfigure(mocker, default_conf) -> None:
|
||||
mocker.patch('freqtrade.wallets.Wallets.update', MagicMock())
|
||||
patched_configuration_load_config_file(mocker, default_conf)
|
||||
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())
|
||||
|
||||
args = Arguments(['trade', '-c', 'config.json.example']).get_parsed_arg()
|
||||
worker = Worker(args=args, config=default_conf)
|
||||
|
@@ -8,13 +8,13 @@ from sqlalchemy import create_engine
|
||||
|
||||
from freqtrade import constants
|
||||
from freqtrade.exceptions import DependencyException, OperationalException
|
||||
from freqtrade.persistence import Order, Trade, clean_dry_run_db, init
|
||||
from freqtrade.persistence import Order, Trade, clean_dry_run_db, init_db
|
||||
from tests.conftest import create_mock_trades, log_has, log_has_re
|
||||
|
||||
|
||||
def test_init_create_session(default_conf):
|
||||
# Check if init create a session
|
||||
init(default_conf['db_url'], default_conf['dry_run'])
|
||||
init_db(default_conf['db_url'], default_conf['dry_run'])
|
||||
assert hasattr(Trade, 'session')
|
||||
assert 'scoped_session' in type(Trade.session).__name__
|
||||
|
||||
@@ -24,7 +24,7 @@ def test_init_custom_db_url(default_conf, mocker):
|
||||
default_conf.update({'db_url': 'sqlite:///tmp/freqtrade2_test.sqlite'})
|
||||
create_engine_mock = mocker.patch('freqtrade.persistence.models.create_engine', MagicMock())
|
||||
|
||||
init(default_conf['db_url'], default_conf['dry_run'])
|
||||
init_db(default_conf['db_url'], default_conf['dry_run'])
|
||||
assert create_engine_mock.call_count == 1
|
||||
assert create_engine_mock.mock_calls[0][1][0] == 'sqlite:///tmp/freqtrade2_test.sqlite'
|
||||
|
||||
@@ -33,7 +33,7 @@ def test_init_invalid_db_url(default_conf):
|
||||
# Update path to a value other than default, but still in-memory
|
||||
default_conf.update({'db_url': 'unknown:///some.url'})
|
||||
with pytest.raises(OperationalException, match=r'.*no valid database URL*'):
|
||||
init(default_conf['db_url'], default_conf['dry_run'])
|
||||
init_db(default_conf['db_url'], default_conf['dry_run'])
|
||||
|
||||
|
||||
def test_init_prod_db(default_conf, mocker):
|
||||
@@ -42,7 +42,7 @@ def test_init_prod_db(default_conf, mocker):
|
||||
|
||||
create_engine_mock = mocker.patch('freqtrade.persistence.models.create_engine', MagicMock())
|
||||
|
||||
init(default_conf['db_url'], default_conf['dry_run'])
|
||||
init_db(default_conf['db_url'], default_conf['dry_run'])
|
||||
assert create_engine_mock.call_count == 1
|
||||
assert create_engine_mock.mock_calls[0][1][0] == 'sqlite:///tradesv3.sqlite'
|
||||
|
||||
@@ -53,7 +53,7 @@ def test_init_dryrun_db(default_conf, mocker):
|
||||
|
||||
create_engine_mock = mocker.patch('freqtrade.persistence.models.create_engine', MagicMock())
|
||||
|
||||
init(default_conf['db_url'], default_conf['dry_run'])
|
||||
init_db(default_conf['db_url'], default_conf['dry_run'])
|
||||
assert create_engine_mock.call_count == 1
|
||||
assert create_engine_mock.mock_calls[0][1][0] == 'sqlite:///tradesv3.dryrun.sqlite'
|
||||
|
||||
@@ -482,7 +482,7 @@ def test_migrate_old(mocker, default_conf, fee):
|
||||
engine.execute(insert_table_old)
|
||||
engine.execute(insert_table_old2)
|
||||
# Run init to test migration
|
||||
init(default_conf['db_url'], default_conf['dry_run'])
|
||||
init_db(default_conf['db_url'], default_conf['dry_run'])
|
||||
|
||||
assert len(Trade.query.filter(Trade.id == 1).all()) == 1
|
||||
trade = Trade.query.filter(Trade.id == 1).first()
|
||||
@@ -581,7 +581,7 @@ def test_migrate_new(mocker, default_conf, fee, caplog):
|
||||
|
||||
engine.execute("create table trades_bak1 as select * from trades")
|
||||
# Run init to test migration
|
||||
init(default_conf['db_url'], default_conf['dry_run'])
|
||||
init_db(default_conf['db_url'], default_conf['dry_run'])
|
||||
|
||||
assert len(Trade.query.filter(Trade.id == 1).all()) == 1
|
||||
trade = Trade.query.filter(Trade.id == 1).first()
|
||||
@@ -661,7 +661,7 @@ def test_migrate_mid_state(mocker, default_conf, fee, caplog):
|
||||
engine.execute(insert_table_old)
|
||||
|
||||
# Run init to test migration
|
||||
init(default_conf['db_url'], default_conf['dry_run'])
|
||||
init_db(default_conf['db_url'], default_conf['dry_run'])
|
||||
|
||||
assert len(Trade.query.filter(Trade.id == 1).all()) == 1
|
||||
trade = Trade.query.filter(Trade.id == 1).first()
|
||||
@@ -904,7 +904,7 @@ def test_to_json(default_conf, fee):
|
||||
|
||||
|
||||
def test_stoploss_reinitialization(default_conf, fee):
|
||||
init(default_conf['db_url'])
|
||||
init_db(default_conf['db_url'])
|
||||
trade = Trade(
|
||||
pair='ETH/BTC',
|
||||
stake_amount=0.001,
|
||||
|
Reference in New Issue
Block a user