Merge branch 'develop' into lock_pairs

This commit is contained in:
Matthias
2019-08-15 06:56:39 +02:00
34 changed files with 611 additions and 278 deletions

View File

@@ -0,0 +1,133 @@
{
/* Single-line C-style comment */
"max_open_trades": 3,
/*
* Multi-line C-style comment
*/
"stake_currency": "BTC",
"stake_amount": 0.05,
"fiat_display_currency": "USD", // C++-style comment
"amount_reserve_percent" : 0.05, // And more, tabs before this comment
"dry_run": false,
"ticker_interval": "5m",
"trailing_stop": false,
"trailing_stop_positive": 0.005,
"trailing_stop_positive_offset": 0.0051,
"trailing_only_offset_is_reached": false,
"minimal_roi": {
"40": 0.0,
"30": 0.01,
"20": 0.02,
"0": 0.04
},
"stoploss": -0.10,
"unfilledtimeout": {
"buy": 10,
"sell": 30, // Trailing comma should also be accepted now
},
"bid_strategy": {
"use_order_book": false,
"ask_last_balance": 0.0,
"order_book_top": 1,
"check_depth_of_market": {
"enabled": false,
"bids_to_ask_delta": 1
}
},
"ask_strategy":{
"use_order_book": false,
"order_book_min": 1,
"order_book_max": 9
},
"order_types": {
"buy": "limit",
"sell": "limit",
"stoploss": "market",
"stoploss_on_exchange": false,
"stoploss_on_exchange_interval": 60
},
"order_time_in_force": {
"buy": "gtc",
"sell": "gtc"
},
"pairlist": {
"method": "VolumePairList",
"config": {
"number_assets": 20,
"sort_key": "quoteVolume",
"precision_filter": false
}
},
"exchange": {
"name": "bittrex",
"sandbox": false,
"key": "your_exchange_key",
"secret": "your_exchange_secret",
"password": "",
"ccxt_config": {"enableRateLimit": true},
"ccxt_async_config": {
"enableRateLimit": false,
"rateLimit": 500,
"aiohttp_trust_env": false
},
"pair_whitelist": [
"ETH/BTC",
"LTC/BTC",
"ETC/BTC",
"DASH/BTC",
"ZEC/BTC",
"XLM/BTC",
"NXT/BTC",
"POWR/BTC",
"ADA/BTC",
"XMR/BTC"
],
"pair_blacklist": [
"DOGE/BTC"
],
"outdated_offset": 5,
"markets_refresh_interval": 60
},
"edge": {
"enabled": false,
"process_throttle_secs": 3600,
"calculate_since_number_of_days": 7,
"capital_available_percentage": 0.5,
"allowed_risk": 0.01,
"stoploss_range_min": -0.01,
"stoploss_range_max": -0.1,
"stoploss_range_step": -0.01,
"minimum_winrate": 0.60,
"minimum_expectancy": 0.20,
"min_trade_number": 10,
"max_trade_duration_minute": 1440,
"remove_pumps": false
},
"experimental": {
"use_sell_signal": false,
"sell_profit_only": false,
"ignore_roi_if_buy_signal": false
},
"telegram": {
// We can now comment out some settings
// "enabled": true,
"enabled": false,
"token": "your_telegram_token",
"chat_id": "your_telegram_chat_id"
},
"api_server": {
"enabled": false,
"listen_ip_address": "127.0.0.1",
"listen_port": 8080,
"username": "freqtrader",
"password": "SuperSecurePassword"
},
"db_url": "sqlite:///tradesv3.sqlite",
"initial_state": "running",
"forcebuy_enable": false,
"internals": {
"process_throttle_secs": 5
},
"strategy": "DefaultStrategy",
"strategy_path": "user_data/strategies/"
}

View File

@@ -4,7 +4,7 @@ import pytest
from arrow import Arrow
from pandas import DataFrame, to_datetime
from freqtrade.configuration import Arguments, TimeRange
from freqtrade.configuration import TimeRange
from freqtrade.data.btanalysis import (BT_DATA_COLUMNS,
combine_tickers_with_mean,
create_cum_profit,
@@ -121,7 +121,7 @@ def test_combine_tickers_with_mean():
def test_create_cum_profit():
filename = make_testdata_path(None) / "backtest-result_test.json"
bt_data = load_backtest_data(filename)
timerange = Arguments.parse_timerange("20180110-20180112")
timerange = TimeRange.parse_timerange("20180110-20180112")
df = load_pair_history(pair="POWR/BTC", ticker_interval='5m',
datadir=None, timerange=timerange)

View File

@@ -578,7 +578,8 @@ def test_generate_optimizer(mocker, default_conf) -> None:
'loss': 1.9840569076926293,
'results_explanation': ' 1 trades. Avg profit 2.31%. Total profit 0.00023300 BTC '
'( 2.31Σ%). Avg duration 100.0 mins.',
'params': optimizer_param
'params': optimizer_param,
'total_profit': 0.00023300
}
hyperopt = Hyperopt(default_conf)

