Merge with develop

This commit is contained in:
Anton
2018-06-08 00:29:44 +03:00
49 changed files with 788 additions and 516 deletions

View File

@@ -9,7 +9,6 @@ from unittest.mock import MagicMock
import arrow
import pytest
from jsonschema import validate
from sqlalchemy import create_engine
from telegram import Chat, Message, Update
from freqtrade.analyze import Analyze
@@ -45,7 +44,7 @@ def get_patched_freqtradebot(mocker, config) -> FreqtradeBot:
mocker.patch('freqtrade.freqtradebot.RPCManager.send_msg', MagicMock())
mocker.patch('freqtrade.freqtradebot.Analyze.get_signal', MagicMock())
return FreqtradeBot(config, create_engine('sqlite://'))
return FreqtradeBot(config)
def patch_coinmarketcap(mocker, value: Optional[Dict[str, float]] = None) -> None:
@@ -108,7 +107,8 @@ def default_conf():
"chat_id": "0"
},
"initial_state": "running",
"loglevel": logging.DEBUG
"db_url": "sqlite://",
"loglevel": logging.DEBUG,
}
validate(configuration, constants.CONF_SCHEMA)
return configuration

View File

@@ -310,9 +310,19 @@ def test_get_ticker(default_conf, mocker):
# if not fetching a new result we should get the cached ticker
ticker = get_ticker(pair='ETH/BTC')
assert api_mock.fetch_ticker.call_count == 1
assert ticker['bid'] == 0.5
assert ticker['ask'] == 1
assert 'ETH/BTC' in exchange._CACHED_TICKER
assert exchange._CACHED_TICKER['ETH/BTC']['bid'] == 0.5
assert exchange._CACHED_TICKER['ETH/BTC']['ask'] == 1
# Test caching
api_mock.fetch_ticker = MagicMock()
get_ticker(pair='ETH/BTC', refresh=False)
assert api_mock.fetch_ticker.call_count == 0
with pytest.raises(TemporaryError): # test retrier
api_mock.fetch_ticker = MagicMock(side_effect=ccxt.NetworkError)
mocker.patch('freqtrade.exchange._API', api_mock)
@@ -323,6 +333,10 @@ def test_get_ticker(default_conf, mocker):
mocker.patch('freqtrade.exchange._API', api_mock)
get_ticker(pair='ETH/BTC', refresh=True)
api_mock.fetch_ticker = MagicMock(return_value={})
mocker.patch('freqtrade.exchange._API', api_mock)
get_ticker(pair='ETH/BTC', refresh=True)
def make_fetch_ohlcv_mock(data):
def fetch_ohlcv_mock(pair, timeframe, since):

View File

