Merge branch 'develop' into test_coverage
This commit is contained in:
@@ -212,7 +212,18 @@ def test_exchange_bittrex_get_ticker_bad():
|
||||
wb = make_wrap_bittrex()
|
||||
fb = FakeBittrex()
|
||||
fb.result = {'success': True,
|
||||
'result': {'Bid': 1}} # incomplete result
|
||||
'result': {'Bid': 1, 'Ask': 0}} # incomplete result
|
||||
|
||||
with pytest.raises(ContentDecodingError, match=r'.*Got invalid response from bittrex params.*'):
|
||||
wb.get_ticker('BTC_ETH')
|
||||
fb.result = {'success': False,
|
||||
'message': 'gone bad'
|
||||
}
|
||||
with pytest.raises(btx.OperationalException, match=r'.*gone bad.*'):
|
||||
wb.get_ticker('BTC_ETH')
|
||||
|
||||
fb.result = {'success': True,
|
||||
'result': {}} # incomplete result
|
||||
with pytest.raises(ContentDecodingError, match=r'.*Got invalid response from bittrex params.*'):
|
||||
wb.get_ticker('BTC_ETH')
|
||||
fb.result = {'success': False,
|
||||
|
@@ -11,6 +11,13 @@ from freqtrade.optimize.backtesting import backtest, generate_text_table, get_ti
|
||||
import freqtrade.optimize.backtesting as backtesting
|
||||
|
||||
|
||||
def trim_dictlist(dl, num):
|
||||
new = {}
|
||||
for pair, pair_data in dl.items():
|
||||
new[pair] = pair_data[num:]
|
||||
return new
|
||||
|
||||
|
||||
def test_generate_text_table():
|
||||
results = pd.DataFrame(
|
||||
{
|
||||
@@ -43,6 +50,7 @@ def test_backtest(default_conf, mocker):
|
||||
exchange._API = Bittrex({'key': '', 'secret': ''})
|
||||
|
||||
data = optimize.load_data(None, ticker_interval=5, pairs=['BTC_ETH'])
|
||||
data = trim_dictlist(data, -200)
|
||||
results = backtest(default_conf['stake_amount'],
|
||||
optimize.preprocess(data), 10, True)
|
||||
assert not results.empty
|
||||
@@ -54,21 +62,15 @@ def test_backtest_1min_ticker_interval(default_conf, mocker):
|
||||
|
||||
# Run a backtesting for an exiting 5min ticker_interval
|
||||
data = optimize.load_data(None, ticker_interval=1, pairs=['BTC_UNITEST'])
|
||||
data = trim_dictlist(data, -200)
|
||||
results = backtest(default_conf['stake_amount'],
|
||||
optimize.preprocess(data), 1, True)
|
||||
assert not results.empty
|
||||
|
||||
|
||||
def trim_dictlist(dl, num):
|
||||
new = {}
|
||||
for pair, pair_data in dl.items():
|
||||
new[pair] = pair_data[num:]
|
||||
return new
|
||||
|
||||
|
||||
def load_data_test(what):
|
||||
data = optimize.load_data(None, ticker_interval=1, pairs=['BTC_UNITEST'])
|
||||
data = trim_dictlist(data, -100)
|
||||
timerange = ((None, 'line'), None, -100)
|
||||
data = optimize.load_data(None, ticker_interval=1, pairs=['BTC_UNITEST'], timerange=timerange)
|
||||
pair = data['BTC_UNITEST']
|
||||
datalen = len(pair)
|
||||
# Depending on the what parameter we now adjust the
|
||||
@@ -125,6 +127,7 @@ def simple_backtest(config, contour, num_results):
|
||||
def test_backtest2(default_conf, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
data = optimize.load_data(None, ticker_interval=5, pairs=['BTC_ETH'])
|
||||
data = trim_dictlist(data, -200)
|
||||
results = backtest(default_conf['stake_amount'],
|
||||
optimize.preprocess(data), 10, True)
|
||||
assert not results.empty
|
||||
@@ -149,10 +152,10 @@ def test_backtest_pricecontours(default_conf, mocker):
|
||||
simple_backtest(default_conf, contour, numres)
|
||||
|
||||
|
||||
def mocked_load_data(datadir, pairs=[], ticker_interval=0, refresh_pairs=False):
|
||||
tickerdata = optimize.load_tickerdata_file(datadir, 'BTC_UNITEST', 1)
|
||||
def mocked_load_data(datadir, pairs=[], ticker_interval=0, refresh_pairs=False, timerange=None):
|
||||
tickerdata = optimize.load_tickerdata_file(datadir, 'BTC_UNITEST', 1, timerange=timerange)
|
||||
pairdata = {'BTC_UNITEST': tickerdata}
|
||||
return trim_dictlist(pairdata, -100)
|
||||
return pairdata
|
||||
|
||||
|
||||
def test_backtest_start(default_conf, mocker, caplog):
|
||||
@@ -166,6 +169,7 @@ def test_backtest_start(default_conf, mocker, caplog):
|
||||
args.level = 10
|
||||
args.live = False
|
||||
args.datadir = None
|
||||
args.timerange = '-100' # needed due to MagicMock malleability
|
||||
backtesting.start(args)
|
||||
# check the logs, that will contain the backtest result
|
||||
exists = ['Using max_open_trades: 1 ...',
|
||||
|
@@ -54,6 +54,7 @@ def create_trials(mocker):
|
||||
|
||||
def test_start_calls_fmin(mocker):
|
||||
trials = create_trials(mocker)
|
||||
mocker.patch('freqtrade.optimize.tickerdata_to_dataframe')
|
||||
mocker.patch('freqtrade.optimize.hyperopt.TRIALS', return_value=trials)
|
||||
mocker.patch('freqtrade.optimize.hyperopt.sorted',
|
||||
return_value=trials.results)
|
||||
@@ -61,7 +62,8 @@ def test_start_calls_fmin(mocker):
|
||||
mocker.patch('freqtrade.optimize.load_data')
|
||||
mock_fmin = mocker.patch('freqtrade.optimize.hyperopt.fmin', return_value={})
|
||||
|
||||
args = mocker.Mock(epochs=1, config='config.json.example', mongodb=False)
|
||||
args = mocker.Mock(epochs=1, config='config.json.example', mongodb=False,
|
||||
timerange=None)
|
||||
start(args)
|
||||
|
||||
mock_fmin.assert_called_once()
|
||||
@@ -70,11 +72,12 @@ def test_start_calls_fmin(mocker):
|
||||
def test_start_uses_mongotrials(mocker):
|
||||
mock_mongotrials = mocker.patch('freqtrade.optimize.hyperopt.MongoTrials',
|
||||
return_value=create_trials(mocker))
|
||||
mocker.patch('freqtrade.optimize.preprocess')
|
||||
mocker.patch('freqtrade.optimize.tickerdata_to_dataframe')
|
||||
mocker.patch('freqtrade.optimize.load_data')
|
||||
mocker.patch('freqtrade.optimize.hyperopt.fmin', return_value={})
|
||||
|
||||
args = mocker.Mock(epochs=1, config='config.json.example', mongodb=True)
|
||||
args = mocker.Mock(epochs=1, config='config.json.example', mongodb=True,
|
||||
timerange=None)
|
||||
start(args)
|
||||
|
||||
mock_mongotrials.assert_called_once()
|
||||
@@ -107,6 +110,7 @@ def test_no_log_if_loss_does_not_improve(mocker):
|
||||
|
||||
def test_fmin_best_results(mocker, caplog):
|
||||
fmin_result = {
|
||||
"macd_below_zero": 0,
|
||||
"adx": 1,
|
||||
"adx-value": 15.0,
|
||||
"fastd": 1,
|
||||
@@ -124,11 +128,12 @@ def test_fmin_best_results(mocker, caplog):
|
||||
}
|
||||
|
||||
mocker.patch('freqtrade.optimize.hyperopt.MongoTrials', return_value=create_trials(mocker))
|
||||
mocker.patch('freqtrade.optimize.preprocess')
|
||||
mocker.patch('freqtrade.optimize.tickerdata_to_dataframe')
|
||||
mocker.patch('freqtrade.optimize.load_data')
|
||||
mocker.patch('freqtrade.optimize.hyperopt.fmin', return_value=fmin_result)
|
||||
|
||||
args = mocker.Mock(epochs=1, config='config.json.example')
|
||||
args = mocker.Mock(epochs=1, config='config.json.example',
|
||||
timerange=None)
|
||||
start(args)
|
||||
|
||||
exists = [
|
||||
@@ -136,7 +141,7 @@ def test_fmin_best_results(mocker, caplog):
|
||||
'"adx": {\n "enabled": true,\n "value": 15.0\n },',
|
||||
'"green_candle": {\n "enabled": true\n },',
|
||||
'"mfi": {\n "enabled": false\n },',
|
||||
'"trigger": {\n "type": "ao_cross_zero"\n },',
|
||||
'"trigger": {\n "type": "faststoch10"\n },',
|
||||
'"stoploss": -0.1',
|
||||
]
|
||||
|
||||
@@ -146,11 +151,12 @@ def test_fmin_best_results(mocker, caplog):
|
||||
|
||||
def test_fmin_throw_value_error(mocker, caplog):
|
||||
mocker.patch('freqtrade.optimize.hyperopt.MongoTrials', return_value=create_trials(mocker))
|
||||
mocker.patch('freqtrade.optimize.preprocess')
|
||||
mocker.patch('freqtrade.optimize.tickerdata_to_dataframe')
|
||||
mocker.patch('freqtrade.optimize.load_data')
|
||||
mocker.patch('freqtrade.optimize.hyperopt.fmin', side_effect=ValueError())
|
||||
|
||||
args = mocker.Mock(epochs=1, config='config.json.example')
|
||||
args = mocker.Mock(epochs=1, config='config.json.example',
|
||||
timerange=None)
|
||||
start(args)
|
||||
|
||||
exists = [
|
||||
@@ -184,7 +190,8 @@ def test_resuming_previous_hyperopt_results_succeeds(mocker):
|
||||
return_value={})
|
||||
args = mocker.Mock(epochs=1,
|
||||
config='config.json.example',
|
||||
mongodb=False)
|
||||
mongodb=False,
|
||||
timerange=None)
|
||||
|
||||
start(args)
|
||||
|
||||
|
@@ -189,3 +189,11 @@ def test_init(mocker):
|
||||
conf = {'exchange': {'pair_whitelist': []}}
|
||||
mocker.patch('freqtrade.optimize.hyperopt_optimize_conf', return_value=conf)
|
||||
assert {} == optimize.load_data('', pairs=[], refresh_pairs=True)
|
||||
|
||||
|
||||
def test_tickerdata_to_dataframe():
|
||||
timerange = ((None, 'line'), None, -100)
|
||||
tick = load_tickerdata_file(None, 'BTC_UNITEST', 1, timerange=timerange)
|
||||
tickerlist = {'BTC_UNITEST': tick}
|
||||
data = optimize.tickerdata_to_dataframe(tickerlist)
|
||||
assert 100 == len(data['BTC_UNITEST'])
|
||||
|
@@ -77,7 +77,7 @@ def test_authorized_only_exception(default_conf, mocker):
|
||||
|
||||
def test_status_handle(default_conf, update, ticker, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
||||
mocker.patch.multiple('freqtrade.rpc.telegram',
|
||||
@@ -112,7 +112,7 @@ def test_status_handle(default_conf, update, ticker, mocker):
|
||||
|
||||
def test_status_table_handle(default_conf, update, ticker, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
@@ -154,7 +154,7 @@ def test_status_table_handle(default_conf, update, ticker, mocker):
|
||||
def test_profit_handle(
|
||||
default_conf, update, ticker, ticker_sell_up, limit_buy_order, limit_sell_order, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
||||
mocker.patch.multiple('freqtrade.rpc.telegram',
|
||||
@@ -210,7 +210,7 @@ def test_profit_handle(
|
||||
|
||||
def test_forcesell_handle(default_conf, update, ticker, ticker_sell_up, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
rpc_mock = mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
||||
mocker.patch.multiple('freqtrade.rpc.telegram',
|
||||
_CONF=default_conf,
|
||||
@@ -247,7 +247,7 @@ def test_forcesell_handle(default_conf, update, ticker, ticker_sell_up, mocker):
|
||||
|
||||
def test_forcesell_down_handle(default_conf, update, ticker, ticker_sell_down, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
rpc_mock = mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
||||
mocker.patch.multiple('freqtrade.rpc.telegram',
|
||||
_CONF=default_conf,
|
||||
@@ -308,7 +308,7 @@ def test_exec_forcesell_open_orders(default_conf, ticker, mocker):
|
||||
|
||||
def test_forcesell_all_handle(default_conf, update, ticker, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
rpc_mock = mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
||||
mocker.patch.multiple('freqtrade.rpc.telegram',
|
||||
_CONF=default_conf,
|
||||
@@ -339,7 +339,7 @@ def test_forcesell_all_handle(default_conf, update, ticker, mocker):
|
||||
|
||||
def test_forcesell_handle_invalid(default_conf, update, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, True))
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple('freqtrade.rpc.telegram',
|
||||
_CONF=default_conf,
|
||||
@@ -376,7 +376,7 @@ def test_forcesell_handle_invalid(default_conf, update, mocker):
|
||||
def test_performance_handle(
|
||||
default_conf, update, ticker, limit_buy_order, limit_sell_order, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
||||
mocker.patch.multiple('freqtrade.rpc.telegram',
|
||||
@@ -410,7 +410,7 @@ def test_performance_handle(
|
||||
def test_daily_handle(
|
||||
default_conf, update, ticker, limit_buy_order, limit_sell_order, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
||||
mocker.patch.multiple('freqtrade.rpc.telegram',
|
||||
@@ -460,7 +460,7 @@ def test_daily_handle(
|
||||
|
||||
def test_count_handle(default_conf, update, ticker, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.rpc.telegram',
|
||||
@@ -492,7 +492,7 @@ def test_count_handle(default_conf, update, ticker, mocker):
|
||||
|
||||
def test_performance_handle_invalid(default_conf, update, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, True))
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple('freqtrade.rpc.telegram',
|
||||
_CONF=default_conf,
|
||||
@@ -606,11 +606,15 @@ def test_balance_handle(default_conf, update, mocker):
|
||||
send_msg=msg_mock)
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
get_balances=MagicMock(return_value=mock_balance))
|
||||
mocker.patch.multiple('freqtrade.fiat_convert.Pymarketcap',
|
||||
ticker=MagicMock(return_value={'price_usd': 15000.0}),
|
||||
_cache_symbols=MagicMock(return_value={'BTC': 1}))
|
||||
|
||||
_balance(bot=MagicMock(), update=update)
|
||||
assert msg_mock.call_count == 1
|
||||
assert '*Currency*: BTC' in msg_mock.call_args_list[0][0][0]
|
||||
assert 'Balance' in msg_mock.call_args_list[0][0][0]
|
||||
assert 'Est. BTC' in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
|
||||
def test_help_handle(default_conf, update, mocker):
|
||||
|
@@ -8,7 +8,7 @@ import datetime
|
||||
import pytest
|
||||
from pandas import DataFrame
|
||||
|
||||
from freqtrade.analyze import (SignalType, get_signal, parse_ticker_dataframe,
|
||||
from freqtrade.analyze import (get_signal, parse_ticker_dataframe,
|
||||
populate_buy_trend, populate_indicators,
|
||||
populate_sell_trend)
|
||||
|
||||
@@ -42,35 +42,35 @@ def test_returns_latest_buy_signal(mocker):
|
||||
mocker.patch('freqtrade.analyze.get_ticker_history', return_value=MagicMock())
|
||||
mocker.patch(
|
||||
'freqtrade.analyze.analyze_ticker',
|
||||
return_value=DataFrame([{'buy': 1, 'date': arrow.utcnow()}])
|
||||
return_value=DataFrame([{'buy': 1, 'sell': 0, 'date': arrow.utcnow()}])
|
||||
)
|
||||
assert get_signal('BTC-ETH', SignalType.BUY)
|
||||
assert get_signal('BTC-ETH') == (True, False)
|
||||
|
||||
mocker.patch(
|
||||
'freqtrade.analyze.analyze_ticker',
|
||||
return_value=DataFrame([{'buy': 0, 'date': arrow.utcnow()}])
|
||||
return_value=DataFrame([{'buy': 0, 'sell': 1, 'date': arrow.utcnow()}])
|
||||
)
|
||||
assert not get_signal('BTC-ETH', SignalType.BUY)
|
||||
assert get_signal('BTC-ETH') == (False, True)
|
||||
|
||||
|
||||
def test_returns_latest_sell_signal(mocker):
|
||||
mocker.patch('freqtrade.analyze.get_ticker_history', return_value=MagicMock())
|
||||
mocker.patch(
|
||||
'freqtrade.analyze.analyze_ticker',
|
||||
return_value=DataFrame([{'sell': 1, 'date': arrow.utcnow()}])
|
||||
return_value=DataFrame([{'sell': 1, 'buy': 0, 'date': arrow.utcnow()}])
|
||||
)
|
||||
assert get_signal('BTC-ETH', SignalType.SELL)
|
||||
assert get_signal('BTC-ETH') == (False, True)
|
||||
|
||||
mocker.patch(
|
||||
'freqtrade.analyze.analyze_ticker',
|
||||
return_value=DataFrame([{'sell': 0, 'date': arrow.utcnow()}])
|
||||
return_value=DataFrame([{'sell': 0, 'buy': 1, 'date': arrow.utcnow()}])
|
||||
)
|
||||
assert not get_signal('BTC-ETH', SignalType.SELL)
|
||||
assert get_signal('BTC-ETH') == (True, False)
|
||||
|
||||
|
||||
def test_get_signal_empty(mocker, caplog):
|
||||
mocker.patch('freqtrade.analyze.get_ticker_history', return_value=None)
|
||||
assert not get_signal('foo', SignalType.BUY)
|
||||
assert (False, False) == get_signal('foo')
|
||||
assert tt.log_has('Empty ticker history for pair foo',
|
||||
caplog.record_tuples)
|
||||
|
||||
@@ -79,17 +79,15 @@ def test_get_signal_execption_valueerror(mocker, caplog):
|
||||
mocker.patch('freqtrade.analyze.get_ticker_history', return_value=1)
|
||||
mocker.patch('freqtrade.analyze.analyze_ticker',
|
||||
side_effect=ValueError('xyz'))
|
||||
assert not get_signal('foo', SignalType.BUY)
|
||||
assert (False, False) == get_signal('foo')
|
||||
assert tt.log_has('Unable to analyze ticker for pair foo: xyz',
|
||||
caplog.record_tuples)
|
||||
|
||||
|
||||
# This error should never occur becase analyze_ticker is run first,
|
||||
# and that function can only add columns, it cant delete all rows from the dataframe
|
||||
def test_get_signal_empty_dataframe(mocker, caplog):
|
||||
mocker.patch('freqtrade.analyze.get_ticker_history', return_value=1)
|
||||
mocker.patch('freqtrade.analyze.analyze_ticker', return_value=DataFrame([]))
|
||||
assert not get_signal('xyz', SignalType.BUY)
|
||||
assert (False, False) == get_signal('xyz')
|
||||
assert tt.log_has('Empty dataframe for pair xyz',
|
||||
caplog.record_tuples)
|
||||
|
||||
@@ -100,7 +98,7 @@ def test_get_signal_old_dataframe(mocker, caplog):
|
||||
oldtime = arrow.utcnow() - datetime.timedelta(minutes=11)
|
||||
ticks = DataFrame([{'buy': 1, 'date': oldtime}])
|
||||
mocker.patch('freqtrade.analyze.analyze_ticker', return_value=DataFrame(ticks))
|
||||
assert not get_signal('xyz', SignalType.BUY)
|
||||
assert (False, False) == get_signal('xyz')
|
||||
assert tt.log_has('Too old dataframe for pair xyz',
|
||||
caplog.record_tuples)
|
||||
|
||||
@@ -110,4 +108,4 @@ def test_get_signal_handles_exceptions(mocker):
|
||||
mocker.patch('freqtrade.analyze.analyze_ticker',
|
||||
side_effect=Exception('invalid ticker history '))
|
||||
|
||||
assert not get_signal('BTC-ETH', SignalType.BUY)
|
||||
assert get_signal('BTC-ETH') == (False, False)
|
||||
|
@@ -11,7 +11,6 @@ from sqlalchemy import create_engine
|
||||
|
||||
import freqtrade.main as main
|
||||
from freqtrade import DependencyException, OperationalException
|
||||
from freqtrade.analyze import SignalType
|
||||
from freqtrade.exchange import Exchanges
|
||||
from freqtrade.main import (_process, check_handle_timedout, create_trade,
|
||||
execute_sell, get_target_bid, handle_trade, init)
|
||||
@@ -91,7 +90,7 @@ def test_process_maybe_execute_buy_exception(default_conf, mocker, caplog):
|
||||
def test_process_trade_creation(default_conf, ticker, limit_buy_order, health, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
get_ticker=ticker,
|
||||
@@ -121,7 +120,7 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order, health, m
|
||||
def test_process_exchange_failures(default_conf, ticker, health, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
sleep_mock = mocker.patch('time.sleep', side_effect=lambda _: None)
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
@@ -138,7 +137,7 @@ def test_process_operational_exception(default_conf, ticker, health, mocker):
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=msg_mock)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
get_ticker=ticker,
|
||||
@@ -156,8 +155,7 @@ def test_process_operational_exception(default_conf, ticker, health, mocker):
|
||||
def test_process_trade_handling(default_conf, ticker, limit_buy_order, health, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch('freqtrade.main.get_signal',
|
||||
side_effect=lambda *args: False if args[1] == SignalType.SELL else True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
get_ticker=ticker,
|
||||
@@ -179,7 +177,7 @@ def test_process_trade_handling(default_conf, ticker, limit_buy_order, health, m
|
||||
|
||||
def test_create_trade(default_conf, ticker, limit_buy_order, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
@@ -210,7 +208,7 @@ def test_create_trade(default_conf, ticker, limit_buy_order, mocker):
|
||||
def test_create_trade_minimal_amount(default_conf, ticker, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
buy_mock = mocker.patch(
|
||||
'freqtrade.main.exchange.buy', MagicMock(return_value='mocked_limit_buy')
|
||||
)
|
||||
@@ -226,7 +224,7 @@ def test_create_trade_minimal_amount(default_conf, ticker, mocker):
|
||||
|
||||
def test_create_trade_no_stake_amount(default_conf, ticker, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
@@ -239,7 +237,7 @@ def test_create_trade_no_stake_amount(default_conf, ticker, mocker):
|
||||
|
||||
def test_create_trade_no_pairs(default_conf, ticker, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
@@ -255,7 +253,7 @@ def test_create_trade_no_pairs(default_conf, ticker, mocker):
|
||||
|
||||
def test_create_trade_no_pairs_after_blacklist(default_conf, ticker, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
@@ -273,7 +271,7 @@ def test_create_trade_no_pairs_after_blacklist(default_conf, ticker, mocker):
|
||||
def test_create_trade_no_signal(default_conf, ticker, mocker):
|
||||
default_conf['dry_run'] = True
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', MagicMock(return_value=False))
|
||||
mocker.patch('freqtrade.main.get_signal', MagicMock(return_value=(False, False)))
|
||||
mocker.patch.multiple('freqtrade.exchange',
|
||||
get_ticker_history=MagicMock(return_value=20))
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
@@ -286,7 +284,7 @@ def test_create_trade_no_signal(default_conf, ticker, mocker):
|
||||
|
||||
def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
@@ -309,6 +307,7 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker):
|
||||
trade.update(limit_buy_order)
|
||||
assert trade.is_open is True
|
||||
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (False, True))
|
||||
handle_trade(trade)
|
||||
assert trade.open_order_id == 'mocked_limit_sell'
|
||||
|
||||
@@ -321,11 +320,57 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker):
|
||||
assert trade.close_date is not None
|
||||
|
||||
|
||||
def test_handle_overlpapping_signals(default_conf, ticker, mocker, caplog):
|
||||
default_conf.update({'experimental': {'use_sell_signal': True}})
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, True))
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
get_ticker=ticker,
|
||||
buy=MagicMock(return_value='mocked_limit_buy'))
|
||||
mocker.patch('freqtrade.main.min_roi_reached', return_value=False)
|
||||
|
||||
init(default_conf, create_engine('sqlite://'))
|
||||
create_trade(0.001)
|
||||
|
||||
# Buy and Sell triggering, so doing nothing ...
|
||||
trades = Trade.query.all()
|
||||
assert len(trades) == 0
|
||||
|
||||
# Buy is triggering, so buying ...
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
create_trade(0.001)
|
||||
trades = Trade.query.all()
|
||||
assert len(trades) == 1
|
||||
assert trades[0].is_open is True
|
||||
|
||||
# Buy and Sell are not triggering, so doing nothing ...
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (False, False))
|
||||
assert handle_trade(trades[0]) is False
|
||||
trades = Trade.query.all()
|
||||
assert len(trades) == 1
|
||||
assert trades[0].is_open is True
|
||||
|
||||
# Buy and Sell are triggering, so doing nothing ...
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, True))
|
||||
assert handle_trade(trades[0]) is False
|
||||
trades = Trade.query.all()
|
||||
assert len(trades) == 1
|
||||
assert trades[0].is_open is True
|
||||
|
||||
# Sell is triggering, guess what : we are Selling!
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (False, True))
|
||||
trades = Trade.query.all()
|
||||
assert handle_trade(trades[0]) is True
|
||||
|
||||
|
||||
def test_handle_trade_roi(default_conf, ticker, mocker, caplog):
|
||||
default_conf.update({'experimental': {'use_sell_signal': True}})
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
@@ -344,11 +389,11 @@ def test_handle_trade_roi(default_conf, ticker, mocker, caplog):
|
||||
# we might just want to check if we are in a sell condition without
|
||||
# executing
|
||||
# if ROI is reached we must sell
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: False)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (False, True))
|
||||
assert handle_trade(trade)
|
||||
assert ('freqtrade', logging.DEBUG, 'Executing sell due to ROI ...') in caplog.record_tuples
|
||||
# if ROI is reached we must sell even if sell-signal is not signalled
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (False, True))
|
||||
assert handle_trade(trade)
|
||||
assert ('freqtrade', logging.DEBUG, 'Executing sell due to ROI ...') in caplog.record_tuples
|
||||
|
||||
@@ -357,7 +402,7 @@ def test_handle_trade_experimental(default_conf, ticker, mocker, caplog):
|
||||
default_conf.update({'experimental': {'use_sell_signal': True}})
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
@@ -371,11 +416,10 @@ def test_handle_trade_experimental(default_conf, ticker, mocker, caplog):
|
||||
trade = Trade.query.first()
|
||||
trade.is_open = True
|
||||
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: False)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (False, False))
|
||||
value_returned = handle_trade(trade)
|
||||
assert ('freqtrade', logging.DEBUG, 'Checking sell_signal ...') in caplog.record_tuples
|
||||
assert value_returned is False
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (False, True))
|
||||
assert handle_trade(trade)
|
||||
s = 'Executing sell due to sell signal ...'
|
||||
assert ('freqtrade', logging.DEBUG, s) in caplog.record_tuples
|
||||
@@ -383,7 +427,7 @@ def test_handle_trade_experimental(default_conf, ticker, mocker, caplog):
|
||||
|
||||
def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
@@ -408,7 +452,8 @@ def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, mo
|
||||
def test_check_handle_timedout_buy(default_conf, ticker, limit_buy_order_old, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
cancel_order_mock = MagicMock()
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch('freqtrade.rpc.init', MagicMock())
|
||||
rpc_mock = mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
get_ticker=ticker,
|
||||
@@ -433,6 +478,7 @@ def test_check_handle_timedout_buy(default_conf, ticker, limit_buy_order_old, mo
|
||||
# check it does cancel buy orders over the time limit
|
||||
check_handle_timedout(600)
|
||||
assert cancel_order_mock.call_count == 1
|
||||
assert rpc_mock.call_count == 1
|
||||
trades = Trade.query.filter(Trade.open_order_id.is_(trade_buy.open_order_id)).all()
|
||||
assert len(trades) == 0
|
||||
|
||||
@@ -454,7 +500,8 @@ def test_handle_timedout_limit_buy(default_conf, mocker):
|
||||
def test_check_handle_timedout_sell(default_conf, ticker, limit_sell_order_old, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
cancel_order_mock = MagicMock()
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch('freqtrade.rpc.init', MagicMock())
|
||||
rpc_mock = mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
get_ticker=ticker,
|
||||
@@ -480,6 +527,7 @@ def test_check_handle_timedout_sell(default_conf, ticker, limit_sell_order_old,
|
||||
# check it does cancel sell orders over the time limit
|
||||
check_handle_timedout(600)
|
||||
assert cancel_order_mock.call_count == 1
|
||||
assert rpc_mock.call_count == 1
|
||||
assert trade_sell.is_open is True
|
||||
|
||||
|
||||
@@ -501,7 +549,8 @@ def test_check_handle_timedout_partial(default_conf, ticker, limit_buy_order_old
|
||||
mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
cancel_order_mock = MagicMock()
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch('freqtrade.rpc.init', MagicMock())
|
||||
rpc_mock = mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
get_ticker=ticker,
|
||||
@@ -527,6 +576,7 @@ def test_check_handle_timedout_partial(default_conf, ticker, limit_buy_order_old
|
||||
# note this is for a partially-complete buy order
|
||||
check_handle_timedout(600)
|
||||
assert cancel_order_mock.call_count == 1
|
||||
assert rpc_mock.call_count == 1
|
||||
trades = Trade.query.filter(Trade.open_order_id.is_(trade_buy.open_order_id)).all()
|
||||
assert len(trades) == 1
|
||||
assert trades[0].amount == 23.0
|
||||
@@ -550,7 +600,7 @@ def test_balance_bigger_last_ask(mocker):
|
||||
|
||||
def test_execute_sell_up(default_conf, ticker, ticker_sell_up, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch('freqtrade.rpc.init', MagicMock())
|
||||
rpc_mock = mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
@@ -583,7 +633,7 @@ def test_execute_sell_up(default_conf, ticker, ticker_sell_up, mocker):
|
||||
|
||||
def test_execute_sell_down(default_conf, ticker, ticker_sell_down, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch('freqtrade.rpc.init', MagicMock())
|
||||
rpc_mock = mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
||||
mocker.patch.multiple('freqtrade.rpc.telegram',
|
||||
@@ -620,7 +670,7 @@ def test_execute_sell_down(default_conf, ticker, ticker_sell_down, mocker):
|
||||
|
||||
def test_execute_sell_without_conf(default_conf, ticker, ticker_sell_up, mocker):
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch('freqtrade.rpc.init', MagicMock())
|
||||
rpc_mock = mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
@@ -657,7 +707,7 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, mocker):
|
||||
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.min_roi_reached', return_value=False)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
@@ -673,6 +723,7 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, mocker):
|
||||
|
||||
trade = Trade.query.first()
|
||||
trade.update(limit_buy_order)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (False, True))
|
||||
assert handle_trade(trade) is True
|
||||
|
||||
|
||||
@@ -684,7 +735,7 @@ def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, mocker):
|
||||
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.min_roi_reached', return_value=False)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
@@ -700,6 +751,7 @@ def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, mocker):
|
||||
|
||||
trade = Trade.query.first()
|
||||
trade.update(limit_buy_order)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (False, True))
|
||||
assert handle_trade(trade) is True
|
||||
|
||||
|
||||
@@ -711,7 +763,7 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, mocker):
|
||||
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.min_roi_reached', return_value=False)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
@@ -727,6 +779,7 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, mocker):
|
||||
|
||||
trade = Trade.query.first()
|
||||
trade.update(limit_buy_order)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (False, True))
|
||||
assert handle_trade(trade) is False
|
||||
|
||||
|
||||
@@ -738,7 +791,7 @@ def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, mocker):
|
||||
|
||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||
mocker.patch('freqtrade.main.min_roi_reached', return_value=False)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (True, False))
|
||||
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
@@ -754,4 +807,6 @@ def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, mocker):
|
||||
|
||||
trade = Trade.query.first()
|
||||
trade.update(limit_buy_order)
|
||||
|
||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s: (False, True))
|
||||
assert handle_trade(trade) is True
|
||||
|
@@ -8,7 +8,7 @@ import pytest
|
||||
from jsonschema import ValidationError
|
||||
|
||||
from freqtrade.misc import (common_args_parser, load_config, parse_args,
|
||||
throttle)
|
||||
throttle, parse_timerange)
|
||||
|
||||
|
||||
def test_throttle():
|
||||
@@ -133,6 +133,13 @@ def test_parse_args_hyperopt_custom(mocker):
|
||||
assert call_args.func is not None
|
||||
|
||||
|
||||
def test_parse_timerange_incorrect():
|
||||
assert ((None, 'line'), None, -200) == parse_timerange('-200')
|
||||
assert (('line', None), 200, None) == parse_timerange('200-')
|
||||
with pytest.raises(Exception, match=r'Incorrect syntax.*'):
|
||||
parse_timerange('-')
|
||||
|
||||
|
||||
def test_load_config(default_conf, mocker):
|
||||
file_mock = mocker.patch('freqtrade.misc.open', mocker.mock_open(
|
||||
read_data=json.dumps(default_conf)
|
||||
|
@@ -1,29 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""This script generate json data from bittrex"""
|
||||
import sys
|
||||
import json
|
||||
from os import path
|
||||
|
||||
from freqtrade import exchange
|
||||
from freqtrade.exchange import Bittrex
|
||||
from freqtrade import misc
|
||||
|
||||
PAIRS = [
|
||||
'BTC_BCC', 'BTC_ETH', 'BTC_MER', 'BTC_POWR', 'BTC_ETC',
|
||||
'BTC_OK', 'BTC_NEO', 'BTC_EMC2', 'BTC_DASH', 'BTC_LSK',
|
||||
'BTC_LTC', 'BTC_XZC', 'BTC_OMG', 'BTC_STRAT', 'BTC_XRP',
|
||||
'BTC_QTUM', 'BTC_WAVES', 'BTC_VTC', 'BTC_XLM', 'BTC_MCO'
|
||||
]
|
||||
TICKER_INTERVAL = 5 # ticker interval in minutes (currently implemented: 1 and 5)
|
||||
OUTPUT_DIR = path.dirname(path.realpath(__file__))
|
||||
parser = misc.common_args_parser('download utility')
|
||||
parser.add_argument(
|
||||
'-p', '--pair',
|
||||
help='JSON file containing pairs to download',
|
||||
dest='pair',
|
||||
default=None
|
||||
)
|
||||
args = parser.parse_args(sys.argv[1:])
|
||||
|
||||
TICKER_INTERVALS = [1, 5] # ticker interval in minutes (currently implemented: 1 and 5)
|
||||
PAIRS = []
|
||||
|
||||
if args.pair:
|
||||
with open(args.pair) as file:
|
||||
PAIRS = json.load(file)
|
||||
PAIRS = list(set(PAIRS))
|
||||
|
||||
print('About to download pairs:', PAIRS)
|
||||
|
||||
# Init Bittrex exchange
|
||||
exchange._API = Bittrex({'key': '', 'secret': ''})
|
||||
|
||||
for pair in PAIRS:
|
||||
data = exchange.get_ticker_history(pair, TICKER_INTERVAL)
|
||||
filename = path.join(OUTPUT_DIR, '{}-{}.json'.format(
|
||||
pair,
|
||||
TICKER_INTERVAL,
|
||||
))
|
||||
with open(filename, 'w') as fp:
|
||||
json.dump(data, fp)
|
||||
for tick_interval in TICKER_INTERVALS:
|
||||
print('downloading pair %s, interval %s' % (pair, tick_interval))
|
||||
data = exchange.get_ticker_history(pair, tick_interval)
|
||||
filename = '{}-{}.json'.format(pair, tick_interval)
|
||||
misc.file_dump_json(filename, data)
|
||||
|
23
freqtrade/tests/testdata/pairs.json
vendored
Normal file
23
freqtrade/tests/testdata/pairs.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
[
|
||||
"BTC_ADA",
|
||||
"BTC_BAT",
|
||||
"BTC_DASH",
|
||||
"BTC_ETC",
|
||||
"BTC_ETH",
|
||||
"BTC_GBYTE",
|
||||
"BTC_LSK",
|
||||
"BTC_LTC",
|
||||
"BTC_NEO",
|
||||
"BTC_NXT",
|
||||
"BTC_POWR",
|
||||
"BTC_STORJ",
|
||||
"BTC_QTUM",
|
||||
"BTC_WAVES",
|
||||
"BTC_VTC",
|
||||
"BTC_XLM",
|
||||
"BTC_XMR",
|
||||
"BTC_XVG",
|
||||
"BTC_XRP",
|
||||
"BTC_ZEC"
|
||||
]
|
||||
|
Reference in New Issue
Block a user