Merge branch 'develop' into add_trades_count_in_performance
This commit is contained in:
commit
01b49dc502
@ -27,23 +27,27 @@ _CONF = {}
|
|||||||
def refresh_whitelist(whitelist: List[str]) -> List[str]:
|
def refresh_whitelist(whitelist: List[str]) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Check wallet health and remove pair from whitelist if necessary
|
Check wallet health and remove pair from whitelist if necessary
|
||||||
:param whitelist: the pair the user might want to trade
|
:param whitelist: the sorted list (based on BaseVolume) of pairs the user might want to trade
|
||||||
:return: the list of pairs the user wants to trade without the one unavailable or black_listed
|
:return: the list of pairs the user wants to trade without the one unavailable or black_listed
|
||||||
"""
|
"""
|
||||||
sanitized_whitelist = []
|
sanitized_whitelist = whitelist
|
||||||
health = exchange.get_wallet_health()
|
health = exchange.get_wallet_health()
|
||||||
|
known_pairs = set()
|
||||||
for status in health:
|
for status in health:
|
||||||
pair = '{}_{}'.format(_CONF['stake_currency'], status['Currency'])
|
pair = '{}_{}'.format(_CONF['stake_currency'], status['Currency'])
|
||||||
|
known_pairs.add(pair)
|
||||||
if pair not in whitelist or pair in _CONF['exchange'].get('pair_blacklist', []):
|
if pair not in whitelist or pair in _CONF['exchange'].get('pair_blacklist', []):
|
||||||
continue
|
continue
|
||||||
if status['IsActive']:
|
if not status['IsActive']:
|
||||||
sanitized_whitelist.append(pair)
|
sanitized_whitelist.remove(pair)
|
||||||
else:
|
|
||||||
logger.info(
|
logger.info(
|
||||||
'Ignoring %s from whitelist (reason: %s).',
|
'Ignoring %s from whitelist (reason: %s).',
|
||||||
pair, status.get('Notice') or 'wallet is not active'
|
pair, status.get('Notice') or 'wallet is not active'
|
||||||
)
|
)
|
||||||
return sanitized_whitelist
|
|
||||||
|
# We need to remove pairs that are unknown
|
||||||
|
final_list = [x for x in sanitized_whitelist if x in known_pairs]
|
||||||
|
return final_list
|
||||||
|
|
||||||
|
|
||||||
def _process(nb_assets: Optional[int] = 0) -> bool:
|
def _process(nb_assets: Optional[int] = 0) -> bool:
|
||||||
|
@ -41,27 +41,29 @@ def generate_text_table(
|
|||||||
Generates and returns a text table for the given backtest data and the results dataframe
|
Generates and returns a text table for the given backtest data and the results dataframe
|
||||||
:return: pretty printed table with tabulate as str
|
:return: pretty printed table with tabulate as str
|
||||||
"""
|
"""
|
||||||
|
floatfmt = ('s', 'd', '.2f', '.8f', '.1f')
|
||||||
tabular_data = []
|
tabular_data = []
|
||||||
headers = ['pair', 'buy count', 'avg profit', 'total profit', 'avg duration']
|
headers = ['pair', 'buy count', 'avg profit %',
|
||||||
|
'total profit ' + stake_currency, 'avg duration']
|
||||||
for pair in data:
|
for pair in data:
|
||||||
result = results[results.currency == pair]
|
result = results[results.currency == pair]
|
||||||
tabular_data.append([
|
tabular_data.append([
|
||||||
pair,
|
pair,
|
||||||
len(result.index),
|
len(result.index),
|
||||||
'{:.2f}%'.format(result.profit_percent.mean() * 100.0),
|
result.profit_percent.mean() * 100.0,
|
||||||
'{:.08f} {}'.format(result.profit_BTC.sum(), stake_currency),
|
result.profit_BTC.sum(),
|
||||||
'{:.2f}'.format(result.duration.mean() * ticker_interval),
|
result.duration.mean() * ticker_interval,
|
||||||
])
|
])
|
||||||
|
|
||||||
# Append Total
|
# Append Total
|
||||||
tabular_data.append([
|
tabular_data.append([
|
||||||
'TOTAL',
|
'TOTAL',
|
||||||
len(results.index),
|
len(results.index),
|
||||||
'{:.2f}%'.format(results.profit_percent.mean() * 100.0),
|
results.profit_percent.mean() * 100.0,
|
||||||
'{:.08f} {}'.format(results.profit_BTC.sum(), stake_currency),
|
results.profit_BTC.sum(),
|
||||||
'{:.2f}'.format(results.duration.mean() * ticker_interval),
|
results.duration.mean() * ticker_interval,
|
||||||
])
|
])
|
||||||
return tabulate(tabular_data, headers=headers)
|
return tabulate(tabular_data, headers=headers, floatfmt=floatfmt)
|
||||||
|
|
||||||
|
|
||||||
def backtest(stake_amount: float, processed: Dict[str, DataFrame],
|
def backtest(stake_amount: float, processed: Dict[str, DataFrame],
|
||||||
@ -173,6 +175,6 @@ def start(args):
|
|||||||
config['stake_amount'], preprocess(data), max_open_trades, args.realistic_simulation
|
config['stake_amount'], preprocess(data), max_open_trades, args.realistic_simulation
|
||||||
)
|
)
|
||||||
logger.info(
|
logger.info(
|
||||||
'\n====================== BACKTESTING REPORT ======================================\n%s',
|
'\n====================== BACKTESTING REPORT ================================\n%s',
|
||||||
generate_text_table(data, results, config['stake_currency'], args.ticker_interval)
|
generate_text_table(data, results, config['stake_currency'], args.ticker_interval)
|
||||||
)
|
)
|
||||||
|
@ -18,11 +18,12 @@ def test_generate_text_table():
|
|||||||
'duration': [10, 30]
|
'duration': [10, 30]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
print(generate_text_table({'BTC_ETH': {}}, results, 'BTC', 5))
|
||||||
assert generate_text_table({'BTC_ETH': {}}, results, 'BTC', 5) == (
|
assert generate_text_table({'BTC_ETH': {}}, results, 'BTC', 5) == (
|
||||||
'pair buy count avg profit total profit avg duration\n'
|
'pair buy count avg profit % total profit BTC avg duration\n'
|
||||||
'------- ----------- ------------ -------------- --------------\n'
|
'------- ----------- -------------- ------------------ --------------\n'
|
||||||
'BTC_ETH 2 15.00% 0.60000000 BTC 100\n'
|
'BTC_ETH 2 15.00 0.60000000 100.0\n'
|
||||||
'TOTAL 2 15.00% 0.60000000 BTC 100')
|
'TOTAL 2 15.00 0.60000000 100.0')
|
||||||
|
|
||||||
|
|
||||||
def test_get_timeframe():
|
def test_get_timeframe():
|
||||||
|
@ -16,24 +16,43 @@ def whitelist_conf():
|
|||||||
"BTC_SWT",
|
"BTC_SWT",
|
||||||
"BTC_BCC"
|
"BTC_BCC"
|
||||||
],
|
],
|
||||||
|
"pair_blacklist": [
|
||||||
|
"BTC_BLK"
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_health():
|
def get_health():
|
||||||
return [{'Currency': 'ETH',
|
return [{'Currency': 'ETH',
|
||||||
'IsActive': True
|
'IsActive': True,
|
||||||
|
'BaseVolume': 42
|
||||||
},
|
},
|
||||||
{'Currency': 'TKN',
|
{'Currency': 'TKN',
|
||||||
'IsActive': True
|
'IsActive': True,
|
||||||
}]
|
'BaseVolume': 1664
|
||||||
|
},
|
||||||
|
{'Currency': 'BLK',
|
||||||
|
'IsActive': True,
|
||||||
|
'BaseVolume': 4096
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def get_health_empty():
|
def get_health_empty():
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# below three test could be merged into a single
|
|
||||||
# test that ran randomlly generated health lists
|
def test_refresh_market_pair_not_in_whitelist(mocker):
|
||||||
|
conf = whitelist_conf()
|
||||||
|
mocker.patch.dict('freqtrade.main._CONF', conf)
|
||||||
|
mocker.patch.multiple('freqtrade.main.exchange',
|
||||||
|
get_wallet_health=get_health)
|
||||||
|
refreshedwhitelist = refresh_whitelist(conf['exchange']['pair_whitelist'] + ['BTC_XXX'])
|
||||||
|
# List ordered by BaseVolume
|
||||||
|
whitelist = ['BTC_ETH', 'BTC_TKN']
|
||||||
|
# Ensure all except those in whitelist are removed
|
||||||
|
assert whitelist == refreshedwhitelist
|
||||||
|
|
||||||
|
|
||||||
def test_refresh_whitelist(mocker):
|
def test_refresh_whitelist(mocker):
|
||||||
@ -42,9 +61,10 @@ def test_refresh_whitelist(mocker):
|
|||||||
mocker.patch.multiple('freqtrade.main.exchange',
|
mocker.patch.multiple('freqtrade.main.exchange',
|
||||||
get_wallet_health=get_health)
|
get_wallet_health=get_health)
|
||||||
refreshedwhitelist = refresh_whitelist(conf['exchange']['pair_whitelist'])
|
refreshedwhitelist = refresh_whitelist(conf['exchange']['pair_whitelist'])
|
||||||
|
# List ordered by BaseVolume
|
||||||
whitelist = ['BTC_ETH', 'BTC_TKN']
|
whitelist = ['BTC_ETH', 'BTC_TKN']
|
||||||
# Ensure all except those in whitelist are removed
|
# Ensure all except those in whitelist are removed
|
||||||
assert set(whitelist) == set(refreshedwhitelist)
|
assert whitelist == refreshedwhitelist
|
||||||
|
|
||||||
|
|
||||||
def test_refresh_whitelist_dynamic(mocker):
|
def test_refresh_whitelist_dynamic(mocker):
|
||||||
@ -53,9 +73,9 @@ def test_refresh_whitelist_dynamic(mocker):
|
|||||||
mocker.patch.multiple('freqtrade.main.exchange',
|
mocker.patch.multiple('freqtrade.main.exchange',
|
||||||
get_wallet_health=get_health)
|
get_wallet_health=get_health)
|
||||||
# argument: use the whitelist dynamically by exchange-volume
|
# argument: use the whitelist dynamically by exchange-volume
|
||||||
whitelist = ['BTC_ETH', 'BTC_TKN']
|
whitelist = ['BTC_TKN', 'BTC_ETH']
|
||||||
refreshedwhitelist = refresh_whitelist(whitelist)
|
refreshedwhitelist = refresh_whitelist(whitelist)
|
||||||
assert set(whitelist) == set(refreshedwhitelist)
|
assert whitelist == refreshedwhitelist
|
||||||
|
|
||||||
|
|
||||||
def test_refresh_whitelist_dynamic_empty(mocker):
|
def test_refresh_whitelist_dynamic_empty(mocker):
|
||||||
|
Loading…
Reference in New Issue
Block a user