Change ticker_interval from integer to string (1m, 5m, 1d, ...)

This commit is contained in:
enenn 2018-02-04 19:41:49 +01:00
parent 1c64b7b0a7
commit e6181fee0e
14 changed files with 193 additions and 149 deletions

View File

@ -17,7 +17,7 @@ The table below will list all configuration parameters.
| `max_open_trades` | 3 | Yes | Number of trades open your bot will have. | `max_open_trades` | 3 | Yes | Number of trades open your bot will have.
| `stake_currency` | BTC | Yes | Crypto-currency used for trading. | `stake_currency` | BTC | Yes | Crypto-currency used for trading.
| `stake_amount` | 0.05 | Yes | Amount of crypto-currency your bot will use for each trade. Per default, the bot will use (0.05 BTC x 3) = 0.15 BTC in total will be always engaged. | `stake_amount` | 0.05 | Yes | Amount of crypto-currency your bot will use for each trade. Per default, the bot will use (0.05 BTC x 3) = 0.15 BTC in total will be always engaged.
| `ticker_interval` | [1, 5, 30, 60, 1440] | No | The ticker interval to use (1min, 5 min, 30 min, 1 hour or 1 day). Defaut is 5 minutes | `ticker_interval` | 5m | No | The ticker interval to use (1m, 5m, 30m, 1h or 1d). Default is 5 minutes (5m).
| `fiat_display_currency` | USD | Yes | Fiat currency used to show your profits. More information below. | `fiat_display_currency` | USD | Yes | Fiat currency used to show your profits. More information below.
| `dry_run` | true | Yes | Define if the bot must be in Dry-run or production mode. | `dry_run` | true | Yes | Define if the bot must be in Dry-run or production mode.
| `minimal_roi` | See below | No | Set the threshold in percent the bot will use to sell a trade. More information below. If set, this parameter will override `minimal_roi` from your strategy file. | `minimal_roi` | See below | No | Set the threshold in percent the bot will use to sell a trade. More information below. If set, this parameter will override `minimal_roi` from your strategy file.

View File

@ -554,7 +554,7 @@ def main(sysargv=sys.argv[1:]) -> int:
_process, _process,
min_secs=_CONF['internals'].get('process_throttle_secs', 10), min_secs=_CONF['internals'].get('process_throttle_secs', 10),
nb_assets=args.dynamic_whitelist, nb_assets=args.dynamic_whitelist,
interval=int(_CONF.get('ticker_interval', 5)) interval=_CONF.get('ticker_interval', '5m')
) )
old_state = new_state old_state = new_state
except KeyboardInterrupt: except KeyboardInterrupt:

View File

@ -60,6 +60,10 @@ def common_datearray(dfs):
return np.sort(arr, axis=0) return np.sort(arr, axis=0)
def ticker_interval_to_minutes(interval) -> int:
return TICKER_INTERVAL_MINUTES[interval]
def file_dump_json(filename, data) -> None: def file_dump_json(filename, data) -> None:
with open(filename, 'w') as fp: with open(filename, 'w') as fp:
json.dump(data, fp) json.dump(data, fp)
@ -216,11 +220,10 @@ def backtesting_options(parser: argparse.ArgumentParser) -> None:
) )
parser.add_argument( parser.add_argument(
'-i', '--ticker-interval', '-i', '--ticker-interval',
help='specify ticker interval in minutes (1, 5, 30, 60, 1440)', help='specify ticker interval (1m, 5m, 30m, 1h, 12h)',
dest='ticker_interval', dest='ticker_interval',
default=5, default='5m',
type=int, type=str
metavar='INT',
) )
parser.add_argument( parser.add_argument(
'--realistic-simulation', '--realistic-simulation',
@ -330,6 +333,20 @@ def build_subcommands(parser: argparse.ArgumentParser) -> None:
hyperopt_options(hyperopt_cmd) hyperopt_options(hyperopt_cmd)
TICKER_INTERVAL_MINUTES = {
'1m': 1,
'5m': 5,
'15m': 15,
'30m': 30,
'1h': 60,
'2h': 120,
'4h': 240,
'6h': 360,
'12h': 720,
'1d': 1440,
'1w': 10080,
}
# Required json-schema for user specified config # Required json-schema for user specified config
CONF_SCHEMA = { CONF_SCHEMA = {
'type': 'object', 'type': 'object',

View File

@ -49,7 +49,7 @@ def generate_text_table(
len(result.index), len(result.index),
result.profit_percent.mean() * 100.0, result.profit_percent.mean() * 100.0,
result.profit_BTC.sum(), result.profit_BTC.sum(),
result.duration.mean() * ticker_interval, result.duration.mean() * misc.ticker_interval_to_minutes(ticker_interval),
len(result[result.profit_BTC > 0]), len(result[result.profit_BTC > 0]),
len(result[result.profit_BTC < 0]) len(result[result.profit_BTC < 0])
]) ])
@ -60,7 +60,7 @@ def generate_text_table(
len(results.index), len(results.index),
results.profit_percent.mean() * 100.0, results.profit_percent.mean() * 100.0,
results.profit_BTC.sum(), results.profit_BTC.sum(),
results.duration.mean() * ticker_interval, results.duration.mean() * misc.ticker_interval_to_minutes(ticker_interval),
len(results[results.profit_BTC > 0]), len(results[results.profit_BTC > 0]),
len(results[results.profit_BTC < 0]) len(results[results.profit_BTC < 0])
]) ])

View File