@@ -14,7 +14,7 @@ from arrow import Arrow
from freqtrade import optimize, constants, DependencyException
from freqtrade.analyze import Analyze
from freqtrade.arguments import Arguments
from freqtrade.arguments import Arguments, TimeRange
from freqtrade.optimize.backtesting import Backtesting, start, setup_configuration
from freqtrade.tests.conftest import log_has
@@ -31,7 +31,7 @@ def trim_dictlist(dict_list, num):
def load_data_test(what):
timerange = ((None, 'line'), None, -100)
timerange = TimeRange(None, 'line', 0, -101)
data = optimize.load_data(None, ticker_interval='1m',
pairs=['UNITTEST/BTC'], timerange=timerange)
pair = data['UNITTEST/BTC']
@@ -111,14 +111,14 @@ def mocked_load_data(datadir, pairs=[], ticker_interval='0m', refresh_pairs=Fals
# use for mock freqtrade.exchange.get_ticker_history'
def _load_pair_as_ticks(pair, tickfreq):
ticks = optimize.load_data(None, ticker_interval=tickfreq, pairs=[pair])
ticks = trim_dictlist(ticks, -200)
ticks = trim_dictlist(ticks, -201)
return ticks[pair]
# FIX: fixturize this?
def _make_backtest_conf(mocker, conf=None, pair='UNITTEST/BTC', record=None):
data = optimize.load_data(None, ticker_interval='8m', pairs=[pair])
data = trim_dictlist(data, -200)
data = trim_dictlist(data, -201)
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
backtesting = Backtesting(conf)
return {
@@ -219,7 +219,8 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non
'--realistic-simulation',
'--refresh-pairs-cached',
'--timerange', ':100',
'--export', '/bar/foo'
'--export', '/bar/foo',
'--export-filename', 'foo_bar.json'
]
config = setup_configuration(get_args(args))
@@ -260,6 +261,11 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non
'Parameter --export detected: {} ...'.format(config['export']),
caplog.record_tuples
)
assert 'exportfilename' in config
assert log_has(
'Storing backtest results to {} ...'.format(config['exportfilename']),
caplog.record_tuples
)
def test_setup_configuration_unlimited_stake_amount(mocker, default_conf, caplog) -> None:
@@ -328,7 +334,7 @@ def test_tickerdata_to_dataframe(default_conf, mocker) -> None:
Test Backtesting.tickerdata_to_dataframe() method
"""
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
timerange = ((None, 'line'), None, -100)
timerange = TimeRange(None, 'line', 0, -100)
tick = optimize.load_tickerdata_file(None, 'UNITTEST/BTC', '1m', timerange=timerange)
tickerlist = {'UNITTEST/BTC': tick}

View File

@@ -11,6 +11,7 @@ from freqtrade.misc import file_dump_json
from freqtrade.optimize.__init__ import make_testdata_path, download_pairs, \
download_backtesting_testdata, load_tickerdata_file, trim_tickerlist, \
load_cached_data_for_updating
from freqtrade.arguments import TimeRange
from freqtrade.tests.conftest import log_has
# Change this if modifying UNITTEST/BTC testdatafile
@@ -176,7 +177,7 @@ def test_load_cached_data_for_updating(mocker) -> None:
# timeframe starts earlier than the cached data
# should fully update data
timerange = (('date', None), test_data[0][0] / 1000 - 1, None)
timerange = TimeRange('date', None, test_data[0][0] / 1000 - 1, 0)
data, start_ts = load_cached_data_for_updating(test_filename,
'1m',
timerange)
@@ -187,13 +188,13 @@ def test_load_cached_data_for_updating(mocker) -> None:
num_lines = (test_data[-1][0] - test_data[1][0]) / 1000 / 60 + 120
data, start_ts = load_cached_data_for_updating(test_filename,
'1m',
((None, 'line'), None, -num_lines))
TimeRange(None, 'line', 0, -num_lines))
assert data == []
assert start_ts < test_data[0][0] - 1
# timeframe starts in the center of the cached data
# should return the chached data w/o the last item
timerange = (('date', None), test_data[0][0] / 1000 + 1, None)
timerange = TimeRange('date', None, test_data[0][0] / 1000 + 1, 0)
data, start_ts = load_cached_data_for_updating(test_filename,
'1m',
timerange)
@@ -202,7 +203,7 @@ def test_load_cached_data_for_updating(mocker) -> None:
# same with 'line' timeframe
num_lines = (test_data[-1][0] - test_data[1][0]) / 1000 / 60 + 30
timerange = ((None, 'line'), None, -num_lines)
timerange = TimeRange(None, 'line', 0, -num_lines)
data, start_ts = load_cached_data_for_updating(test_filename,
'1m',
timerange)
@@ -211,7 +212,7 @@ def test_load_cached_data_for_updating(mocker) -> None:
# timeframe starts after the chached data
# should return the chached data w/o the last item
timerange = (('date', None), test_data[-1][0] / 1000 + 1, None)
timerange = TimeRange('date', None, test_data[-1][0] / 1000 + 1, 0)
data, start_ts = load_cached_data_for_updating(test_filename,
'1m',
timerange)
@@ -220,7 +221,7 @@ def test_load_cached_data_for_updating(mocker) -> None:
# same with 'line' timeframe
num_lines = 30
timerange = ((None, 'line'), None, -num_lines)
timerange = TimeRange(None, 'line', 0, -num_lines)
data, start_ts = load_cached_data_for_updating(test_filename,
'1m',
timerange)
@@ -230,7 +231,7 @@ def test_load_cached_data_for_updating(mocker) -> None:
# no timeframe is set
# should return the chached data w/o the last item
num_lines = 30
timerange = ((None, 'line'), None, -num_lines)
timerange = TimeRange(None, 'line', 0, -num_lines)
data, start_ts = load_cached_data_for_updating(test_filename,
'1m',
timerange)
@@ -239,7 +240,7 @@ def test_load_cached_data_for_updating(mocker) -> None:
# no datafile exist
# should return timestamp start time
timerange = (('date', None), now_ts - 10000, None)
timerange = TimeRange('date', None, now_ts - 10000, 0)
data, start_ts = load_cached_data_for_updating(test_filename + 'unexist',
'1m',
timerange)
@@ -248,7 +249,7 @@ def test_load_cached_data_for_updating(mocker) -> None:
# same with 'line' timeframe
num_lines = 30
timerange = ((None, 'line'), None, -num_lines)
timerange = TimeRange(None, 'line', 0, -num_lines)
data, start_ts = load_cached_data_for_updating(test_filename + 'unexist',
'1m',
timerange)
@@ -343,7 +344,7 @@ def test_trim_tickerlist() -> None:
# Test the pattern ^(-\d+)$
# This pattern uses the latest N elements
timerange = ((None, 'line'), None, -5)
timerange = TimeRange(None, 'line', 0, -5)
ticker = trim_tickerlist(ticker_list, timerange)
ticker_len = len(ticker)
@@ -353,7 +354,7 @@ def test_trim_tickerlist() -> None:
# Test the pattern ^(\d+)-$
# This pattern keep X element from the end
timerange = (('line', None), 5, None)
timerange = TimeRange('line', None, 5, 0)
ticker = trim_tickerlist(ticker_list, timerange)
ticker_len = len(ticker)
@@ -363,7 +364,7 @@ def test_trim_tickerlist() -> None:
# Test the pattern ^(\d+)-(\d+)$
# This pattern extract a window
timerange = (('index', 'index'), 5, 10)
timerange = TimeRange('index', 'index', 5, 10)
ticker = trim_tickerlist(ticker_list, timerange)
ticker_len = len(ticker)
@@ -374,7 +375,7 @@ def test_trim_tickerlist() -> None:
# Test the pattern ^(\d{8})-(\d{8})$
# This pattern extract a window between the dates
timerange = (('date', 'date'), ticker_list[5][0] / 1000, ticker_list[10][0] / 1000 - 1)
timerange = TimeRange('date', 'date', ticker_list[5][0] / 1000, ticker_list[10][0] / 1000 - 1)
ticker = trim_tickerlist(ticker_list, timerange)
ticker_len = len(ticker)
@@ -385,7 +386,7 @@ def test_trim_tickerlist() -> None:
# Test the pattern ^-(\d{8})$
# This pattern extracts elements from the start to the date
timerange = ((None, 'date'), None, ticker_list[10][0] / 1000 - 1)
timerange = TimeRange(None, 'date', 0, ticker_list[10][0] / 1000 - 1)
ticker = trim_tickerlist(ticker_list, timerange)
ticker_len = len(ticker)
@@ -395,7 +396,7 @@ def test_trim_tickerlist() -> None:
# Test the pattern ^(\d{8})-$
# This pattern extracts elements from the date to now
timerange = (('date', None), ticker_list[10][0] / 1000 - 1, None)
timerange = TimeRange('date', None, ticker_list[10][0] / 1000 - 1, None)
ticker = trim_tickerlist(ticker_list, timerange)
ticker_len = len(ticker)
@@ -405,7 +406,7 @@ def test_trim_tickerlist() -> None:
# Test a wrong pattern
# This pattern must return the list unchanged
timerange = ((None, None), None, 5)
timerange = TimeRange(None, None, None, 5)
ticker = trim_tickerlist(ticker_list, timerange)
ticker_len = len(ticker)

View File

@@ -7,8 +7,6 @@ Unit test file for rpc/rpc.py
from datetime import datetime
from unittest.mock import MagicMock
from sqlalchemy import create_engine
from freqtrade.freqtradebot import FreqtradeBot
from freqtrade.persistence import Trade
from freqtrade.rpc.rpc import RPC
@@ -39,7 +37,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
rpc = RPC(freqtradebot)
freqtradebot.state = State.STOPPED
@@ -88,7 +86,7 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
rpc = RPC(freqtradebot)
freqtradebot.state = State.STOPPED
@@ -123,7 +121,7 @@ def test_rpc_daily_profit(default_conf, update, ticker, fee,
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
stake_currency = default_conf['stake_currency']
fiat_display_currency = default_conf['fiat_display_currency']
@@ -180,7 +178,7 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
stake_currency = default_conf['stake_currency']
fiat_display_currency = default_conf['fiat_display_currency']
@@ -206,15 +204,30 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
trade.close_date = datetime.utcnow()
trade.is_open = False
freqtradebot.create_trade()
trade = Trade.query.first()
# Simulate fulfilled LIMIT_BUY order for trade
trade.update(limit_buy_order)
# Update the ticker with a market going up
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker_sell_up
)
trade.update(limit_sell_order)
trade.close_date = datetime.utcnow()
trade.is_open = False
(error, stats) = rpc.rpc_trade_statistics(stake_currency, fiat_display_currency)
assert not error
assert prec_satoshi(stats['profit_closed_coin'], 6.217e-05)
assert prec_satoshi(stats['profit_closed_percent'], 6.2)
assert prec_satoshi(stats['profit_closed_fiat'], 0.93255)
assert prec_satoshi(stats['profit_all_coin'], 6.217e-05)
assert prec_satoshi(stats['profit_all_percent'], 6.2)
assert prec_satoshi(stats['profit_all_fiat'], 0.93255)
assert stats['trade_count'] == 1
assert prec_satoshi(stats['profit_all_coin'], 5.632e-05)
assert prec_satoshi(stats['profit_all_percent'], 2.81)
assert prec_satoshi(stats['profit_all_fiat'], 0.8448)
assert stats['trade_count'] == 2
assert stats['first_trade_date'] == 'just now'
assert stats['latest_trade_date'] == 'just now'
assert stats['avg_duration'] == '0:00:00'
@@ -243,7 +256,7 @@ def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, fee,
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
stake_currency = default_conf['stake_currency']
fiat_display_currency = default_conf['fiat_display_currency']
@@ -314,7 +327,7 @@ def test_rpc_balance_handle(default_conf, mocker):
get_balances=MagicMock(return_value=mock_balance)
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
rpc = RPC(freqtradebot)
(error, res) = rpc.rpc_balance(default_conf['fiat_display_currency'])
@@ -344,7 +357,7 @@ def test_rpc_start(mocker, default_conf) -> None:
get_ticker=MagicMock()
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
rpc = RPC(freqtradebot)
freqtradebot.state = State.STOPPED
@@ -372,7 +385,7 @@ def test_rpc_stop(mocker, default_conf) -> None:
get_ticker=MagicMock()
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
rpc = RPC(freqtradebot)
freqtradebot.state = State.RUNNING
@@ -411,7 +424,7 @@ def test_rpc_forcesell(default_conf, ticker, fee, mocker) -> None:
get_fee=fee,
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
rpc = RPC(freqtradebot)
freqtradebot.state = State.STOPPED
@@ -521,7 +534,7 @@ def test_performance_handle(default_conf, ticker, limit_buy_order, fee,
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
rpc = RPC(freqtradebot)
# Create some test data
@@ -560,7 +573,7 @@ def test_rpc_count(mocker, default_conf, ticker, fee) -> None:
get_fee=fee,
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
rpc = RPC(freqtradebot)
(error, trades) = rpc.rpc_count()

View File

@@ -11,7 +11,6 @@ from datetime import datetime
from random import randint
from unittest.mock import MagicMock
from sqlalchemy import create_engine
from telegram import Update, Message, Chat
from telegram.error import NetworkError
@@ -156,7 +155,7 @@ def test_authorized_only(default_conf, mocker, caplog) -> None:
conf = deepcopy(default_conf)
conf['telegram']['enabled'] = False
dummy = DummyCls(FreqtradeBot(conf, create_engine('sqlite://')))
dummy = DummyCls(FreqtradeBot(conf))
dummy.dummy_handler(bot=MagicMock(), update=update)
assert dummy.state['called'] is True
assert log_has(
@@ -187,7 +186,7 @@ def test_authorized_only_unauthorized(default_conf, mocker, caplog) -> None:
conf = deepcopy(default_conf)
conf['telegram']['enabled'] = False
dummy = DummyCls(FreqtradeBot(conf, create_engine('sqlite://')))
dummy = DummyCls(FreqtradeBot(conf))
dummy.dummy_handler(bot=MagicMock(), update=update)
assert dummy.state['called'] is False
assert not log_has(
@@ -217,7 +216,7 @@ def test_authorized_only_exception(default_conf, mocker, caplog) -> None:
conf = deepcopy(default_conf)
conf['telegram']['enabled'] = False
dummy = DummyCls(FreqtradeBot(conf, create_engine('sqlite://')))
dummy = DummyCls(FreqtradeBot(conf))
dummy.dummy_exception(bot=MagicMock(), update=update)
assert dummy.state['called'] is False
assert not log_has(
@@ -263,7 +262,7 @@ def test_status(default_conf, update, mocker, fee, ticker) -> None:
)
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
freqtradebot = FreqtradeBot(conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(conf)
telegram = Telegram(freqtradebot)
# Create some test data
@@ -301,7 +300,7 @@ def test_status_handle(default_conf, update, ticker, fee, mocker) -> None:
)
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
freqtradebot.state = State.STOPPED
@@ -348,7 +347,7 @@ def test_status_table_handle(default_conf, update, ticker, fee, mocker) -> None:
conf = deepcopy(default_conf)
conf['stake_amount'] = 15.0
freqtradebot = FreqtradeBot(conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(conf)
telegram = Telegram(freqtradebot)
freqtradebot.state = State.STOPPED
@@ -402,7 +401,7 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
)
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
# Create some test data
@@ -470,7 +469,7 @@ def test_daily_wrong_input(default_conf, update, ticker, mocker) -> None:
)
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
# Try invalid data
@@ -511,7 +510,7 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
)
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
telegram._profit(bot=MagicMock(), update=update)
@@ -608,7 +607,7 @@ def test_telegram_balance_handle(default_conf, update, mocker) -> None:
send_msg=msg_mock
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
telegram._balance(bot=MagicMock(), update=update)
@@ -638,7 +637,7 @@ def test_zero_balance_handle(default_conf, update, mocker) -> None:
send_msg=msg_mock
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
telegram._balance(bot=MagicMock(), update=update)
@@ -661,7 +660,7 @@ def test_start_handle(default_conf, update, mocker) -> None:
)
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
freqtradebot.state = State.STOPPED
@@ -685,7 +684,7 @@ def test_start_handle_already_running(default_conf, update, mocker) -> None:
)
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
freqtradebot.state = State.RUNNING
@@ -710,7 +709,7 @@ def test_stop_handle(default_conf, update, mocker) -> None:
)
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
freqtradebot.state = State.RUNNING
@@ -735,7 +734,7 @@ def test_stop_handle_already_stopped(default_conf, update, mocker) -> None:
)
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
freqtradebot.state = State.STOPPED
@@ -762,7 +761,7 @@ def test_forcesell_handle(default_conf, update, ticker, fee, ticker_sell_up, moc
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
# Create some test data
@@ -802,7 +801,7 @@ def test_forcesell_down_handle(default_conf, update, ticker, fee, ticker_sell_do
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
# Create some test data
@@ -847,7 +846,7 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None
get_fee=fee
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
# Create some test data
@@ -880,7 +879,7 @@ def test_forcesell_handle_invalid(default_conf, update, mocker) -> None:
)
mocker.patch('freqtrade.freqtradebot.exchange.validate_pairs', MagicMock())
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
# Trader is not running
@@ -927,7 +926,7 @@ def test_performance_handle(default_conf, update, ticker, fee,
get_fee=fee
)
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
# Create some test data
@@ -962,7 +961,7 @@ def test_performance_handle_invalid(default_conf, update, mocker) -> None:
send_msg=msg_mock
)
mocker.patch('freqtrade.freqtradebot.exchange.validate_pairs', MagicMock())
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
# Trader is not running
@@ -991,7 +990,7 @@ def test_count_handle(default_conf, update, ticker, fee, mocker) -> None:
buy=MagicMock(return_value={'id': 'mocked_order_id'})
)
mocker.patch('freqtrade.optimize.backtesting.exchange.get_fee', fee)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
freqtradebot.state = State.STOPPED
@@ -1027,7 +1026,7 @@ def test_help_handle(default_conf, update, mocker) -> None:
_init=MagicMock(),
send_msg=msg_mock
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
telegram._help(bot=MagicMock(), update=update)
@@ -1047,7 +1046,7 @@ def test_version_handle(default_conf, update, mocker) -> None:
_init=MagicMock(),
send_msg=msg_mock
)
freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(default_conf)
telegram = Telegram(freqtradebot)
telegram._version(bot=MagicMock(), update=update)
@@ -1064,7 +1063,7 @@ def test_send_msg(default_conf, mocker) -> None:
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
conf = deepcopy(default_conf)
bot = MagicMock()
freqtradebot = FreqtradeBot(conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(conf)
telegram = Telegram(freqtradebot)
telegram._config['telegram']['enabled'] = False
@@ -1087,7 +1086,7 @@ def test_send_msg_network_error(default_conf, mocker, caplog) -> None:
conf = deepcopy(default_conf)
bot = MagicMock()
bot.send_message = MagicMock(side_effect=NetworkError('Oh snap'))
freqtradebot = FreqtradeBot(conf, create_engine('sqlite://'))
freqtradebot = FreqtradeBot(conf)
telegram = Telegram(freqtradebot)
telegram._config['telegram']['enabled'] = True

View File

@@ -13,6 +13,7 @@ from pandas import DataFrame
from freqtrade.analyze import Analyze, SignalType
from freqtrade.optimize.__init__ import load_tickerdata_file
from freqtrade.arguments import TimeRange
from freqtrade.tests.conftest import log_has
# Avoid to reinit the same object again and again
@@ -183,7 +184,7 @@ def test_tickerdata_to_dataframe(default_conf) -> None:
"""
analyze = Analyze(default_conf)
timerange = ((None, 'line'), None, -100)
timerange = TimeRange(None, 'line', 0, -100)
tick = load_tickerdata_file(None, 'UNITTEST/BTC', '1m', timerange=timerange)
tickerlist = {'UNITTEST/BTC': tick}
data = analyze.tickerdata_to_dataframe(tickerlist)