View File

@@ -44,7 +44,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, markets, mocker) -> None:
with pytest.raises(RPCException, match=r'.*no active trade*'):
rpc._rpc_trade_status()
freqtradebot.create_trade()
freqtradebot.create_trades()
results = rpc._rpc_trade_status()
assert {
'trade_id': 1,
@@ -116,7 +116,7 @@ def test_rpc_status_table(default_conf, ticker, fee, markets, mocker) -> None:
with pytest.raises(RPCException, match=r'.*no active order*'):
rpc._rpc_status_table()
freqtradebot.create_trade()
freqtradebot.create_trades()
result = rpc._rpc_status_table()
assert 'instantly' in result['Since'].all()
assert 'ETH/BTC' in result['Pair'].all()
@@ -151,7 +151,7 @@ def test_rpc_daily_profit(default_conf, update, ticker, fee,
rpc = RPC(freqtradebot)
rpc._fiat_converter = CryptoToFiatConverter()
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
assert trade
@@ -208,7 +208,7 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
rpc._rpc_trade_statistics(stake_currency, fiat_display_currency)
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
# Simulate fulfilled LIMIT_BUY order for trade
trade.update(limit_buy_order)
@@ -222,7 +222,7 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
trade.close_date = datetime.utcnow()
trade.is_open = False
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
# Simulate fulfilled LIMIT_BUY order for trade
trade.update(limit_buy_order)
@@ -292,7 +292,7 @@ def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, fee, markets,
rpc = RPC(freqtradebot)
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
# Simulate fulfilled LIMIT_BUY order for trade
trade.update(limit_buy_order)
@@ -536,7 +536,7 @@ def test_rpc_forcesell(default_conf, ticker, fee, mocker, markets) -> None:
msg = rpc._rpc_forcesell('all')
assert msg == {'result': 'Created sell orders for all open trades.'}
freqtradebot.create_trade()
freqtradebot.create_trades()
msg = rpc._rpc_forcesell('all')
assert msg == {'result': 'Created sell orders for all open trades.'}
@@ -570,7 +570,7 @@ def test_rpc_forcesell(default_conf, ticker, fee, mocker, markets) -> None:
assert cancel_order_mock.call_count == 1
assert trade.amount == filled_amount
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.filter(Trade.id == '2').first()
amount = trade.amount
# make an limit-buy open trade, if there is no 'filled', don't sell it
@@ -589,7 +589,7 @@ def test_rpc_forcesell(default_conf, ticker, fee, mocker, markets) -> None:
assert cancel_order_mock.call_count == 2
assert trade.amount == amount
freqtradebot.create_trade()
freqtradebot.create_trades()
# make an limit-sell open trade
mocker.patch(
'freqtrade.exchange.Exchange.get_order',
@@ -622,7 +622,7 @@ def test_performance_handle(default_conf, ticker, limit_buy_order, fee,
rpc = RPC(freqtradebot)
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
assert trade
@@ -660,7 +660,7 @@ def test_rpc_count(mocker, default_conf, ticker, fee, markets) -> None:
assert counts["current"] == 0
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
counts = rpc._rpc_count()
assert counts["current"] == 1

View File

@@ -275,7 +275,7 @@ def test_api_count(botclient, mocker, ticker, fee, markets):
assert rc.json["max"] == 1.0
# Create some test data
ftbot.create_trade()
ftbot.create_trades()
rc = client_get(client, f"{BASE_URI}/count")
assert_response(rc)
assert rc.json["current"] == 1.0
@@ -329,7 +329,7 @@ def test_api_profit(botclient, mocker, ticker, fee, markets, limit_buy_order, li
assert len(rc.json) == 1
assert rc.json == {"error": "Error querying _profit: no closed trade"}
ftbot.create_trade()
ftbot.create_trades()
trade = Trade.query.first()
# Simulate fulfilled LIMIT_BUY order for trade
@@ -418,7 +418,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets):
assert_response(rc, 502)
assert rc.json == {'error': 'Error querying _status: no active trade'}
ftbot.create_trade()
ftbot.create_trades()
rc = client_get(client, f"{BASE_URI}/status")
assert_response(rc)
assert len(rc.json) == 1
@@ -548,7 +548,7 @@ def test_api_forcesell(botclient, mocker, ticker, fee, markets):
assert_response(rc, 502)
assert rc.json == {"error": "Error querying _forcesell: invalid argument"}
ftbot.create_trade()
ftbot.create_trades()
rc = client_post(client, f"{BASE_URI}/forcesell",
data='{"tradeid": "1"}')

View File

@@ -192,7 +192,7 @@ def test_status(default_conf, update, mocker, fee, ticker, markets) -> None:
# Create some test data
for _ in range(3):
freqtradebot.create_trade()
freqtradebot.create_trades()
telegram._status(bot=MagicMock(), update=update)
assert msg_mock.call_count == 1
@@ -240,7 +240,7 @@ def test_status_handle(default_conf, update, ticker, fee, markets, mocker) -> No
msg_mock.reset_mock()
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
# Trigger status while we have a fulfilled order for the open trade
telegram._status(bot=MagicMock(), update=update)
@@ -292,7 +292,7 @@ def test_status_table_handle(default_conf, update, ticker, fee, markets, mocker)
msg_mock.reset_mock()
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
telegram._status_table(bot=MagicMock(), update=update)
@@ -308,6 +308,7 @@ def test_status_table_handle(default_conf, update, ticker, fee, markets, mocker)
def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
limit_sell_order, markets, mocker) -> None:
patch_exchange(mocker)
default_conf['max_open_trades'] = 1
mocker.patch(
'freqtrade.rpc.rpc.CryptoToFiatConverter._find_price',
return_value=15000.0
@@ -331,7 +332,7 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
telegram = Telegram(freqtradebot)
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
assert trade
@@ -357,9 +358,9 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
# Reset msg_mock
msg_mock.reset_mock()
freqtradebot.config['max_open_trades'] = 2
# Add two other trades
freqtradebot.create_trade()
freqtradebot.create_trade()
freqtradebot.create_trades()
trades = Trade.query.all()
for trade in trades:
@@ -438,7 +439,7 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
msg_mock.reset_mock()
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
# Simulate fulfilled LIMIT_BUY order for trade
@@ -733,7 +734,7 @@ def test_forcesell_handle(default_conf, update, ticker, fee,
telegram = Telegram(freqtradebot)
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
assert trade
@@ -784,7 +785,7 @@ def test_forcesell_down_handle(default_conf, update, ticker, fee,
telegram = Telegram(freqtradebot)
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
# Decrease the price and sell it
mocker.patch.multiple(
@@ -832,14 +833,13 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, markets, mocker
markets=PropertyMock(return_value=markets),
validate_pairs=MagicMock(return_value={})
)
default_conf['max_open_trades'] = 4
freqtradebot = FreqtradeBot(default_conf)
patch_get_signal(freqtradebot, (True, False))
telegram = Telegram(freqtradebot)
# Create some test data
for _ in range(4):
freqtradebot.create_trade()
freqtradebot.create_trades()
rpc_mock.reset_mock()
update.message.text = '/forcesell all'
@@ -983,7 +983,7 @@ def test_performance_handle(default_conf, update, ticker, fee,
telegram = Telegram(freqtradebot)
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
trade = Trade.query.first()
assert trade
@@ -1028,7 +1028,7 @@ def test_count_handle(default_conf, update, ticker, fee, markets, mocker) -> Non
freqtradebot.state = State.RUNNING
# Create some test data
freqtradebot.create_trade()
freqtradebot.create_trades()
msg_mock.reset_mock()
telegram._count(bot=MagicMock(), update=update)

View File

@@ -3,7 +3,7 @@ import argparse
import pytest
from freqtrade.configuration import Arguments, TimeRange
from freqtrade.configuration import Arguments
from freqtrade.configuration.arguments import ARGS_DOWNLOADER, ARGS_PLOT_DATAFRAME
from freqtrade.configuration.cli_options import check_int_positive
@@ -86,30 +86,6 @@ def test_parse_args_strategy_path_invalid() -> None:
Arguments(['--strategy-path'], '').get_parsed_arg()
def test_parse_timerange_incorrect() -> None:
assert TimeRange(None, 'line', 0, -200) == Arguments.parse_timerange('-200')
assert TimeRange('line', None, 200, 0) == Arguments.parse_timerange('200-')
assert TimeRange('index', 'index', 200, 500) == Arguments.parse_timerange('200-500')
assert TimeRange('date', None, 1274486400, 0) == Arguments.parse_timerange('20100522-')
assert TimeRange(None, 'date', 0, 1274486400) == Arguments.parse_timerange('-20100522')
timerange = Arguments.parse_timerange('20100522-20150730')
assert timerange == TimeRange('date', 'date', 1274486400, 1438214400)
# Added test for unix timestamp - BTC genesis date
assert TimeRange('date', None, 1231006505, 0) == Arguments.parse_timerange('1231006505-')
assert TimeRange(None, 'date', 0, 1233360000) == Arguments.parse_timerange('-1233360000')
timerange = Arguments.parse_timerange('1231006505-1233360000')
assert TimeRange('date', 'date', 1231006505, 1233360000) == timerange
# TODO: Find solution for the following case (passing timestamp in ms)
timerange = Arguments.parse_timerange('1231006505000-1233360000000')
assert TimeRange('date', 'date', 1231006505, 1233360000) != timerange
with pytest.raises(Exception, match=r'Incorrect syntax.*'):
Arguments.parse_timerange('-')
def test_parse_args_backtesting_invalid() -> None:
with pytest.raises(SystemExit, match=r'2'):
Arguments(['backtesting --ticker-interval'], '').get_parsed_arg()

View File

@@ -499,9 +499,9 @@ def test_check_exchange(default_conf, caplog) -> None:
# Test a 'bad' exchange, which known to have serious problems
default_conf.get('exchange').update({'name': 'bitmex'})
assert not check_exchange(default_conf)
assert log_has_re(r"Exchange .* is known to not work with the bot yet\. "
r"Use it only for development and testing purposes\.", caplog)
with pytest.raises(OperationalException,
match=r"Exchange .* is known to not work with the bot yet.*"):
check_exchange(default_conf)
caplog.clear()
# Test a 'bad' exchange with check_for_bad=False
@@ -642,6 +642,17 @@ def test_validate_tsl(default_conf):
configuration._validate_config_consistency(default_conf)
def test_load_config_test_comments() -> None:
"""
Load config with comments
"""
config_file = Path(__file__).parents[0] / "config_test_comments.json"
print(config_file)
conf = load_config_file(str(config_file))
assert conf
def test_load_config_default_exchange(all_conf) -> None:
"""
config['exchange'] subtree has required options in it

View File

@@ -253,13 +253,13 @@ def test_get_trade_stake_amount_unlimited_amount(default_conf,
assert result == default_conf['stake_amount'] / conf['max_open_trades']
# create one trade, order amount should be 'balance / (max_open_trades - num_open_trades)'
freqtrade.create_trade()
freqtrade.execute_buy('ETH/BTC', result)
result = freqtrade._get_trade_stake_amount('LTC/BTC')
assert result == default_conf['stake_amount'] / (conf['max_open_trades'] - 1)
# create 2 trades, order amount should be None
freqtrade.create_trade()
freqtrade.execute_buy('LTC/BTC', result)
result = freqtrade._get_trade_stake_amount('XRP/BTC')
assert result is None
@@ -301,6 +301,7 @@ def test_edge_overrides_stoploss(limit_buy_order, fee, markets, caplog, mocker,
patch_RPCManager(mocker)
patch_exchange(mocker)
patch_edge(mocker)
edge_conf['max_open_trades'] = float('inf')
# Strategy stoploss is -0.1 but Edge imposes a stoploss at -0.2
# Thus, if price falls 21%, stoploss should be triggered
@@ -325,7 +326,7 @@ def test_edge_overrides_stoploss(limit_buy_order, fee, markets, caplog, mocker,
freqtrade.active_pair_whitelist = ['NEO/BTC']
patch_get_signal(freqtrade)
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.update(limit_buy_order)
#############################################
@@ -341,6 +342,7 @@ def test_edge_should_ignore_strategy_stoploss(limit_buy_order, fee, markets,
patch_RPCManager(mocker)
patch_exchange(mocker)
patch_edge(mocker)
edge_conf['max_open_trades'] = float('inf')
# Strategy stoploss is -0.1 but Edge imposes a stoploss at -0.2
# Thus, if price falls 15%, stoploss should not be triggered
@@ -365,7 +367,7 @@ def test_edge_should_ignore_strategy_stoploss(limit_buy_order, fee, markets,
freqtrade.active_pair_whitelist = ['NEO/BTC']
patch_get_signal(freqtrade)
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.update(limit_buy_order)
#############################################
@@ -379,6 +381,7 @@ def test_total_open_trades_stakes(mocker, default_conf, ticker,
patch_RPCManager(mocker)
patch_exchange(mocker)
default_conf['stake_amount'] = 0.0000098751
default_conf['max_open_trades'] = 2
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
get_ticker=ticker,
@@ -388,7 +391,7 @@ def test_total_open_trades_stakes(mocker, default_conf, ticker,
)
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
assert trade is not None
@@ -396,7 +399,7 @@ def test_total_open_trades_stakes(mocker, default_conf, ticker,
assert trade.is_open
assert trade.open_date is not None
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.order_by(Trade.id.desc()).first()
assert trade is not None
@@ -519,7 +522,7 @@ def test_get_min_pair_stake_amount(mocker, default_conf) -> None:
assert result == min(8, 2 * 2) / 0.9
def test_create_trade(default_conf, ticker, limit_buy_order, fee, markets, mocker) -> None:
def test_create_trades(default_conf, ticker, limit_buy_order, fee, markets, mocker) -> None:
patch_RPCManager(mocker)
patch_exchange(mocker)
mocker.patch.multiple(
@@ -534,7 +537,7 @@ def test_create_trade(default_conf, ticker, limit_buy_order, fee, markets, mocke
whitelist = deepcopy(default_conf['exchange']['pair_whitelist'])
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
assert trade is not None
@@ -552,8 +555,8 @@ def test_create_trade(default_conf, ticker, limit_buy_order, fee, markets, mocke
assert whitelist == default_conf['exchange']['pair_whitelist']
def test_create_trade_no_stake_amount(default_conf, ticker, limit_buy_order,
fee, markets, mocker) -> None:
def test_create_trades_no_stake_amount(default_conf, ticker, limit_buy_order,
fee, markets, mocker) -> None:
patch_RPCManager(mocker)
patch_exchange(mocker)
patch_wallet(mocker, free=default_conf['stake_amount'] * 0.5)
@@ -568,11 +571,11 @@ def test_create_trade_no_stake_amount(default_conf, ticker, limit_buy_order,
patch_get_signal(freqtrade)
with pytest.raises(DependencyException, match=r'.*stake amount.*'):
freqtrade.create_trade()
freqtrade.create_trades()
def test_create_trade_minimal_amount(default_conf, ticker, limit_buy_order,
fee, markets, mocker) -> None:
def test_create_trades_minimal_amount(default_conf, ticker, limit_buy_order,
fee, markets, mocker) -> None:
patch_RPCManager(mocker)
patch_exchange(mocker)
buy_mock = MagicMock(return_value={'id': limit_buy_order['id']})
@@ -587,13 +590,13 @@ def test_create_trade_minimal_amount(default_conf, ticker, limit_buy_order,
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
freqtrade.create_trade()
freqtrade.create_trades()
rate, amount = buy_mock.call_args[1]['rate'], buy_mock.call_args[1]['amount']
assert rate * amount >= default_conf['stake_amount']
def test_create_trade_too_small_stake_amount(default_conf, ticker, limit_buy_order,
fee, markets, mocker) -> None:
def test_create_trades_too_small_stake_amount(default_conf, ticker, limit_buy_order,
fee, markets, mocker) -> None:
patch_RPCManager(mocker)
patch_exchange(mocker)
buy_mock = MagicMock(return_value={'id': limit_buy_order['id']})
@@ -609,11 +612,11 @@ def test_create_trade_too_small_stake_amount(default_conf, ticker, limit_buy_ord
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
assert not freqtrade.create_trade()
assert not freqtrade.create_trades()
def test_create_trade_limit_reached(default_conf, ticker, limit_buy_order,
fee, markets, mocker) -> None:
def test_create_trades_limit_reached(default_conf, ticker, limit_buy_order,
fee, markets, mocker) -> None:
patch_RPCManager(mocker)
patch_exchange(mocker)
mocker.patch.multiple(
@@ -630,12 +633,12 @@ def test_create_trade_limit_reached(default_conf, ticker, limit_buy_order,
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
assert not freqtrade.create_trade()
assert not freqtrade.create_trades()
assert freqtrade._get_trade_stake_amount('ETH/BTC') is None
def test_create_trade_no_pairs_let(default_conf, ticker, limit_buy_order, fee,
markets, mocker, caplog) -> None:
def test_create_trades_no_pairs_let(default_conf, ticker, limit_buy_order, fee,
markets, mocker, caplog) -> None:
patch_RPCManager(mocker)
patch_exchange(mocker)
mocker.patch.multiple(
@@ -650,13 +653,13 @@ def test_create_trade_no_pairs_let(default_conf, ticker, limit_buy_order, fee,
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
assert freqtrade.create_trade()
assert not freqtrade.create_trade()
assert freqtrade.create_trades()
assert not freqtrade.create_trades()
assert log_has("No currency pair in whitelist, but checking to sell open trades.", caplog)
def test_create_trade_no_pairs_in_whitelist(default_conf, ticker, limit_buy_order, fee,
markets, mocker, caplog) -> None:
def test_create_trades_no_pairs_in_whitelist(default_conf, ticker, limit_buy_order, fee,
markets, mocker, caplog) -> None:
patch_RPCManager(mocker)
patch_exchange(mocker)
mocker.patch.multiple(
@@ -670,11 +673,11 @@ def test_create_trade_no_pairs_in_whitelist(default_conf, ticker, limit_buy_orde
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
assert not freqtrade.create_trade()
assert not freqtrade.create_trades()
assert log_has("Whitelist is empty.", caplog)
def test_create_trade_no_signal(default_conf, fee, mocker) -> None:
def test_create_trades_no_signal(default_conf, fee, mocker) -> None:
default_conf['dry_run'] = True
patch_RPCManager(mocker)
@@ -690,7 +693,56 @@ def test_create_trade_no_signal(default_conf, fee, mocker) -> None:
Trade.query = MagicMock()
Trade.query.filter = MagicMock()
assert not freqtrade.create_trade()
assert not freqtrade.create_trades()
@pytest.mark.parametrize("max_open", range(0, 5))
def test_create_trades_multiple_trades(default_conf, ticker,
fee, markets, mocker, max_open) -> None:
patch_RPCManager(mocker)
patch_exchange(mocker)
default_conf['max_open_trades'] = max_open
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
get_ticker=ticker,
buy=MagicMock(return_value={'id': "12355555"}),
get_fee=fee,
markets=PropertyMock(return_value=markets)
)
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
freqtrade.create_trades()
trades = Trade.get_open_trades()
assert len(trades) == max_open
def test_create_trades_preopen(default_conf, ticker, fee, markets, mocker) -> None:
patch_RPCManager(mocker)
patch_exchange(mocker)
default_conf['max_open_trades'] = 4
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
get_ticker=ticker,
buy=MagicMock(return_value={'id': "12355555"}),
get_fee=fee,
markets=PropertyMock(return_value=markets)
)
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
# Create 2 existing trades
freqtrade.execute_buy('ETH/BTC', default_conf['stake_amount'])
freqtrade.execute_buy('NEO/BTC', default_conf['stake_amount'])
assert len(Trade.get_open_trades()) == 2
# Create 2 new trades using create_trades
assert freqtrade.create_trades()
trades = Trade.get_open_trades()
assert len(trades) == 4
def test_process_trade_creation(default_conf, ticker, limit_buy_order,
@@ -711,8 +763,7 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order,
trades = Trade.query.filter(Trade.is_open.is_(True)).all()
assert not trades
result = freqtrade.process()
assert result is True
freqtrade.process()
trades = Trade.query.filter(Trade.is_open.is_(True)).all()
assert len(trades) == 1
@@ -744,8 +795,7 @@ def test_process_exchange_failures(default_conf, ticker, markets, mocker) -> Non
worker = Worker(args=None, config=default_conf)
patch_get_signal(worker.freqtrade)
result = worker._process()
assert result is False
worker._process()
assert sleep_mock.has_calls()
@@ -763,8 +813,7 @@ def test_process_operational_exception(default_conf, ticker, markets, mocker) ->
assert worker.state == State.RUNNING
result = worker._process()
assert result is False
worker._process()
assert worker.state == State.STOPPED
assert 'OperationalException' in msg_mock.call_args_list[-1][0][0]['status']
@@ -786,13 +835,14 @@ def test_process_trade_handling(
trades = Trade.query.filter(Trade.is_open.is_(True)).all()
assert not trades
result = freqtrade.process()
assert result is True
freqtrade.process()
trades = Trade.query.filter(Trade.is_open.is_(True)).all()
assert len(trades) == 1
result = freqtrade.process()
assert result is False
# Nothing happened ...
freqtrade.process()
assert len(trades) == 1
def test_process_trade_no_whitelist_pair(
@@ -834,11 +884,10 @@ def test_process_trade_no_whitelist_pair(
))
assert pair not in freqtrade.active_pair_whitelist
result = freqtrade.process()
freqtrade.process()
assert pair in freqtrade.active_pair_whitelist
# Make sure each pair is only in the list once
assert len(freqtrade.active_pair_whitelist) == len(set(freqtrade.active_pair_whitelist))
assert result is True
def test_process_informative_pairs_added(default_conf, ticker, markets, mocker) -> None:
@@ -1078,7 +1127,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf, fee, caplog,
# Fourth case: when stoploss is set and it is hit
# should unset stoploss_order_id and return true
# as a trade actually happened
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.is_open = True
trade.open_order_id = None
@@ -1153,7 +1202,7 @@ def test_handle_stoploss_on_exchange_trailing(mocker, default_conf, fee, caplog,
patch_get_signal(freqtrade)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.is_open = True
trade.open_order_id = None
@@ -1243,7 +1292,7 @@ def test_handle_stoploss_on_exchange_trailing_error(mocker, default_conf, fee, c
# setting stoploss_on_exchange_interval to 60 seconds
freqtrade.strategy.order_types['stoploss_on_exchange_interval'] = 60
patch_get_signal(freqtrade)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.is_open = True
trade.open_order_id = None
@@ -1286,7 +1335,7 @@ def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog,
patch_RPCManager(mocker)
patch_exchange(mocker)
patch_edge(mocker)
edge_conf['max_open_trades'] = float('inf')
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
get_ticker=MagicMock(return_value={
@@ -1324,7 +1373,7 @@ def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog,
freqtrade.active_pair_whitelist = freqtrade.edge.adjust(freqtrade.active_pair_whitelist)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.is_open = True
trade.open_order_id = None
@@ -1388,21 +1437,19 @@ def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog,
stop_price=0.00002344 * 0.99)
def test_process_maybe_execute_buy(mocker, default_conf) -> None:
def test_process_maybe_execute_buy(mocker, default_conf, caplog) -> None:
freqtrade = get_patched_freqtradebot(mocker, default_conf)
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.create_trade', MagicMock(return_value=True))
assert freqtrade.process_maybe_execute_buy()
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.create_trade', MagicMock(return_value=False))
assert not freqtrade.process_maybe_execute_buy()
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.create_trades', MagicMock(return_value=False))
freqtrade.process_maybe_execute_buy()
assert log_has('Found no buy signals for whitelisted currencies. Trying again...', caplog)
def test_process_maybe_execute_buy_exception(mocker, default_conf, caplog) -> None:
freqtrade = get_patched_freqtradebot(mocker, default_conf)
mocker.patch(
'freqtrade.freqtradebot.FreqtradeBot.create_trade',
'freqtrade.freqtradebot.FreqtradeBot.create_trades',
MagicMock(side_effect=DependencyException)
)
freqtrade.process_maybe_execute_buy()
@@ -1589,7 +1636,7 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order,
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
assert trade
@@ -1629,7 +1676,7 @@ def test_handle_overlpapping_signals(default_conf, ticker, limit_buy_order,
patch_get_signal(freqtrade, value=(True, True))
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
freqtrade.create_trade()
freqtrade.create_trades()
# Buy and Sell triggering, so doing nothing ...
trades = Trade.query.all()
@@ -1638,7 +1685,7 @@ def test_handle_overlpapping_signals(default_conf, ticker, limit_buy_order,
# Buy is triggering, so buying ...
patch_get_signal(freqtrade, value=(True, False))
freqtrade.create_trade()
freqtrade.create_trades()
trades = Trade.query.all()
nb_trades = len(trades)
assert nb_trades == 1
@@ -1685,7 +1732,7 @@ def test_handle_trade_roi(default_conf, ticker, limit_buy_order,
patch_get_signal(freqtrade, value=(True, False))
freqtrade.strategy.min_roi_reached = MagicMock(return_value=True)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.is_open = True
@@ -1717,7 +1764,7 @@ def test_handle_trade_experimental(
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.is_open = True
@@ -1745,7 +1792,7 @@ def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order,
patch_get_signal(freqtrade)
# Create trade and sell it
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
assert trade
@@ -2085,7 +2132,7 @@ def test_execute_sell_up(default_conf, ticker, fee, ticker_sell_up, markets, moc
patch_get_signal(freqtrade)
# Create some test data
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
assert trade
@@ -2131,7 +2178,7 @@ def test_execute_sell_down(default_conf, ticker, fee, ticker_sell_down, markets,
patch_get_signal(freqtrade)
# Create some test data
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
assert trade
@@ -2180,7 +2227,7 @@ def test_execute_sell_down_stoploss_on_exchange_dry_run(default_conf, ticker, fe
patch_get_signal(freqtrade)
# Create some test data
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
assert trade
@@ -2237,7 +2284,7 @@ def test_execute_sell_sloe_cancel_exception(mocker, default_conf, ticker, fee,
freqtrade.strategy.order_types['stoploss_on_exchange'] = True
patch_get_signal(freqtrade)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
Trade.session = MagicMock()
@@ -2284,7 +2331,7 @@ def test_execute_sell_with_stoploss_on_exchange(default_conf,
patch_get_signal(freqtrade)
# Create some test data
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
assert trade
@@ -2336,7 +2383,7 @@ def test_may_execute_sell_after_stoploss_on_exchange_hit(default_conf,
patch_get_signal(freqtrade)
# Create some test data
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
freqtrade.process_maybe_execute_sell(trade)
assert trade
@@ -2374,6 +2421,58 @@ def test_may_execute_sell_after_stoploss_on_exchange_hit(default_conf,
assert rpc_mock.call_count == 2
def test_execute_sell_market_order(default_conf, ticker, fee,
ticker_sell_up, markets, mocker) -> None:
rpc_mock = patch_RPCManager(mocker)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
_load_markets=MagicMock(return_value={}),
get_ticker=ticker,
get_fee=fee,
markets=PropertyMock(return_value=markets)
)
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
# Create some test data
freqtrade.create_trades()
trade = Trade.query.first()
assert trade
# Increase the price and sell it
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
get_ticker=ticker_sell_up
)
freqtrade.config['order_types']['sell'] = 'market'
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'], sell_reason=SellType.ROI)
assert not trade.is_open
assert trade.close_profit == 0.0611052
assert rpc_mock.call_count == 2
last_msg = rpc_mock.call_args_list[-1][0][0]
assert {
'type': RPCMessageType.SELL_NOTIFICATION,
'exchange': 'Bittrex',
'pair': 'ETH/BTC',
'gain': 'profit',
'limit': 1.172e-05,
'amount': 90.99181073703367,
'order_type': 'market',
'open_rate': 1.099e-05,
'current_rate': 1.172e-05,
'profit_amount': 6.126e-05,
'profit_percent': 0.0611052,
'stake_currency': 'BTC',
'fiat_currency': 'USD',
'sell_reason': SellType.ROI.value
} == last_msg
def test_sell_profit_only_enable_profit(default_conf, limit_buy_order,
fee, markets, mocker) -> None:
patch_RPCManager(mocker)
@@ -2397,7 +2496,7 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order,
patch_get_signal(freqtrade)
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.update(limit_buy_order)
@@ -2428,7 +2527,7 @@ def test_sell_profit_only_disable_profit(default_conf, limit_buy_order,
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.update(limit_buy_order)
@@ -2459,7 +2558,7 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, fee, market
patch_get_signal(freqtrade)
freqtrade.strategy.stop_loss_reached = MagicMock(return_value=SellCheckTuple(
sell_flag=False, sell_type=SellType.NONE))
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.update(limit_buy_order)
@@ -2490,7 +2589,7 @@ def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, fee, marke
patch_get_signal(freqtrade)
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.update(limit_buy_order)
@@ -2557,7 +2656,7 @@ def test_ignore_roi_if_buy_signal(default_conf, limit_buy_order, fee, markets, m
patch_get_signal(freqtrade)
freqtrade.strategy.min_roi_reached = MagicMock(return_value=True)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.update(limit_buy_order)
@@ -2589,7 +2688,7 @@ def test_trailing_stop_loss(default_conf, limit_buy_order, fee, markets, caplog,
patch_get_signal(freqtrade)
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
assert freqtrade.handle_trade(trade) is False
@@ -2642,7 +2741,7 @@ def test_trailing_stop_loss_positive(default_conf, limit_buy_order, fee, markets
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.update(limit_buy_order)
@@ -2700,7 +2799,7 @@ def test_trailing_stop_loss_offset(default_conf, limit_buy_order, fee,
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.update(limit_buy_order)
@@ -2763,7 +2862,7 @@ def test_tsl_only_offset_reached(default_conf, limit_buy_order, fee,
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.update(limit_buy_order)
@@ -2822,7 +2921,7 @@ def test_disable_ignore_roi_if_buy_signal(default_conf, limit_buy_order,
patch_get_signal(freqtrade)
freqtrade.strategy.min_roi_reached = MagicMock(return_value=True)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
trade.update(limit_buy_order)
@@ -3079,7 +3178,7 @@ def test_order_book_depth_of_market(default_conf, ticker, limit_buy_order, fee,
whitelist = deepcopy(default_conf['exchange']['pair_whitelist'])
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
assert trade is not None
@@ -3113,7 +3212,7 @@ def test_order_book_depth_of_market_high_delta(default_conf, ticker, limit_buy_o
# Save state of current whitelist
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
assert trade is None
@@ -3219,7 +3318,7 @@ def test_order_book_ask_strategy(default_conf, limit_buy_order, limit_sell_order
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
freqtrade.create_trade()
freqtrade.create_trades()
trade = Trade.query.first()
assert trade

View File

@@ -5,7 +5,7 @@ from unittest.mock import MagicMock
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from freqtrade.configuration import Arguments, TimeRange
from freqtrade.configuration import TimeRange
from freqtrade.data import history
from freqtrade.data.btanalysis import create_cum_profit, load_backtest_data
from freqtrade.plot.plotting import (add_indicators, add_profit,
@@ -222,7 +222,7 @@ def test_generate_plot_file(mocker, caplog):
def test_add_profit():
filename = history.make_testdata_path(None) / "backtest-result_test.json"
bt_data = load_backtest_data(filename)
timerange = Arguments.parse_timerange("20180110-20180112")
timerange = TimeRange.parse_timerange("20180110-20180112")
df = history.load_pair_history(pair="POWR/BTC", ticker_interval='5m',
datadir=None, timerange=timerange)
@@ -242,7 +242,7 @@ def test_add_profit():
def test_generate_profit_graph():
filename = history.make_testdata_path(None) / "backtest-result_test.json"
trades = load_backtest_data(filename)
timerange = Arguments.parse_timerange("20180110-20180112")
timerange = TimeRange.parse_timerange("20180110-20180112")
pairs = ["POWR/BTC", "XLM/BTC"]
tickers = history.load_data(datadir=None,

View File

@@ -0,0 +1,28 @@
# pragma pylint: disable=missing-docstring, C0103
import pytest
from freqtrade.configuration import TimeRange
def test_parse_timerange_incorrect() -> None:
assert TimeRange(None, 'line', 0, -200) == TimeRange.parse_timerange('-200')
assert TimeRange('line', None, 200, 0) == TimeRange.parse_timerange('200-')
assert TimeRange('index', 'index', 200, 500) == TimeRange.parse_timerange('200-500')
assert TimeRange('date', None, 1274486400, 0) == TimeRange.parse_timerange('20100522-')
assert TimeRange(None, 'date', 0, 1274486400) == TimeRange.parse_timerange('-20100522')
timerange = TimeRange.parse_timerange('20100522-20150730')
assert timerange == TimeRange('date', 'date', 1274486400, 1438214400)
# Added test for unix timestamp - BTC genesis date
assert TimeRange('date', None, 1231006505, 0) == TimeRange.parse_timerange('1231006505-')
assert TimeRange(None, 'date', 0, 1233360000) == TimeRange.parse_timerange('-1233360000')
timerange = TimeRange.parse_timerange('1231006505-1233360000')
assert TimeRange('date', 'date', 1231006505, 1233360000) == timerange
# TODO: Find solution for the following case (passing timestamp in ms)
timerange = TimeRange.parse_timerange('1231006505000-1233360000000')
assert TimeRange('date', 'date', 1231006505, 1233360000) != timerange
with pytest.raises(Exception, match=r'Incorrect syntax.*'):
TimeRange.parse_timerange('-')