@ -30,7 +30,7 @@ def default_conf():
"stake_currency": "BTC", "stake_currency": "BTC",
"stake_amount": 0.001, "stake_amount": 0.001,
"fiat_display_currency": "USD", "fiat_display_currency": "USD",
"ticker_interval": 5, "ticker_interval": "5m",
"dry_run": True, "dry_run": True,
"minimal_roi": { "minimal_roi": {
"40": 0.0, "40": 0.0,
@ -198,6 +198,36 @@ def limit_sell_order():
} }
@pytest.fixture
def ticker_history_api():
return [
[
1511686200000, # unix timestamp ms
8.794e-05, # open
8.948e-05, # high
8.794e-05, # low
8.88e-05, # close
0.0877869, # volume (in quote currency)
],
[
1511686500000,
8.88e-05,
8.942e-05,
8.88e-05,
8.893e-05,
0.05874751,
],
[
1511686800,
8.891e-05,
8.893e-05,
8.875e-05,
8.877e-05,
0.7039405
]
]
@pytest.fixture @pytest.fixture
def ticker_history(): def ticker_history():
return [ return [
@ -263,7 +293,7 @@ def ticker_history_without_bv():
@pytest.fixture @pytest.fixture
def result(): def result():
with open('freqtrade/tests/testdata/ETH_BTC-1.json') as data_file: with open('freqtrade/tests/testdata/ETH_BTC-1m.json') as data_file:
return parse_ticker_dataframe(json.load(data_file)) return parse_ticker_dataframe(json.load(data_file))

View File

@ -216,13 +216,26 @@ def test_get_ticker(default_conf, mocker):
def test_get_ticker_history(default_conf, mocker): def test_get_ticker_history(default_conf, mocker):
api_mock = MagicMock() api_mock = MagicMock()
tick = 123 tick = [
[
1511686200000, # unix timestamp ms
1, # open
2, # high
3, # low
4, # close
5, # volume (in quote currency)
]
]
api_mock.fetch_ohlcv = MagicMock(return_value=tick) api_mock.fetch_ohlcv = MagicMock(return_value=tick)
mocker.patch('freqtrade.exchange._API', api_mock) mocker.patch('freqtrade.exchange._API', api_mock)
# retrieve original ticker # retrieve original ticker
ticks = get_ticker_history('ETH/BTC', int(default_conf['ticker_interval'])) ticks = get_ticker_history('ETH/BTC', default_conf['ticker_interval'])
assert ticks == 123 assert ticks[0]['O'] == 1
assert ticks[0]['H'] == 2
assert ticks[0]['L'] == 3
assert ticks[0]['C'] == 4
assert ticks[0]['V'] == 5
# change the ticker # change the ticker
# tick = 999 # tick = 999
@ -230,7 +243,7 @@ def test_get_ticker_history(default_conf, mocker):
# mocker.patch('freqtrade.exchange._API', api_mock) # mocker.patch('freqtrade.exchange._API', api_mock)
# ensure caching will still return the original ticker # ensure caching will still return the original ticker
# ticks = get_ticker_history('ETH/BTC', int(default_conf['ticker_interval'])) # ticks = get_ticker_history('ETH/BTC', default_conf['ticker_interval'])
# assert ticks == 123 # assert ticks == 123

View File

@ -29,8 +29,8 @@ def test_generate_text_table():
'loss': [0, 0] 'loss': [0, 0]
} }
) )
print(generate_text_table({'ETH/BTC': {}}, results, 'BTC', 5)) print(generate_text_table({'ETH/BTC': {}}, results, 'BTC', '5m'))
assert generate_text_table({'ETH/BTC': {}}, results, 'BTC', 5) == ( assert generate_text_table({'ETH/BTC': {}}, results, 'BTC', '5m') == (
'pair buy count avg profit % total profit BTC avg duration profit loss\n' # noqa 'pair buy count avg profit % total profit BTC avg duration profit loss\n' # noqa
'------- ----------- -------------- ------------------ -------------- -------- ------\n' # noqa '------- ----------- -------------- ------------------ -------------- -------- ------\n' # noqa
'ETH/BTC 2 15.00 0.60000000 100.0 2 0\n' # noqa 'ETH/BTC 2 15.00 0.60000000 100.0 2 0\n' # noqa
@ -39,7 +39,7 @@ def test_generate_text_table():
def test_get_timeframe(default_strategy): def test_get_timeframe(default_strategy):
data = preprocess(optimize.load_data( data = preprocess(optimize.load_data(
None, ticker_interval=1, pairs=['UNITTEST/BTC'])) None, ticker_interval='1m', pairs=['UNITTEST/BTC']))
min_date, max_date = get_timeframe(data) min_date, max_date = get_timeframe(data)
assert min_date.isoformat() == '2017-11-04T23:02:00+00:00' assert min_date.isoformat() == '2017-11-04T23:02:00+00:00'
assert max_date.isoformat() == '2017-11-14T22:59:00+00:00' assert max_date.isoformat() == '2017-11-14T22:59:00+00:00'
@ -51,7 +51,7 @@ def test_backtest(default_strategy, default_conf, mocker):
get_fee=MagicMock(return_value=0.0025)) get_fee=MagicMock(return_value=0.0025))
exchange._API = ccxt.binance() exchange._API = ccxt.binance()
data = optimize.load_data(None, ticker_interval=5, pairs=['ETH/BTC']) data = optimize.load_data(None, ticker_interval='5m', pairs=['UNITTEST/BTC'])
data = trim_dictlist(data, -200) data = trim_dictlist(data, -200)
results = backtest({'stake_amount': default_conf['stake_amount'], results = backtest({'stake_amount': default_conf['stake_amount'],
'processed': optimize.preprocess(data), 'processed': optimize.preprocess(data),
@ -67,7 +67,7 @@ def test_backtest_1min_ticker_interval(default_strategy, default_conf, mocker):
exchange._API = ccxt.binance() exchange._API = ccxt.binance()
# Run a backtesting for an exiting 5min ticker_interval # Run a backtesting for an exiting 5min ticker_interval
data = optimize.load_data(None, ticker_interval=1, pairs=['UNITTEST/BTC']) data = optimize.load_data(None, ticker_interval='1m', pairs=['UNITTEST/BTC'])
data = trim_dictlist(data, -200) data = trim_dictlist(data, -200)
results = backtest({'stake_amount': default_conf['stake_amount'], results = backtest({'stake_amount': default_conf['stake_amount'],
'processed': optimize.preprocess(data), 'processed': optimize.preprocess(data),
@ -78,20 +78,20 @@ def test_backtest_1min_ticker_interval(default_strategy, default_conf, mocker):
def load_data_test(what): def load_data_test(what):
timerange = ((None, 'line'), None, -100) timerange = ((None, 'line'), None, -100)
data = optimize.load_data(None, ticker_interval=1, pairs=['UNITTEST/BTC'], timerange=timerange) data = optimize.load_data(None, ticker_interval='1m',
pairs=['UNITTEST/BTC'], timerange=timerange)
pair = data['UNITTEST/BTC'] pair = data['UNITTEST/BTC']
datalen = len(pair) datalen = len(pair)
# Depending on the what parameter we now adjust the # Depending on the what parameter we now adjust the
# loaded data looks: # loaded data looks:
# pair :: [{'O': 0.123, 'H': 0.123, 'L': 0.123, # pair :: [{'O': 0.123, 'H': 0.123, 'L': 0.123,
# 'C': 0.123, 'V': 123.123, # 'C': 0.123, 'V': 123.123,
# 'T': '2017-11-04T23:02:00', 'BV': 0.123}] # 'T': '2017-11-04T23:02:00.000000'}]
base = 0.001 base = 0.001
if what == 'raise': if what == 'raise':
return {'UNITTEST/BTC': return {'UNITTEST/BTC':
[{'T': pair[x]['T'], # Keep old dates [{'T': pair[x]['T'], # Keep old dates
'V': pair[x]['V'], # Keep old volume 'V': pair[x]['V'], # Keep old volume
'BV': pair[x]['BV'], # keep too
'O': x * base, # But replace O,H,L,C 'O': x * base, # But replace O,H,L,C
'H': x * base + 0.0001, 'H': x * base + 0.0001,
'L': x * base - 0.0001, 'L': x * base - 0.0001,
@ -100,7 +100,6 @@ def load_data_test(what):
return {'UNITTEST/BTC': return {'UNITTEST/BTC':
[{'T': pair[x]['T'], # Keep old dates [{'T': pair[x]['T'], # Keep old dates
'V': pair[x]['V'], # Keep old volume 'V': pair[x]['V'], # Keep old volume
'BV': pair[x]['BV'], # keep too
'O': 1 - x * base, # But replace O,H,L,C 'O': 1 - x * base, # But replace O,H,L,C
'H': 1 - x * base + 0.0001, 'H': 1 - x * base + 0.0001,
'L': 1 - x * base - 0.0001, 'L': 1 - x * base - 0.0001,
@ -110,7 +109,6 @@ def load_data_test(what):
return {'UNITTEST/BTC': return {'UNITTEST/BTC':
[{'T': pair[x]['T'], # Keep old dates [{'T': pair[x]['T'], # Keep old dates
'V': pair[x]['V'], # Keep old volume 'V': pair[x]['V'], # Keep old volume
'BV': pair[x]['BV'], # keep too
# But replace O,H,L,C # But replace O,H,L,C
'O': math.sin(x * hz) / 1000 + base, 'O': math.sin(x * hz) / 1000 + base,
'H': math.sin(x * hz) / 1000 + base + 0.0001, 'H': math.sin(x * hz) / 1000 + base + 0.0001,
@ -131,23 +129,6 @@ def simple_backtest(config, contour, num_results):
assert len(results) == num_results assert len(results) == num_results
# Test backtest on offline data
# loaded by freqdata/optimize/__init__.py::load_data()
def test_backtest2(default_conf, mocker, default_strategy):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch.multiple('freqtrade.optimize.backtesting.exchange',
get_fee=MagicMock(return_value=0.0025))
data = optimize.load_data(None, ticker_interval=5, pairs=['ETH/BTC'])
data = trim_dictlist(data, -200)
results = backtest({'stake_amount': default_conf['stake_amount'],
'processed': optimize.preprocess(data),
'max_open_trades': 10,
'realistic': True})
assert not results.empty
def test_processed(default_conf, mocker, default_strategy): def test_processed(default_conf, mocker, default_strategy):
mocker.patch.dict('freqtrade.main._CONF', default_conf) mocker.patch.dict('freqtrade.main._CONF', default_conf)
dict_of_tickerrows = load_data_test('raise') dict_of_tickerrows = load_data_test('raise')
@ -170,7 +151,7 @@ def test_backtest_pricecontours(default_conf, mocker, default_strategy):
def mocked_load_data(datadir, pairs=[], ticker_interval=0, refresh_pairs=False, timerange=None): def mocked_load_data(datadir, pairs=[], ticker_interval=0, refresh_pairs=False, timerange=None):
tickerdata = optimize.load_tickerdata_file(datadir, 'UNITTEST/BTC', 1, timerange=timerange) tickerdata = optimize.load_tickerdata_file(datadir, 'UNITTEST/BTC', '1m', timerange=timerange)
pairdata = {'UNITTEST/BTC': tickerdata} pairdata = {'UNITTEST/BTC': tickerdata}
return pairdata return pairdata
@ -182,7 +163,7 @@ def test_backtest_start(default_conf, mocker, caplog):
mocker.patch.multiple('freqtrade.optimize', mocker.patch.multiple('freqtrade.optimize',
load_data=mocked_load_data) load_data=mocked_load_data)
args = MagicMock() args = MagicMock()
args.ticker_interval = 1 args.ticker_interval = '1m'
args.level = 10 args.level = 10
args.live = False args.live = False
args.datadir = None args.datadir = None

View File

@ -6,8 +6,9 @@ import logging
import ccxt import ccxt
import uuid import uuid
from shutil import copyfile from shutil import copyfile
from freqtrade.strategy.strategy import Strategy
from freqtrade import exchange, optimize from freqtrade import exchange, optimize
from freqtrade.optimize.__init__ import make_testdata_path, download_pairs,\ from freqtrade.optimize.__init__ import make_testdata_path, download_pairs, \
download_backtesting_testdata, load_tickerdata_file, trim_tickerlist, file_dump_json download_backtesting_testdata, load_tickerdata_file, trim_tickerlist, file_dump_json
# Change this if modifying UNITTEST/BTC testdatafile # Change this if modifying UNITTEST/BTC testdatafile
@ -53,11 +54,11 @@ def test_load_data_30min_ticker(default_conf, ticker_history, mocker, caplog):
file = 'freqtrade/tests/testdata/UNITTEST_BTC-30m.json' file = 'freqtrade/tests/testdata/UNITTEST_BTC-30m.json'
_backup_file(file, copy_file=True) _backup_file(file, copy_file=True)
optimize.load_data(None, pairs=['UNITTEST/BTC'], ticker_interval=30) optimize.load_data(None, pairs=['UNITTEST/BTC'], ticker_interval='30m')
assert os.path.isfile(file) is True assert os.path.isfile(file) is True
assert ('freqtrade.optimize', assert ('freqtrade.optimize',
logging.INFO, logging.INFO,
'Download the pair: "ETH/BTC", Interval: 30 min') not in caplog.record_tuples 'Downloading the pair: "ETH/BTC", Interval: 30 min') not in caplog.record_tuples
_clean_test_file(file) _clean_test_file(file)
@ -67,13 +68,13 @@ def test_load_data_5min_ticker(default_conf, ticker_history, mocker, caplog):
exchange._API = ccxt.binance({'key': '', 'secret': ''}) exchange._API = ccxt.binance({'key': '', 'secret': ''})
file = 'freqtrade/tests/testdata/ETH_BTC-5.json' file = 'freqtrade/tests/testdata/ETH_BTC-5m.json'
_backup_file(file, copy_file=True) _backup_file(file, copy_file=True)
optimize.load_data(None, pairs=['ETH/BTC'], ticker_interval=5) optimize.load_data(None, pairs=['ETH/BTC'], ticker_interval='5m')
assert os.path.isfile(file) is True assert os.path.isfile(file) is True
assert ('freqtrade.optimize', assert ('freqtrade.optimize',
logging.INFO, logging.INFO,
'Download the pair: "ETH/BTC", Interval: 5 min') not in caplog.record_tuples 'Downloading the pair: "ETH/BTC", Interval: 5 min') not in caplog.record_tuples
_clean_test_file(file) _clean_test_file(file)
@ -83,9 +84,9 @@ def test_load_data_1min_ticker(default_conf, ticker_history, mocker, caplog):
exchange._API = ccxt.binance({'key': '', 'secret': ''}) exchange._API = ccxt.binance({'key': '', 'secret': ''})
file = 'freqtrade/tests/testdata/ETH_BTC-1.json' file = 'freqtrade/tests/testdata/ETH_BTC-1m.json'
_backup_file(file, copy_file=True) _backup_file(file, copy_file=True)
optimize.load_data(None, ticker_interval=1, pairs=['ETH/BTC']) optimize.load_data(None, ticker_interval='1m', pairs=['ETH/BTC'])
assert os.path.isfile(file) is True assert os.path.isfile(file) is True
assert ('freqtrade.optimize', assert ('freqtrade.optimize',
logging.INFO, logging.INFO,
@ -99,13 +100,13 @@ def test_load_data_with_new_pair_1min(default_conf, ticker_history, mocker, capl
exchange._API = ccxt.binance({'key': '', 'secret': ''}) exchange._API = ccxt.binance({'key': '', 'secret': ''})
file = 'freqtrade/tests/testdata/MEME_BTC-1.json' file = 'freqtrade/tests/testdata/MEME_BTC-1m.json'
_backup_file(file) _backup_file(file)
optimize.load_data(None, ticker_interval=1, pairs=['MEME/BTC']) optimize.load_data(None, ticker_interval='1m', pairs=['MEME/BTC'])
assert os.path.isfile(file) is True assert os.path.isfile(file) is True
assert ('freqtrade.optimize', assert ('freqtrade.optimize',
logging.INFO, logging.INFO,
'Download the pair: "MEME/BTC", Interval: 1 min') in caplog.record_tuples 'Downloading the pair: "MEME/BTC", Interval: 1m') in caplog.record_tuples
_clean_test_file(file) _clean_test_file(file)
@ -118,10 +119,10 @@ def test_download_pairs(default_conf, ticker_history, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf) mocker.patch.dict('freqtrade.main._CONF', default_conf)
exchange._API = ccxt.binance({'key': '', 'secret': ''}) exchange._API = ccxt.binance({'key': '', 'secret': ''})
file1_1 = 'freqtrade/tests/testdata/MEME_BTC-1.json' file1_1 = 'freqtrade/tests/testdata/MEME_BTC-1m.json'
file1_5 = 'freqtrade/tests/testdata/MEME_BTC-5.json' file1_5 = 'freqtrade/tests/testdata/MEME_BTC-5m.json'
file2_1 = 'freqtrade/tests/testdata/CFI_BTC-1.json' file2_1 = 'freqtrade/tests/testdata/CFI_BTC-1m.json'
file2_5 = 'freqtrade/tests/testdata/CFI_BTC-5.json' file2_5 = 'freqtrade/tests/testdata/CFI_BTC-5m.json'
_backup_file(file1_1) _backup_file(file1_1)
_backup_file(file1_5) _backup_file(file1_5)
@ -131,7 +132,7 @@ def test_download_pairs(default_conf, ticker_history, mocker):
assert os.path.isfile(file1_1) is False assert os.path.isfile(file1_1) is False
assert os.path.isfile(file2_1) is False assert os.path.isfile(file2_1) is False
assert download_pairs(None, pairs=['MEME/BTC', 'CFI/BTC'], ticker_interval=1) is True assert download_pairs(None, pairs=['MEME/BTC', 'CFI/BTC'], ticker_interval='1m') is True
assert os.path.isfile(file1_1) is True assert os.path.isfile(file1_1) is True
assert os.path.isfile(file2_1) is True assert os.path.isfile(file2_1) is True
@ -143,7 +144,7 @@ def test_download_pairs(default_conf, ticker_history, mocker):
assert os.path.isfile(file1_5) is False assert os.path.isfile(file1_5) is False
assert os.path.isfile(file2_5) is False assert os.path.isfile(file2_5) is False
assert download_pairs(None, pairs=['MEME/BTC', 'CFI/BTC'], ticker_interval=5) is True assert download_pairs(None, pairs=['MEME/BTC', 'CFI/BTC'], ticker_interval='5m') is True
assert os.path.isfile(file1_5) is True assert os.path.isfile(file1_5) is True
assert os.path.isfile(file2_5) is True assert os.path.isfile(file2_5) is True
@ -160,18 +161,18 @@ def test_download_pairs_exception(default_conf, ticker_history, mocker, caplog):
mocker.patch.dict('freqtrade.main._CONF', default_conf) mocker.patch.dict('freqtrade.main._CONF', default_conf)
exchange._API = ccxt.binance({'key': '', 'secret': ''}) exchange._API = ccxt.binance({'key': '', 'secret': ''})
file1_1 = 'freqtrade/tests/testdata/MEME_BTC-1.json' file1_1 = 'freqtrade/tests/testdata/MEME_BTC-1m.json'
file1_5 = 'freqtrade/tests/testdata/MEME_BTC-5.json' file1_5 = 'freqtrade/tests/testdata/MEME_BTC-5m.json'
_backup_file(file1_1) _backup_file(file1_1)
_backup_file(file1_5) _backup_file(file1_5)
download_pairs(None, pairs=['MEME/BTC'], ticker_interval=1) download_pairs(None, pairs=['MEME/BTC'], ticker_interval='1m')
# clean files freshly downloaded # clean files freshly downloaded
_clean_test_file(file1_1) _clean_test_file(file1_1)
_clean_test_file(file1_5) _clean_test_file(file1_5)
assert ('freqtrade.optimize.__init__', assert ('freqtrade.optimize.__init__',
logging.INFO, logging.INFO,
'Failed to download the pair: "MEME/BTC", Interval: 1 min') in caplog.record_tuples 'Failed to download the pair: "MEME/BTC", Interval: 1m') in caplog.record_tuples
def test_download_backtesting_testdata(default_conf, ticker_history, mocker): def test_download_backtesting_testdata(default_conf, ticker_history, mocker):
@ -180,37 +181,37 @@ def test_download_backtesting_testdata(default_conf, ticker_history, mocker):
exchange._API = ccxt.binance({'key': '', 'secret': ''}) exchange._API = ccxt.binance({'key': '', 'secret': ''})
# Download a 1 min ticker file # Download a 1 min ticker file
file1 = 'freqtrade/tests/testdata/XEL_BTC-1.json' file1 = 'freqtrade/tests/testdata/XEL_BTC-1m.json'
_backup_file(file1) _backup_file(file1)
download_backtesting_testdata(None, pair="XEL/BTC", interval=1) download_backtesting_testdata(None, pair="XEL/BTC", interval='1m')
assert os.path.isfile(file1) is True assert os.path.isfile(file1) is True
_clean_test_file(file1) _clean_test_file(file1)
# Download a 5 min ticker file # Download a 5 min ticker file
file2 = 'freqtrade/tests/testdata/STORJ_BTC-5.json' file2 = 'freqtrade/tests/testdata/STORJ_BTC-5m.json'
_backup_file(file2) _backup_file(file2)
download_backtesting_testdata(None, pair="STORJ/BTC", interval=5) download_backtesting_testdata(None, pair="STORJ/BTC", interval='5m')
assert os.path.isfile(file2) is True assert os.path.isfile(file2) is True
_clean_test_file(file2) _clean_test_file(file2)
def test_download_backtesting_testdata2(mocker): def test_download_backtesting_testdata2(mocker):
tick = [{'T': 'bar'}, {'T': 'foo'}] tick = [{'T': 'foo'}, {'T': 'bar'}] # invalid response
mocker.patch('freqtrade.misc.file_dump_json', return_value=None) mocker.patch('freqtrade.misc.file_dump_json', return_value=None)
mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=tick) mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=tick)
assert download_backtesting_testdata(None, pair="UNITEST/BTC", interval=1) assert download_backtesting_testdata(None, pair="UNITEST/BTC", interval='1m')
assert download_backtesting_testdata(None, pair="UNITEST/BTC", interval=3) assert download_backtesting_testdata(None, pair="UNITEST/BTC", interval='3m')
def test_load_tickerdata_file(): def test_load_tickerdata_file():
# 7 does not exist in either format. # 7m does not exist in either format.
assert not load_tickerdata_file(None, 'UNITTEST/BTC', 7) assert not load_tickerdata_file(None, 'UNITTEST/BTC', '7m')
# 1 exists only as a .json # 1m exists only as a .json
tickerdata = load_tickerdata_file(None, 'UNITTEST/BTC', 1) tickerdata = load_tickerdata_file(None, 'UNITTEST/BTC', '1m')
assert _BTC_UNITTEST_LENGTH == len(tickerdata) assert _BTC_UNITTEST_LENGTH == len(tickerdata)
# 8 .json is empty and will fail if it's loaded. .json.gz is a copy of 1.json # 8m.json is empty and will fail if it's loaded. 8m.json.gz is a copy of 1m.json
tickerdata = load_tickerdata_file(None, 'UNITTEST/BTC', 8) tickerdata = load_tickerdata_file(None, 'UNITTEST/BTC', '8m')
assert _BTC_UNITTEST_LENGTH == len(tickerdata) assert _BTC_UNITTEST_LENGTH == len(tickerdata)
@ -218,19 +219,22 @@ def test_init(default_conf, mocker):
conf = {'exchange': {'pair_whitelist': []}} conf = {'exchange': {'pair_whitelist': []}}
mocker.patch('freqtrade.optimize.hyperopt_optimize_conf', return_value=conf) mocker.patch('freqtrade.optimize.hyperopt_optimize_conf', return_value=conf)
assert {} == optimize.load_data('', pairs=[], refresh_pairs=True, assert {} == optimize.load_data('', pairs=[], refresh_pairs=True,
ticker_interval=int(default_conf['ticker_interval'])) ticker_interval=default_conf['ticker_interval'])
def test_tickerdata_to_dataframe(): def test_tickerdata_to_dataframe():
timerange = ((None, 'line'), None, -100) timerange = ((None, 'line'), None, -100)
tick = load_tickerdata_file(None, 'UNITTEST/BTC', 1, timerange=timerange) tick = load_tickerdata_file(None, 'UNITTEST/BTC', '1m', timerange=timerange)
tickerlist = {'UNITTEST/BTC': tick} tickerlist = {'UNITTEST/BTC': tick}
strategy = Strategy()
strategy.init({})
data = optimize.tickerdata_to_dataframe(tickerlist) data = optimize.tickerdata_to_dataframe(tickerlist)
assert len(data['UNITTEST/BTC']) == 100 assert len(data['UNITTEST/BTC']) == 100
def test_trim_tickerlist(): def test_trim_tickerlist():
with open('freqtrade/tests/testdata/ETH_BTC-1.json') as data_file: with open('freqtrade/tests/testdata/ETH_BTC-1m.json') as data_file:
ticker_list = json.load(data_file) ticker_list = json.load(data_file)
ticker_list_len = len(ticker_list) ticker_list_len = len(ticker_list)
@ -275,7 +279,6 @@ def test_trim_tickerlist():
def test_file_dump_json(): def test_file_dump_json():
file = 'freqtrade/tests/testdata/test_{id}.json'.format(id=str(uuid.uuid4())) file = 'freqtrade/tests/testdata/test_{id}.json'.format(id=str(uuid.uuid4()))
data = {'bar': 'foo'} data = {'bar': 'foo'}

View File

@ -103,7 +103,7 @@ def test_status_handle(default_conf, update, ticker, mocker):
msg_mock.reset_mock() msg_mock.reset_mock()
# Create some test data # Create some test data
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
# Trigger status while we have a fulfilled order for the open trade # Trigger status while we have a fulfilled order for the open trade
_status(bot=MagicMock(), update=update) _status(bot=MagicMock(), update=update)
@ -139,7 +139,7 @@ def test_status_table_handle(default_conf, update, ticker, mocker):
msg_mock.reset_mock() msg_mock.reset_mock()
# Create some test data # Create some test data
create_trade(15.0, int(default_conf['ticker_interval'])) create_trade(15.0, default_conf['ticker_interval'])
_status_table(bot=MagicMock(), update=update) _status_table(bot=MagicMock(), update=update)
@ -178,7 +178,7 @@ def test_profit_handle(
msg_mock.reset_mock() msg_mock.reset_mock()
# Create some test data # Create some test data
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
# Simulate fulfilled LIMIT_BUY order for trade # Simulate fulfilled LIMIT_BUY order for trade
@ -226,7 +226,7 @@ def test_forcesell_handle(default_conf, update, ticker, ticker_sell_up, mocker):
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
# Create some test data # Create some test data
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
assert trade assert trade
@ -265,7 +265,7 @@ def test_forcesell_down_handle(default_conf, update, ticker, ticker_sell_down, m
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
# Create some test data # Create some test data
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
# Decrease the price and sell it # Decrease the price and sell it
mocker.patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
@ -329,7 +329,7 @@ def test_forcesell_all_handle(default_conf, update, ticker, mocker):
# Create some test data # Create some test data
for _ in range(4): for _ in range(4):
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
rpc_mock.reset_mock() rpc_mock.reset_mock()
update.message.text = '/forcesell all' update.message.text = '/forcesell all'
@ -395,7 +395,7 @@ def test_performance_handle(
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
# Create some test data # Create some test data
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
assert trade assert trade
@ -433,7 +433,7 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, limit_sell_
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
# Create some test data # Create some test data
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
assert trade assert trade
@ -460,8 +460,8 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, limit_sell_
# Reset msg_mock # Reset msg_mock
msg_mock.reset_mock() msg_mock.reset_mock()
# Add two other trades # Add two other trades
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trades = Trade.query.all() trades = Trade.query.all()
for trade in trades: for trade in trades:
@ -534,7 +534,7 @@ def test_count_handle(default_conf, update, ticker, mocker):
update_state(State.RUNNING) update_state(State.RUNNING)
# Create some test data # Create some test data
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
msg_mock.reset_mock() msg_mock.reset_mock()
_count(bot=MagicMock(), update=update) _count(bot=MagicMock(), update=update)

View File

@ -7,7 +7,7 @@ from freqtrade.analyze import parse_ticker_dataframe
@pytest.fixture @pytest.fixture
def result(): def result():
with open('freqtrade/tests/testdata/ETH_BTC-1.json') as data_file: with open('freqtrade/tests/testdata/ETH_BTC-1m.json') as data_file:
return parse_ticker_dataframe(json.load(data_file)) return parse_ticker_dataframe(json.load(data_file))

View File

@ -44,13 +44,13 @@ def test_returns_latest_buy_signal(mocker):
'freqtrade.analyze.analyze_ticker', 'freqtrade.analyze.analyze_ticker',
return_value=DataFrame([{'buy': 1, 'sell': 0, 'date': arrow.utcnow()}]) return_value=DataFrame([{'buy': 1, 'sell': 0, 'date': arrow.utcnow()}])
) )
assert get_signal('ETH/BTC', 5) == (True, False) assert get_signal('ETH/BTC', '5m') == (True, False)
mocker.patch( mocker.patch(
'freqtrade.analyze.analyze_ticker', 'freqtrade.analyze.analyze_ticker',
return_value=DataFrame([{'buy': 0, 'sell': 1, 'date': arrow.utcnow()}]) return_value=DataFrame([{'buy': 0, 'sell': 1, 'date': arrow.utcnow()}])
) )
assert get_signal('ETH/BTC', 5) == (False, True) assert get_signal('ETH/BTC', '5m') == (False, True)
def test_returns_latest_sell_signal(mocker): def test_returns_latest_sell_signal(mocker):
@ -59,18 +59,18 @@ def test_returns_latest_sell_signal(mocker):
'freqtrade.analyze.analyze_ticker', 'freqtrade.analyze.analyze_ticker',
return_value=DataFrame([{'sell': 1, 'buy': 0, 'date': arrow.utcnow()}]) return_value=DataFrame([{'sell': 1, 'buy': 0, 'date': arrow.utcnow()}])
) )
assert get_signal('ETH/BTC', 5) == (False, True) assert get_signal('ETH/BTC', '5m') == (False, True)
mocker.patch( mocker.patch(
'freqtrade.analyze.analyze_ticker', 'freqtrade.analyze.analyze_ticker',
return_value=DataFrame([{'sell': 0, 'buy': 1, 'date': arrow.utcnow()}]) return_value=DataFrame([{'sell': 0, 'buy': 1, 'date': arrow.utcnow()}])
) )
assert get_signal('ETH/BTC', 5) == (True, False) assert get_signal('ETH/BTC', '5m') == (True, False)
def test_get_signal_empty(default_conf, mocker, caplog): def test_get_signal_empty(default_conf, mocker, caplog):
mocker.patch('freqtrade.analyze.get_ticker_history', return_value=None) mocker.patch('freqtrade.analyze.get_ticker_history', return_value=None)
assert (False, False) == get_signal('foo', int(default_conf['ticker_interval'])) assert (False, False) == get_signal('foo', default_conf['ticker_interval'])
assert tt.log_has('Empty ticker history for pair foo', assert tt.log_has('Empty ticker history for pair foo',
caplog.record_tuples) caplog.record_tuples)
@ -79,7 +79,7 @@ def test_get_signal_exception_valueerror(default_conf, mocker, caplog):
mocker.patch('freqtrade.analyze.get_ticker_history', return_value=1) mocker.patch('freqtrade.analyze.get_ticker_history', return_value=1)
mocker.patch('freqtrade.analyze.analyze_ticker', mocker.patch('freqtrade.analyze.analyze_ticker',
side_effect=ValueError('xyz')) side_effect=ValueError('xyz'))
assert (False, False) == get_signal('foo', int(default_conf['ticker_interval'])) assert (False, False) == get_signal('foo', default_conf['ticker_interval'])
assert tt.log_has('Unable to analyze ticker for pair foo: xyz', assert tt.log_has('Unable to analyze ticker for pair foo: xyz',
caplog.record_tuples) caplog.record_tuples)
@ -87,7 +87,7 @@ def test_get_signal_exception_valueerror(default_conf, mocker, caplog):
def test_get_signal_empty_dataframe(default_conf, mocker, caplog): def test_get_signal_empty_dataframe(default_conf, mocker, caplog):
mocker.patch('freqtrade.analyze.get_ticker_history', return_value=1) mocker.patch('freqtrade.analyze.get_ticker_history', return_value=1)
mocker.patch('freqtrade.analyze.analyze_ticker', return_value=DataFrame([])) mocker.patch('freqtrade.analyze.analyze_ticker', return_value=DataFrame([]))
assert (False, False) == get_signal('xyz', int(default_conf['ticker_interval'])) assert (False, False) == get_signal('xyz', default_conf['ticker_interval'])
assert tt.log_has('Empty dataframe for pair xyz', assert tt.log_has('Empty dataframe for pair xyz',
caplog.record_tuples) caplog.record_tuples)
@ -98,7 +98,7 @@ def test_get_signal_old_dataframe(default_conf, mocker, caplog):
oldtime = arrow.utcnow() - datetime.timedelta(minutes=11) oldtime = arrow.utcnow() - datetime.timedelta(minutes=11)
ticks = DataFrame([{'buy': 1, 'date': oldtime}]) ticks = DataFrame([{'buy': 1, 'date': oldtime}])
mocker.patch('freqtrade.analyze.analyze_ticker', return_value=DataFrame(ticks)) mocker.patch('freqtrade.analyze.analyze_ticker', return_value=DataFrame(ticks))
assert (False, False) == get_signal('xyz', int(default_conf['ticker_interval'])) assert (False, False) == get_signal('xyz', default_conf['ticker_interval'])
assert tt.log_has('Too old dataframe for pair xyz', assert tt.log_has('Too old dataframe for pair xyz',
caplog.record_tuples) caplog.record_tuples)
@ -108,7 +108,7 @@ def test_get_signal_handles_exceptions(mocker):
mocker.patch('freqtrade.analyze.analyze_ticker', mocker.patch('freqtrade.analyze.analyze_ticker',
side_effect=Exception('invalid ticker history ')) side_effect=Exception('invalid ticker history '))
assert get_signal('ETH/BTC', 5) == (False, False) assert get_signal('ETH/BTC', '5m') == (False, False)
def test_parse_ticker_dataframe(ticker_history, ticker_history_without_bv): def test_parse_ticker_dataframe(ticker_history, ticker_history_without_bv):

View File

@ -8,7 +8,7 @@ _pairs = ['ETH/BTC']
def load_dataframe_pair(pairs): def load_dataframe_pair(pairs):
ld = freqtrade.optimize.load_data(None, ticker_interval=5, pairs=pairs) ld = freqtrade.optimize.load_data(None, ticker_interval='5m', pairs=pairs)
assert isinstance(ld, dict) assert isinstance(ld, dict)
assert isinstance(pairs[0], str) assert isinstance(pairs[0], str)
dataframe = ld[pairs[0]] dataframe = ld[pairs[0]]

View File

@ -31,7 +31,7 @@ def test_parse_args_backtesting(mocker):
assert call_args.loglevel == 20 assert call_args.loglevel == 20
assert call_args.subparser == 'backtesting' assert call_args.subparser == 'backtesting'
assert call_args.func is not None assert call_args.func is not None
assert call_args.ticker_interval == 5 assert call_args.ticker_interval == '5m'
def test_main_start_hyperopt(mocker): def test_main_start_hyperopt(mocker):
@ -49,9 +49,9 @@ def test_main_start_hyperopt(mocker):
def test_process_maybe_execute_buy(default_conf, mocker): def test_process_maybe_execute_buy(default_conf, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf) mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.create_trade', return_value=True) mocker.patch('freqtrade.main.create_trade', return_value=True)
assert main.process_maybe_execute_buy(int(default_conf['ticker_interval'])) assert main.process_maybe_execute_buy(default_conf['ticker_interval'])
mocker.patch('freqtrade.main.create_trade', return_value=False) mocker.patch('freqtrade.main.create_trade', return_value=False)
assert not main.process_maybe_execute_buy(int(default_conf['ticker_interval'])) assert not main.process_maybe_execute_buy(default_conf['ticker_interval'])
def test_process_maybe_execute_sell(default_conf, mocker): def test_process_maybe_execute_sell(default_conf, mocker):
@ -60,17 +60,17 @@ def test_process_maybe_execute_sell(default_conf, mocker):
mocker.patch('freqtrade.exchange.get_order', return_value=1) mocker.patch('freqtrade.exchange.get_order', return_value=1)
trade = MagicMock() trade = MagicMock()
trade.open_order_id = '123' trade.open_order_id = '123'
assert not main.process_maybe_execute_sell(trade, int(default_conf['ticker_interval'])) assert not main.process_maybe_execute_sell(trade, default_conf['ticker_interval'])
trade.is_open = True trade.is_open = True
trade.open_order_id = None trade.open_order_id = None
# Assert we call handle_trade() if trade is feasible for execution # Assert we call handle_trade() if trade is feasible for execution
assert main.process_maybe_execute_sell(trade, int(default_conf['ticker_interval'])) assert main.process_maybe_execute_sell(trade, default_conf['ticker_interval'])
def test_process_maybe_execute_buy_exception(default_conf, mocker, caplog): def test_process_maybe_execute_buy_exception(default_conf, mocker, caplog):
mocker.patch.dict('freqtrade.main._CONF', default_conf) mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.create_trade', MagicMock(side_effect=DependencyException)) mocker.patch('freqtrade.main.create_trade', MagicMock(side_effect=DependencyException))
main.process_maybe_execute_buy(int(default_conf['ticker_interval'])) main.process_maybe_execute_buy(default_conf['ticker_interval'])
tt.log_has('Unable to create trade:', caplog.record_tuples) tt.log_has('Unable to create trade:', caplog.record_tuples)
@ -88,7 +88,7 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order, health, m
trades = Trade.query.filter(Trade.is_open.is_(True)).all() trades = Trade.query.filter(Trade.is_open.is_(True)).all()
assert not trades assert not trades
result = _process(interval=int(default_conf['ticker_interval'])) result = _process(interval=default_conf['ticker_interval'])
assert result is True assert result is True
trades = Trade.query.filter(Trade.is_open.is_(True)).all() trades = Trade.query.filter(Trade.is_open.is_(True)).all()
@ -113,7 +113,7 @@ def test_process_exchange_failures(default_conf, ticker, health, mocker):
get_ticker=ticker, get_ticker=ticker,
buy=MagicMock(side_effect=requests.exceptions.RequestException)) buy=MagicMock(side_effect=requests.exceptions.RequestException))
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
result = _process(interval=int(default_conf['ticker_interval'])) result = _process(interval=default_conf['ticker_interval'])
assert result is False assert result is False
assert sleep_mock.has_calls() assert sleep_mock.has_calls()
@ -130,7 +130,7 @@ def test_process_operational_exception(default_conf, ticker, health, mocker):
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
assert get_state() == State.RUNNING assert get_state() == State.RUNNING
result = _process(interval=int(default_conf['ticker_interval'])) result = _process(interval=default_conf['ticker_interval'])
assert result is False assert result is False
assert get_state() == State.STOPPED assert get_state() == State.STOPPED
assert 'OperationalException' in msg_mock.call_args_list[-1][0][0] assert 'OperationalException' in msg_mock.call_args_list[-1][0][0]
@ -149,12 +149,12 @@ def test_process_trade_handling(default_conf, ticker, limit_buy_order, health, m
trades = Trade.query.filter(Trade.is_open.is_(True)).all() trades = Trade.query.filter(Trade.is_open.is_(True)).all()
assert not trades assert not trades
result = _process(interval=int(default_conf['ticker_interval'])) result = _process(interval=default_conf['ticker_interval'])
assert result is True assert result is True
trades = Trade.query.filter(Trade.is_open.is_(True)).all() trades = Trade.query.filter(Trade.is_open.is_(True)).all()
assert len(trades) == 1 assert len(trades) == 1
result = _process(interval=int(default_conf['ticker_interval'])) result = _process(interval=default_conf['ticker_interval'])
assert result is False assert result is False
@ -170,7 +170,7 @@ def test_create_trade(default_conf, ticker, limit_buy_order, mocker):
whitelist = copy.deepcopy(default_conf['exchange']['pair_whitelist']) whitelist = copy.deepcopy(default_conf['exchange']['pair_whitelist'])
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
assert trade is not None assert trade is not None
@ -200,7 +200,7 @@ def test_create_trade_minimal_amount(default_conf, ticker, mocker):
get_ticker=ticker) get_ticker=ticker)
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
min_stake_amount = 0.0005 min_stake_amount = 0.0005
create_trade(min_stake_amount, int(default_conf['ticker_interval'])) create_trade(min_stake_amount, default_conf['ticker_interval'])
rate, amount = buy_mock.call_args[0][1], buy_mock.call_args[0][2] rate, amount = buy_mock.call_args[0][1], buy_mock.call_args[0][2]
assert rate * amount >= min_stake_amount assert rate * amount >= min_stake_amount
@ -215,7 +215,7 @@ def test_create_trade_no_stake_amount(default_conf, ticker, mocker):
buy=MagicMock(return_value='mocked_limit_buy'), buy=MagicMock(return_value='mocked_limit_buy'),
get_balance=MagicMock(return_value=default_conf['stake_amount'] * 0.5)) get_balance=MagicMock(return_value=default_conf['stake_amount'] * 0.5))
with pytest.raises(DependencyException, match=r'.*stake amount.*'): with pytest.raises(DependencyException, match=r'.*stake amount.*'):
create_trade(default_conf['stake_amount'], int(default_conf['ticker_interval'])) create_trade(default_conf['stake_amount'], default_conf['ticker_interval'])
def test_create_trade_no_pairs(default_conf, ticker, mocker): def test_create_trade_no_pairs(default_conf, ticker, mocker):
@ -231,7 +231,7 @@ def test_create_trade_no_pairs(default_conf, ticker, mocker):
conf = copy.deepcopy(default_conf) conf = copy.deepcopy(default_conf)
conf['exchange']['pair_whitelist'] = [] conf['exchange']['pair_whitelist'] = []
mocker.patch.dict('freqtrade.main._CONF', conf) mocker.patch.dict('freqtrade.main._CONF', conf)
create_trade(default_conf['stake_amount'], int(default_conf['ticker_interval'])) create_trade(default_conf['stake_amount'], default_conf['ticker_interval'])
def test_create_trade_no_pairs_after_blacklist(default_conf, ticker, mocker): def test_create_trade_no_pairs_after_blacklist(default_conf, ticker, mocker):
@ -248,7 +248,7 @@ def test_create_trade_no_pairs_after_blacklist(default_conf, ticker, mocker):
conf['exchange']['pair_whitelist'] = ["ETH/BTC"] conf['exchange']['pair_whitelist'] = ["ETH/BTC"]
conf['exchange']['pair_blacklist'] = ["ETH/BTC"] conf['exchange']['pair_blacklist'] = ["ETH/BTC"]
mocker.patch.dict('freqtrade.main._CONF', conf) mocker.patch.dict('freqtrade.main._CONF', conf)
create_trade(default_conf['stake_amount'], int(default_conf['ticker_interval'])) create_trade(default_conf['stake_amount'], default_conf['ticker_interval'])
def test_create_trade_no_signal(default_conf, mocker): def test_create_trade_no_signal(default_conf, mocker):
@ -262,7 +262,7 @@ def test_create_trade_no_signal(default_conf, mocker):
stake_amount = 10 stake_amount = 10
Trade.query = MagicMock() Trade.query = MagicMock()
Trade.query.filter = MagicMock() Trade.query.filter = MagicMock()
assert not create_trade(stake_amount, int(default_conf['ticker_interval'])) assert not create_trade(stake_amount, default_conf['ticker_interval'])
def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker): def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker):
@ -283,7 +283,7 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker):
ticker=MagicMock(return_value={'price_usd': 15000.0}), ticker=MagicMock(return_value={'price_usd': 15000.0}),
_cache_symbols=MagicMock(return_value={'BTC': 1})) _cache_symbols=MagicMock(return_value={'BTC': 1}))
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
assert trade assert trade
@ -292,7 +292,7 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker):
assert trade.is_open is True assert trade.is_open is True
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True)) mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True))
assert handle_trade(trade, int(default_conf['ticker_interval'])) is True assert handle_trade(trade, default_conf['ticker_interval']) is True
assert trade.open_order_id == 'mocked_limit_sell' assert trade.open_order_id == 'mocked_limit_sell'
# Simulate fulfilled LIMIT_SELL order for trade # Simulate fulfilled LIMIT_SELL order for trade
@ -317,7 +317,7 @@ def test_handle_overlpapping_signals(default_conf, ticker, mocker):
mocker.patch('freqtrade.main.min_roi_reached', return_value=False) mocker.patch('freqtrade.main.min_roi_reached', return_value=False)
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
# Buy and Sell triggering, so doing nothing ... # Buy and Sell triggering, so doing nothing ...
trades = Trade.query.all() trades = Trade.query.all()
@ -326,7 +326,7 @@ def test_handle_overlpapping_signals(default_conf, ticker, mocker):
# Buy is triggering, so buying ... # Buy is triggering, so buying ...
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (True, False)) mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (True, False))
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trades = Trade.query.all() trades = Trade.query.all()
nb_trades = len(trades) nb_trades = len(trades)
assert nb_trades == 1 assert nb_trades == 1
@ -334,7 +334,7 @@ def test_handle_overlpapping_signals(default_conf, ticker, mocker):
# Buy and Sell are not triggering, so doing nothing ... # Buy and Sell are not triggering, so doing nothing ...
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, False)) mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, False))
assert handle_trade(trades[0], int(default_conf['ticker_interval'])) is False assert handle_trade(trades[0], default_conf['ticker_interval']) is False
trades = Trade.query.all() trades = Trade.query.all()
nb_trades = len(trades) nb_trades = len(trades)
assert nb_trades == 1 assert nb_trades == 1
@ -342,7 +342,7 @@ def test_handle_overlpapping_signals(default_conf, ticker, mocker):
# Buy and Sell are triggering, so doing nothing ... # Buy and Sell are triggering, so doing nothing ...
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (True, True)) mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (True, True))
assert handle_trade(trades[0], int(default_conf['ticker_interval'])) is False assert handle_trade(trades[0], default_conf['ticker_interval']) is False
trades = Trade.query.all() trades = Trade.query.all()
nb_trades = len(trades) nb_trades = len(trades)
assert nb_trades == 1 assert nb_trades == 1
@ -351,7 +351,7 @@ def test_handle_overlpapping_signals(default_conf, ticker, mocker):
# Sell is triggering, guess what : we are Selling! # Sell is triggering, guess what : we are Selling!
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True)) mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True))
trades = Trade.query.all() trades = Trade.query.all()
assert handle_trade(trades[0], int(default_conf['ticker_interval'])) is True assert handle_trade(trades[0], default_conf['ticker_interval']) is True
def test_handle_trade_roi(default_conf, ticker, mocker, caplog): def test_handle_trade_roi(default_conf, ticker, mocker, caplog):
@ -367,7 +367,7 @@ def test_handle_trade_roi(default_conf, ticker, mocker, caplog):
mocker.patch('freqtrade.main.min_roi_reached', return_value=True) mocker.patch('freqtrade.main.min_roi_reached', return_value=True)
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
trade.is_open = True trade.is_open = True
@ -378,11 +378,11 @@ def test_handle_trade_roi(default_conf, ticker, mocker, caplog):
# executing # executing
# if ROI is reached we must sell # if ROI is reached we must sell
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True)) mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True))
assert handle_trade(trade, interval=int(default_conf['ticker_interval'])) assert handle_trade(trade, interval=default_conf['ticker_interval'])
assert ('freqtrade', logging.DEBUG, 'Executing sell due to ROI ...') in caplog.record_tuples 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 # 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: (False, True)) mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True))
assert handle_trade(trade, interval=int(default_conf['ticker_interval'])) assert handle_trade(trade, interval=default_conf['ticker_interval'])
assert ('freqtrade', logging.DEBUG, 'Executing sell due to ROI ...') in caplog.record_tuples assert ('freqtrade', logging.DEBUG, 'Executing sell due to ROI ...') in caplog.record_tuples
@ -399,16 +399,16 @@ def test_handle_trade_experimental(default_conf, ticker, mocker, caplog):
mocker.patch('freqtrade.main.min_roi_reached', return_value=False) mocker.patch('freqtrade.main.min_roi_reached', return_value=False)
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
trade.is_open = True trade.is_open = True
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, False)) mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, False))
value_returned = handle_trade(trade, int(default_conf['ticker_interval'])) value_returned = handle_trade(trade, default_conf['ticker_interval'])
assert value_returned is False assert value_returned is False
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True)) mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True))
assert handle_trade(trade, int(default_conf['ticker_interval'])) assert handle_trade(trade, default_conf['ticker_interval'])
s = 'Executing sell due to sell signal ...' s = 'Executing sell due to sell signal ...'
assert ('freqtrade', logging.DEBUG, s) in caplog.record_tuples assert ('freqtrade', logging.DEBUG, s) in caplog.record_tuples
@ -424,7 +424,7 @@ def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, mo
# Create trade and sell it # Create trade and sell it
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
assert trade assert trade
@ -434,7 +434,7 @@ def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, mo
assert trade.is_open is False assert trade.is_open is False
with pytest.raises(ValueError, match=r'.*closed trade.*'): with pytest.raises(ValueError, match=r'.*closed trade.*'):
handle_trade(trade, int(default_conf['ticker_interval'])) handle_trade(trade, default_conf['ticker_interval'])
def test_check_handle_timedout_buy(default_conf, ticker, limit_buy_order_old, mocker): def test_check_handle_timedout_buy(default_conf, ticker, limit_buy_order_old, mocker):
@ -600,7 +600,7 @@ def test_execute_sell_up(default_conf, ticker, ticker_sell_up, mocker):
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
# Create some test data # Create some test data
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
assert trade assert trade
@ -640,7 +640,7 @@ def test_execute_sell_down(default_conf, ticker, ticker_sell_down, mocker):
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
# Create some test data # Create some test data
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
assert trade assert trade
@ -673,7 +673,7 @@ def test_execute_sell_without_conf_sell_down(default_conf, ticker, ticker_sell_d
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
# Create some test data # Create some test data
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
assert trade assert trade
@ -706,7 +706,7 @@ def test_execute_sell_without_conf_sell_up(default_conf, ticker, ticker_sell_up,
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
# Create some test data # Create some test data
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
assert trade assert trade
@ -750,12 +750,12 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, mocker):
buy=MagicMock(return_value='mocked_limit_buy')) buy=MagicMock(return_value='mocked_limit_buy'))
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
trade.update(limit_buy_order) trade.update(limit_buy_order)
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True)) mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True))
assert handle_trade(trade, int(default_conf['ticker_interval'])) is True assert handle_trade(trade, default_conf['ticker_interval']) is True
def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, mocker): def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, mocker):
@ -779,12 +779,12 @@ def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, mocker):
buy=MagicMock(return_value='mocked_limit_buy')) buy=MagicMock(return_value='mocked_limit_buy'))
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
trade.update(limit_buy_order) trade.update(limit_buy_order)
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True)) mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True))
assert handle_trade(trade, int(default_conf['ticker_interval'])) is True assert handle_trade(trade, default_conf['ticker_interval']) is True
def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, mocker): def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, mocker):
@ -808,12 +808,12 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, mocker):
buy=MagicMock(return_value='mocked_limit_buy')) buy=MagicMock(return_value='mocked_limit_buy'))
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
trade.update(limit_buy_order) trade.update(limit_buy_order)
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True)) mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True))
assert handle_trade(trade, int(default_conf['ticker_interval'])) is False assert handle_trade(trade, default_conf['ticker_interval']) is False
def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, mocker): def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, mocker):
@ -837,9 +837,9 @@ def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, mocker):
buy=MagicMock(return_value='mocked_limit_buy')) buy=MagicMock(return_value='mocked_limit_buy'))
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
create_trade(0.001, int(default_conf['ticker_interval'])) create_trade(0.001, default_conf['ticker_interval'])
trade = Trade.query.first() trade = Trade.query.first()
trade.update(limit_buy_order) trade.update(limit_buy_order)
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True)) mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (False, True))
assert handle_trade(trade, int(default_conf['ticker_interval'])) is True assert handle_trade(trade, default_conf['ticker_interval']) is True

View File

@ -113,7 +113,7 @@ def test_parse_args_backtesting_custom():
'-c', 'test_conf.json', '-c', 'test_conf.json',
'backtesting', 'backtesting',
'--live', '--live',
'--ticker-interval', '1', '--ticker-interval', '1m',
'--refresh-pairs-cached'] '--refresh-pairs-cached']
call_args = parse_args(args, '') call_args = parse_args(args, '')
assert call_args.config == 'test_conf.json' assert call_args.config == 'test_conf.json'
@ -121,7 +121,7 @@ def test_parse_args_backtesting_custom():
assert call_args.loglevel == 20 assert call_args.loglevel == 20
assert call_args.subparser == 'backtesting' assert call_args.subparser == 'backtesting'
assert call_args.func is not None assert call_args.func is not None
assert call_args.ticker_interval == 1 assert call_args.ticker_interval == '1m'
assert call_args.refresh_pairs is True assert call_args.refresh_pairs is True