View File

@@ -9,7 +9,7 @@ import logging
import pytest
from freqtrade.arguments import Arguments
from freqtrade.arguments import Arguments, TimeRange
def test_arguments_object() -> None:
@@ -46,6 +46,11 @@ def test_parse_args_config() -> None:
assert args.config == '/dev/null'
def test_parse_args_db_url() -> None:
args = Arguments(['--db-url', 'sqlite:///test.sqlite'], '').get_parsed_arg()
assert args.db_url == 'sqlite:///test.sqlite'
def test_parse_args_verbose() -> None:
args = Arguments(['-v'], '').get_parsed_arg()
assert args.loglevel == logging.DEBUG
@@ -107,20 +112,24 @@ def test_parse_args_dynamic_whitelist_invalid_values() -> None:
def test_parse_timerange_incorrect() -> None:
assert ((None, 'line'), None, -200) == Arguments.parse_timerange('-200')
assert (('line', None), 200, None) == Arguments.parse_timerange('200-')
assert (('index', 'index'), 200, 500) == Arguments.parse_timerange('200-500')
assert TimeRange(None, 'line', 0, -200) == Arguments.parse_timerange('-200')
assert TimeRange('line', None, 200, 0) == Arguments.parse_timerange('200-')
assert TimeRange('index', 'index', 200, 500) == Arguments.parse_timerange('200-500')
assert (('date', None), 1274486400, None) == Arguments.parse_timerange('20100522-')
assert ((None, 'date'), None, 1274486400) == Arguments.parse_timerange('-20100522')
assert TimeRange('date', None, 1274486400, 0) == Arguments.parse_timerange('20100522-')
assert TimeRange(None, 'date', 0, 1274486400) == Arguments.parse_timerange('-20100522')
timerange = Arguments.parse_timerange('20100522-20150730')
assert timerange == (('date', 'date'), 1274486400, 1438214400)
assert timerange == TimeRange('date', 'date', 1274486400, 1438214400)
# Added test for unix timestamp - BTC genesis date
assert (('date', None), 1231006505, None) == Arguments.parse_timerange('1231006505-')
assert ((None, 'date'), None, 1233360000) == Arguments.parse_timerange('-1233360000')
assert TimeRange('date', None, 1231006505, 0) == Arguments.parse_timerange('1231006505-')
assert TimeRange(None, 'date', 0, 1233360000) == Arguments.parse_timerange('-1233360000')
timerange = Arguments.parse_timerange('1231006505-1233360000')
assert timerange == (('date', 'date'), 1231006505, 1233360000)
assert TimeRange('date', 'date', 1231006505, 1233360000) == timerange
# TODO: Find solution for the following case (passing timestamp in ms)
timerange = Arguments.parse_timerange('1231006505000-1233360000000')
assert TimeRange('date', 'date', 1231006505, 1233360000) != timerange
with pytest.raises(Exception, match=r'Incorrect syntax.*'):
Arguments.parse_timerange('-')

