Performancefilter - improve sorting
Ordering of Pairs without history should remain identical, so pairs with positive performance move to the front, and negative pairs move to the back. closes #4893
This commit is contained in:
parent
ef086d438c
commit
5eb5029856
@ -60,6 +60,7 @@ class PerformanceFilter(IPairList):
|
|||||||
|
|
||||||
# Get pairlist from performance dataframe values
|
# Get pairlist from performance dataframe values
|
||||||
list_df = pd.DataFrame({'pair': pairlist})
|
list_df = pd.DataFrame({'pair': pairlist})
|
||||||
|
list_df['prior_idx'] = list_df.index
|
||||||
|
|
||||||
# Set initial value for pairs with no trades to 0
|
# Set initial value for pairs with no trades to 0
|
||||||
# Sort the list using:
|
# Sort the list using:
|
||||||
@ -67,7 +68,7 @@ class PerformanceFilter(IPairList):
|
|||||||
# - then count (low to high, so as to favor same performance with fewer trades)
|
# - then count (low to high, so as to favor same performance with fewer trades)
|
||||||
# - then pair name alphametically
|
# - then pair name alphametically
|
||||||
sorted_df = list_df.merge(performance, on='pair', how='left')\
|
sorted_df = list_df.merge(performance, on='pair', how='left')\
|
||||||
.fillna(0).sort_values(by=['count', 'pair'], ascending=True)\
|
.fillna(0).sort_values(by=['count', 'prior_idx'], ascending=True)\
|
||||||
.sort_values(by=['profit_ratio'], ascending=False)
|
.sort_values(by=['profit_ratio'], ascending=False)
|
||||||
if self._min_profit is not None:
|
if self._min_profit is not None:
|
||||||
removed = sorted_df[sorted_df['profit_ratio'] < self._min_profit]
|
removed = sorted_df[sorted_df['profit_ratio'] < self._min_profit]
|
||||||
|
@ -342,7 +342,8 @@ def mock_trade_usdt_7(fee):
|
|||||||
stake_amount=20.0,
|
stake_amount=20.0,
|
||||||
amount=2.0,
|
amount=2.0,
|
||||||
amount_requested=2.0,
|
amount_requested=2.0,
|
||||||
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=5),
|
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20),
|
||||||
|
close_date=datetime.now(tz=timezone.utc) - timedelta(minutes=5),
|
||||||
fee_open=fee.return_value,
|
fee_open=fee.return_value,
|
||||||
fee_close=fee.return_value,
|
fee_close=fee.return_value,
|
||||||
is_open=False,
|
is_open=False,
|
||||||
|
@ -740,6 +740,33 @@ def test_PerformanceFilter_lookback(mocker, default_conf_usdt, fee, caplog) -> N
|
|||||||
assert pm.whitelist == ['ETH/USDT', 'XRP/USDT', 'NEO/USDT', 'TKN/USDT']
|
assert pm.whitelist == ['ETH/USDT', 'XRP/USDT', 'NEO/USDT', 'TKN/USDT']
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("init_persistence")
|
||||||
|
def test_PerformanceFilter_keep_mid_order(mocker, default_conf_usdt, fee, caplog) -> None:
|
||||||
|
default_conf_usdt['exchange']['pair_whitelist'].extend(['ADA/USDT', 'ETC/USDT'])
|
||||||
|
default_conf_usdt['pairlists'] = [
|
||||||
|
{"method": "StaticPairList", "allow_inactive": True},
|
||||||
|
{"method": "PerformanceFilter", "minutes": 60, }
|
||||||
|
]
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.exchange_has', return_value=True)
|
||||||
|
exchange = get_patched_exchange(mocker, default_conf_usdt)
|
||||||
|
pm = PairListManager(exchange, default_conf_usdt)
|
||||||
|
pm.refresh_pairlist()
|
||||||
|
|
||||||
|
assert pm.whitelist == ['ETH/USDT', 'LTC/USDT', 'XRP/USDT',
|
||||||
|
'NEO/USDT', 'TKN/USDT', 'ADA/USDT', 'ETC/USDT']
|
||||||
|
|
||||||
|
with time_machine.travel("2021-09-01 05:00:00 +00:00") as t:
|
||||||
|
create_mock_trades_usdt(fee)
|
||||||
|
pm.refresh_pairlist()
|
||||||
|
assert pm.whitelist == ['XRP/USDT', 'ETC/USDT', 'ETH/USDT',
|
||||||
|
'NEO/USDT', 'TKN/USDT', 'ADA/USDT', 'LTC/USDT']
|
||||||
|
# assert log_has_re(r'Removing pair .* since .* is below .*', caplog)
|
||||||
|
|
||||||
|
# Move to "outside" of lookback window, so original sorting is restored.
|
||||||
|
t.move_to("2021-09-01 07:00:00 +00:00")
|
||||||
|
pm.refresh_pairlist()
|
||||||
|
assert pm.whitelist == ['ETH/USDT', 'LTC/USDT', 'XRP/USDT',
|
||||||
|
'NEO/USDT', 'TKN/USDT', 'ADA/USDT', 'ETC/USDT']
|
||||||
|
|
||||||
|
|
||||||
def test_gen_pair_whitelist_not_supported(mocker, default_conf, tickers) -> None:
|
def test_gen_pair_whitelist_not_supported(mocker, default_conf, tickers) -> None:
|
||||||
@ -1170,13 +1197,13 @@ def test_pairlistmanager_no_pairlist(mocker, whitelist_conf):
|
|||||||
{'pair': 'TKN/BTC', 'profit_ratio': -0.0501, 'count': 2},
|
{'pair': 'TKN/BTC', 'profit_ratio': -0.0501, 'count': 2},
|
||||||
{'pair': 'ETH/BTC', 'profit_ratio': -0.0501, 'count': 100}],
|
{'pair': 'ETH/BTC', 'profit_ratio': -0.0501, 'count': 100}],
|
||||||
['TKN/BTC', 'ETH/BTC', 'LTC/BTC']),
|
['TKN/BTC', 'ETH/BTC', 'LTC/BTC']),
|
||||||
# Tie in performance and count, broken by alphabetical sort
|
# Tie in performance and count, broken by prior sorting sort
|
||||||
([{"method": "StaticPairList"}, {"method": "PerformanceFilter"}],
|
([{"method": "StaticPairList"}, {"method": "PerformanceFilter"}],
|
||||||
['ETH/BTC', 'TKN/BTC', 'LTC/BTC'],
|
['ETH/BTC', 'TKN/BTC', 'LTC/BTC'],
|
||||||
[{'pair': 'LTC/BTC', 'profit_ratio': -0.0501, 'count': 1},
|
[{'pair': 'LTC/BTC', 'profit_ratio': -0.0501, 'count': 1},
|
||||||
{'pair': 'TKN/BTC', 'profit_ratio': -0.0501, 'count': 1},
|
{'pair': 'TKN/BTC', 'profit_ratio': -0.0501, 'count': 1},
|
||||||
{'pair': 'ETH/BTC', 'profit_ratio': -0.0501, 'count': 1}],
|
{'pair': 'ETH/BTC', 'profit_ratio': -0.0501, 'count': 1}],
|
||||||
['ETH/BTC', 'LTC/BTC', 'TKN/BTC']),
|
['ETH/BTC', 'TKN/BTC', 'LTC/BTC']),
|
||||||
])
|
])
|
||||||
def test_performance_filter(mocker, whitelist_conf, pairlists, pair_allowlist, overall_performance,
|
def test_performance_filter(mocker, whitelist_conf, pairlists, pair_allowlist, overall_performance,
|
||||||
allowlist_result, tickers, markets, ohlcv_history_list):
|
allowlist_result, tickers, markets, ohlcv_history_list):
|
||||||
|
Loading…
Reference in New Issue
Block a user