View File

@@ -130,7 +130,6 @@ def test_load_config(default_conf, mocker) -> None:
assert validated_conf.get('strategy') == 'DefaultStrategy'
assert validated_conf.get('strategy_path') is None
assert 'dynamic_whitelist' not in validated_conf
assert 'dry_run_db' not in validated_conf
def test_load_config_with_params(default_conf, mocker) -> None:
@@ -145,7 +144,7 @@ def test_load_config_with_params(default_conf, mocker) -> None:
'--dynamic-whitelist', '10',
'--strategy', 'TestStrategy',
'--strategy-path', '/some/path',
'--dry-run-db',
'--db-url', 'sqlite:///someurl',
]
args = Arguments(arglist, '').get_parsed_arg()
@@ -155,7 +154,7 @@ def test_load_config_with_params(default_conf, mocker) -> None:
assert validated_conf.get('dynamic_whitelist') == 10
assert validated_conf.get('strategy') == 'TestStrategy'
assert validated_conf.get('strategy_path') == '/some/path'
assert validated_conf.get('dry_run_db') is True
assert validated_conf.get('db_url') == 'sqlite:///someurl'
def test_load_custom_strategy(default_conf, mocker) -> None:
@@ -190,7 +189,7 @@ def test_show_info(default_conf, mocker, caplog) -> None:
arglist = [
'--dynamic-whitelist', '10',
'--strategy', 'TestStrategy',
'--dry-run-db'
'--db-url', 'sqlite:///tmp/testdb',
]
args = Arguments(arglist, '').get_parsed_arg()
@@ -204,23 +203,8 @@ def test_show_info(default_conf, mocker, caplog) -> None:
caplog.record_tuples
)
assert log_has(
'Parameter --dry-run-db detected ...',
caplog.record_tuples
)
assert log_has(
'Dry_run will use the DB file: "tradesv3.dry_run.sqlite"',
caplog.record_tuples
)
# Test the Dry run condition
configuration.config.update({'dry_run': False}) # type: ignore
configuration._load_common_config(configuration.config) # type: ignore
assert log_has(
'Dry run is disabled. (--dry_run_db ignored)',
caplog.record_tuples
)
assert log_has('Using DB: "sqlite:///tmp/testdb"', caplog.record_tuples)
assert log_has('Dry run is enabled', caplog.record_tuples)
def test_setup_configuration_without_arguments(mocker, default_conf, caplog) -> None:

View File

@@ -13,7 +13,6 @@ from unittest.mock import MagicMock
import arrow
import pytest
import requests
from sqlalchemy import create_engine
from freqtrade import constants, DependencyException, OperationalException, TemporaryError
from freqtrade.freqtradebot import FreqtradeBot
@@ -36,7 +35,7 @@ def get_patched_freqtradebot(mocker, config) -> FreqtradeBot:
mocker.patch('freqtrade.freqtradebot.exchange.init', MagicMock())
patch_coinmarketcap(mocker)
return FreqtradeBot(config, create_engine('sqlite://'))
return FreqtradeBot(config)
def patch_get_signal(mocker, value=(True, False)) -> None:
@@ -346,7 +345,7 @@ def test_create_trade(default_conf, ticker, limit_buy_order, fee, mocker) -> Non
# Save state of current whitelist
whitelist = deepcopy(default_conf['exchange']['pair_whitelist'])
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
freqtrade.create_trade()
trade = Trade.query.first()
@@ -383,13 +382,34 @@ def test_create_trade_minimal_amount(default_conf, ticker, limit_buy_order, fee,
conf = deepcopy(default_conf)
conf['stake_amount'] = 0.0005
freqtrade = FreqtradeBot(conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(conf)
freqtrade.create_trade()
rate, amount = buy_mock.call_args[0][1], buy_mock.call_args[0][2]
assert rate * amount >= conf['stake_amount']
def test_create_trade_no_stake_amount(default_conf, ticker, limit_buy_order, fee, mocker) -> None:
"""
Test create_trade() method
"""
patch_get_signal(mocker)
patch_RPCManager(mocker)
patch_coinmarketcap(mocker)
mocker.patch.multiple(
'freqtrade.freqtradebot.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
buy=MagicMock(return_value={'id': limit_buy_order['id']}),
get_balance=MagicMock(return_value=default_conf['stake_amount'] * 0.5),
get_fee=fee,
)
freqtrade = FreqtradeBot(default_conf)
with pytest.raises(DependencyException, match=r'.*stake amount.*'):
freqtrade.create_trade()
def test_create_trade_no_pairs(default_conf, ticker, limit_buy_order, fee, mocker) -> None:
"""
Test create_trade() method
@@ -408,7 +428,7 @@ def test_create_trade_no_pairs(default_conf, ticker, limit_buy_order, fee, mocke
conf = deepcopy(default_conf)
conf['exchange']['pair_whitelist'] = ["ETH/BTC"]
conf['exchange']['pair_blacklist'] = ["ETH/BTC"]
freqtrade = FreqtradeBot(conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(conf)
freqtrade.create_trade()
@@ -435,7 +455,7 @@ def test_create_trade_no_pairs_after_blacklist(default_conf, ticker,
conf = deepcopy(default_conf)
conf['exchange']['pair_whitelist'] = ["ETH/BTC"]
conf['exchange']['pair_blacklist'] = ["ETH/BTC"]
freqtrade = FreqtradeBot(conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(conf)
freqtrade.create_trade()
@@ -463,7 +483,7 @@ def test_create_trade_no_signal(default_conf, fee, mocker) -> None:
conf = deepcopy(default_conf)
conf['stake_amount'] = 10
freqtrade = FreqtradeBot(conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(conf)
Trade.query = MagicMock()
Trade.query.filter = MagicMock()
@@ -487,7 +507,7 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order,
get_order=MagicMock(return_value=limit_buy_order),
get_fee=fee,
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
trades = Trade.query.filter(Trade.is_open.is_(True)).all()
assert not trades
@@ -528,7 +548,7 @@ def test_process_exchange_failures(default_conf, ticker, markets, mocker) -> Non
)
sleep_mock = mocker.patch('time.sleep', side_effect=lambda _: None)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
result = freqtrade._process()
assert result is False
assert sleep_mock.has_calls()
@@ -548,7 +568,7 @@ def test_process_operational_exception(default_conf, ticker, markets, mocker) ->
get_markets=markets,
buy=MagicMock(side_effect=OperationalException)
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
assert freqtrade.state == State.RUNNING
result = freqtrade._process()
@@ -574,7 +594,7 @@ def test_process_trade_handling(
get_order=MagicMock(return_value=limit_buy_order),
get_fee=fee,
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
trades = Trade.query.filter(Trade.is_open.is_(True)).all()
assert not trades
@@ -691,7 +711,7 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, fee, mock
)
patch_coinmarketcap(mocker, value={'price_usd': 15000.0})
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
freqtrade.create_trade()
@@ -734,7 +754,7 @@ def test_handle_overlpapping_signals(default_conf, ticker, limit_buy_order, fee,
get_fee=fee,
)
freqtrade = FreqtradeBot(conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(conf)
freqtrade.create_trade()
@@ -793,7 +813,7 @@ def test_handle_trade_roi(default_conf, ticker, limit_buy_order, fee, mocker, ca
)
mocker.patch('freqtrade.freqtradebot.Analyze.min_roi_reached', return_value=True)
freqtrade = FreqtradeBot(conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(conf)
freqtrade.create_trade()
trade = Trade.query.first()
@@ -830,7 +850,7 @@ def test_handle_trade_experimental(
)
mocker.patch('freqtrade.freqtradebot.Analyze.min_roi_reached', return_value=False)
freqtrade = FreqtradeBot(conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(conf)
freqtrade.create_trade()
trade = Trade.query.first()
@@ -858,7 +878,7 @@ def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, fe
buy=MagicMock(return_value={'id': limit_buy_order['id']}),
get_fee=fee,
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
# Create trade and sell it
freqtrade.create_trade()
@@ -889,7 +909,7 @@ def test_check_handle_timedout_buy(default_conf, ticker, limit_buy_order_old, fe
cancel_order=cancel_order_mock,
get_fee=fee
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
trade_buy = Trade(
pair='ETH/BTC',
@@ -929,7 +949,7 @@ def test_check_handle_timedout_sell(default_conf, ticker, limit_sell_order_old,
get_order=MagicMock(return_value=limit_sell_order_old),
cancel_order=cancel_order_mock
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
trade_sell = Trade(
pair='ETH/BTC',
@@ -969,7 +989,7 @@ def test_check_handle_timedout_partial(default_conf, ticker, limit_buy_order_old
get_order=MagicMock(return_value=limit_buy_order_old_partial),
cancel_order=cancel_order_mock
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
trade_buy = Trade(
pair='ETH/BTC',
@@ -1017,7 +1037,7 @@ def test_check_handle_timedout_exception(default_conf, ticker, mocker, caplog) -
get_order=MagicMock(side_effect=requests.exceptions.RequestException('Oh snap')),
cancel_order=cancel_order_mock
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
trade_buy = Trade(
pair='ETH/BTC',
@@ -1056,7 +1076,7 @@ def test_handle_timedout_limit_buy(mocker, default_conf) -> None:
cancel_order=cancel_order_mock
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
Trade.session = MagicMock()
trade = MagicMock()
@@ -1082,7 +1102,7 @@ def test_handle_timedout_limit_sell(mocker, default_conf) -> None:
cancel_order=cancel_order_mock
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
trade = MagicMock()
order = {'remaining': 1,
@@ -1109,7 +1129,7 @@ def test_execute_sell_up(default_conf, ticker, fee, ticker_sell_up, mocker) -> N
get_fee=fee
)
mocker.patch('freqtrade.fiat_convert.CryptoToFiatConverter._find_price', return_value=15000.0)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
# Create some test data
freqtrade.create_trade()
@@ -1150,7 +1170,7 @@ def test_execute_sell_down(default_conf, ticker, fee, ticker_sell_down, mocker)
get_ticker=ticker,
get_fee=fee
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
# Create some test data
freqtrade.create_trade()
@@ -1190,7 +1210,7 @@ def test_execute_sell_without_conf_sell_up(default_conf, ticker, fee,
get_ticker=ticker,
get_fee=fee
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
# Create some test data
freqtrade.create_trade()
@@ -1231,7 +1251,7 @@ def test_execute_sell_without_conf_sell_down(default_conf, ticker, fee,
get_ticker=ticker,
get_fee=fee
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
# Create some test data
freqtrade.create_trade()
@@ -1280,7 +1300,7 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, fee, mock
'use_sell_signal': True,
'sell_profit_only': True,
}
freqtrade = FreqtradeBot(conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(conf)
freqtrade.create_trade()
trade = Trade.query.first()
@@ -1313,7 +1333,7 @@ def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, fee, moc
'use_sell_signal': True,
'sell_profit_only': False,
}
freqtrade = FreqtradeBot(conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(conf)
freqtrade.create_trade()
trade = Trade.query.first()
@@ -1346,7 +1366,7 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, fee, mocker
'use_sell_signal': True,
'sell_profit_only': True,
}
freqtrade = FreqtradeBot(conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(conf)
freqtrade.create_trade()
trade = Trade.query.first()
@@ -1381,7 +1401,7 @@ def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, fee, mocke
'sell_profit_only': False,
}
freqtrade = FreqtradeBot(conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(conf)
freqtrade.create_trade()
trade = Trade.query.first()
@@ -1409,7 +1429,7 @@ def test_get_real_amount_quote(default_conf, trades_for_order, buy_order_fee, ca
open_rate=0.245441,
open_order_id="123456"
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
# Amount is reduced by "fee"
assert freqtrade.get_real_amount(trade, buy_order_fee) == amount - (amount * 0.001)
assert log_has('Applying fee on amount for Trade(id=None, pair=LTC/ETH, amount=8.00000000, '
@@ -1436,7 +1456,7 @@ def test_get_real_amount_no_trade(default_conf, buy_order_fee, caplog, mocker):
open_rate=0.245441,
open_order_id="123456"
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
# Amount is reduced by "fee"
assert freqtrade.get_real_amount(trade, buy_order_fee) == amount
assert log_has('Applying fee on amount for Trade(id=None, pair=LTC/ETH, amount=8.00000000, '
@@ -1463,7 +1483,7 @@ def test_get_real_amount_stake(default_conf, trades_for_order, buy_order_fee, ca
open_rate=0.245441,
open_order_id="123456"
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
# Amount does not change
assert freqtrade.get_real_amount(trade, buy_order_fee) == amount
@@ -1489,7 +1509,7 @@ def test_get_real_amount_BNB(default_conf, trades_for_order, buy_order_fee, mock
open_rate=0.245441,
open_order_id="123456"
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
# Amount does not change
assert freqtrade.get_real_amount(trade, buy_order_fee) == amount
@@ -1512,7 +1532,7 @@ def test_get_real_amount_multi(default_conf, trades_for_order2, buy_order_fee, c
open_rate=0.245441,
open_order_id="123456"
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
# Amount is reduced by "fee"
assert freqtrade.get_real_amount(trade, buy_order_fee) == amount - (amount * 0.001)
assert log_has('Applying fee on amount for Trade(id=None, pair=LTC/ETH, amount=8.00000000, '
@@ -1540,7 +1560,7 @@ def test_get_real_amount_fromorder(default_conf, trades_for_order, buy_order_fee
open_rate=0.245441,
open_order_id="123456"
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
# Amount is reduced by "fee"
assert freqtrade.get_real_amount(trade, limit_buy_order) == amount - 0.004
assert log_has('Applying fee on amount for Trade(id=None, pair=LTC/ETH, amount=8.00000000, '
@@ -1568,7 +1588,7 @@ def test_get_real_amount_invalid_order(default_conf, trades_for_order, buy_order
open_rate=0.245441,
open_order_id="123456"
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
# Amount does not change
assert freqtrade.get_real_amount(trade, limit_buy_order) == amount
@@ -1593,6 +1613,6 @@ def test_get_real_amount_invalid(default_conf, trades_for_order, buy_order_fee,
open_rate=0.245441,
open_order_id="123456"
)
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
freqtrade = FreqtradeBot(default_conf)
# Amount does not change
assert freqtrade.get_real_amount(trade, buy_order_fee) == amount

View File

@@ -1,9 +1,11 @@
# pragma pylint: disable=missing-docstring, C0103
import os
from copy import deepcopy
from unittest.mock import MagicMock
import pytest
from sqlalchemy import create_engine
from freqtrade import constants, OperationalException
from freqtrade.persistence import Trade, init, clean_dry_run_db
@@ -21,77 +23,54 @@ def test_init_create_session(default_conf, mocker):
assert 'Session' in type(Trade.session).__name__
def test_init_dry_run_db(default_conf, mocker):
default_conf.update({'dry_run_db': True})
mocker.patch.dict('freqtrade.persistence._CONF', default_conf)
def test_init_custom_db_url(default_conf, mocker):
conf = deepcopy(default_conf)
# First, protect the existing 'tradesv3.dry_run.sqlite' (Do not delete user data)
dry_run_db = 'tradesv3.dry_run.sqlite'
dry_run_db_swp = dry_run_db + '.swp'
# Update path to a value other than default, but still in-memory
conf.update({'db_url': 'sqlite:///tmp/freqtrade2_test.sqlite'})
create_engine_mock = mocker.patch('freqtrade.persistence.create_engine', MagicMock())
mocker.patch.dict('freqtrade.persistence._CONF', conf)
if os.path.isfile(dry_run_db):
os.rename(dry_run_db, dry_run_db_swp)
# Check if the new tradesv3.dry_run.sqlite was created
init(default_conf)
assert os.path.isfile(dry_run_db) is True
# Delete the file made for this unitest and rollback to the previous
# tradesv3.dry_run.sqlite file
# 1. Delete file from the test
if os.path.isfile(dry_run_db):
os.remove(dry_run_db)
# 2. Rollback to the initial file
if os.path.isfile(dry_run_db_swp):
os.rename(dry_run_db_swp, dry_run_db)
init(conf)
assert create_engine_mock.call_count == 1
assert create_engine_mock.mock_calls[0][1][0] == 'sqlite:///tmp/freqtrade2_test.sqlite'
def test_init_dry_run_without_db(default_conf, mocker):
default_conf.update({'dry_run_db': False})
mocker.patch.dict('freqtrade.persistence._CONF', default_conf)
def test_init_invalid_db_url(default_conf, mocker):
conf = deepcopy(default_conf)
# First, protect the existing 'tradesv3.dry_run.sqlite' (Do not delete user data)
dry_run_db = 'tradesv3.dry_run.sqlite'
dry_run_db_swp = dry_run_db + '.swp'
# Update path to a value other than default, but still in-memory
conf.update({'db_url': 'unknown:///some.url'})
mocker.patch.dict('freqtrade.persistence._CONF', conf)
if os.path.isfile(dry_run_db):
os.rename(dry_run_db, dry_run_db_swp)
# Check if the new tradesv3.dry_run.sqlite was created
init(default_conf)
assert os.path.isfile(dry_run_db) is False
# Rollback to the initial 'tradesv3.dry_run.sqlite' file
if os.path.isfile(dry_run_db_swp):
os.rename(dry_run_db_swp, dry_run_db)
with pytest.raises(OperationalException, match=r'.*no valid database URL*'):
init(conf)
def test_init_prod_db(default_conf, mocker):
default_conf.update({'dry_run': False})
mocker.patch.dict('freqtrade.persistence._CONF', default_conf)
conf = deepcopy(default_conf)
conf.update({'dry_run': False})
conf.update({'db_url': constants.DEFAULT_DB_PROD_URL})
# First, protect the existing 'tradesv3.sqlite' (Do not delete user data)
prod_db = 'tradesv3.sqlite'
prod_db_swp = prod_db + '.swp'
create_engine_mock = mocker.patch('freqtrade.persistence.create_engine', MagicMock())
mocker.patch.dict('freqtrade.persistence._CONF', conf)
if os.path.isfile(prod_db):
os.rename(prod_db, prod_db_swp)
init(conf)
assert create_engine_mock.call_count == 1
assert create_engine_mock.mock_calls[0][1][0] == 'sqlite:///tradesv3.sqlite'
# Check if the new tradesv3.sqlite was created
init(default_conf)
assert os.path.isfile(prod_db) is True
# Delete the file made for this unitest and rollback to the previous tradesv3.sqlite file
def test_init_dryrun_db(default_conf, mocker):
conf = deepcopy(default_conf)
conf.update({'dry_run': True})
conf.update({'db_url': constants.DEFAULT_DB_DRYRUN_URL})
# 1. Delete file from the test
if os.path.isfile(prod_db):
os.remove(prod_db)
create_engine_mock = mocker.patch('freqtrade.persistence.create_engine', MagicMock())
mocker.patch.dict('freqtrade.persistence._CONF', conf)
# Rollback to the initial 'tradesv3.sqlite' file
if os.path.isfile(prod_db_swp):
os.rename(prod_db_swp, prod_db)
init(conf)
assert create_engine_mock.call_count == 1
assert create_engine_mock.mock_calls[0][1][0] == 'sqlite://'
@pytest.mark.usefixtures("init_persistence")
@@ -328,7 +307,7 @@ def test_calc_profit_percent(limit_buy_order, limit_sell_order, fee):
def test_clean_dry_run_db(default_conf, fee):
init(default_conf, create_engine('sqlite://'))
init(default_conf)
# Simulate dry_run entries
trade = Trade(
@@ -377,7 +356,7 @@ def test_clean_dry_run_db(default_conf, fee):
assert len(Trade.query.filter(Trade.open_order_id.isnot(None)).all()) == 1
def test_migrate_old(default_conf, fee):
def test_migrate_old(mocker, default_conf, fee):
"""
Test Database migration(starting with old pairformat)
"""
@@ -409,11 +388,13 @@ def test_migrate_old(default_conf, fee):
amount=amount
)
engine = create_engine('sqlite://')
mocker.patch('freqtrade.persistence.create_engine', lambda *args, **kwargs: engine)
# Create table using the old format
engine.execute(create_table_old)
engine.execute(insert_table_old)
# Run init to test migration
init(default_conf, engine)
init(default_conf)
assert len(Trade.query.filter(Trade.id == 1).all()) == 1
trade = Trade.query.filter(Trade.id == 1).first()
@@ -428,7 +409,7 @@ def test_migrate_old(default_conf, fee):
assert trade.exchange == "bittrex"
def test_migrate_new(default_conf, fee):
def test_migrate_new(mocker, default_conf, fee):
"""
Test Database migration (starting with new pairformat)
"""
@@ -460,11 +441,13 @@ def test_migrate_new(default_conf, fee):
amount=amount
)
engine = create_engine('sqlite://')
mocker.patch('freqtrade.persistence.create_engine', lambda *args, **kwargs: engine)
# Create table using the old format
engine.execute(create_table_old)
engine.execute(insert_table_old)
# Run init to test migration
init(default_conf, engine)
init(default_conf)
assert len(Trade.query.filter(Trade.id == 1).all()) == 1
trade = Trade.query.filter(Trade.id == 1).first()