Merge pull request #173 from glonlas/autoselect_top_currencies

Allow to change the number of currencies used by dynamic-whitelist
This commit is contained in:
Janne Sinivirta 2017-12-11 18:04:10 +02:00 committed by GitHub
commit b77fad6e5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 14 deletions

View File

@ -154,11 +154,32 @@ optional arguments:
specify configuration file (default: config.json) specify configuration file (default: config.json)
-v, --verbose be verbose -v, --verbose be verbose
--version show program's version number and exit --version show program's version number and exit
--dynamic-whitelist dynamically generate and update whitelist based on 24h --dynamic-whitelist INT dynamically generate and update whitelist based on 24h
BaseVolume BaseVolume (Default 20 currencies)
``` ```
#### Dynamic whitelist example
Per default `--dynamic-whitelist` will retrieve the 20 currencies based
on BaseVolume. This value can be changed when you run the script.
**By Default**
Get the 20 currencies based on BaseVolume.
```bash
freqtrade --dynamic-whitelist
```
**Customize the number of currencies to retrieve**
Get the 30 currencies based on BaseVolume.
```bash
freqtrade --dynamic-whitelist 30
```
**Exception**
`--dynamic-whitelist` must be greater than 0. If you enter 0 or a
negative value (e.g -2), `--dynamic-whitelist` will use the default
value (20).
### Backtesting ### Backtesting
Backtesting also uses the config specified via `-c/--config`. Backtesting also uses the config specified via `-c/--config`.

View File

@ -49,7 +49,7 @@ def refresh_whitelist(whitelist: Optional[List[str]] = None) -> None:
_CONF['exchange']['pair_whitelist'] = sanitized_whitelist _CONF['exchange']['pair_whitelist'] = sanitized_whitelist
def _process(dynamic_whitelist: Optional[bool] = False) -> bool: def _process(dynamic_whitelist: Optional[int] = 0) -> bool:
""" """
Queries the persistence layer for open trades and handles them, Queries the persistence layer for open trades and handles them,
otherwise a new trade is created. otherwise a new trade is created.
@ -60,7 +60,7 @@ def _process(dynamic_whitelist: Optional[bool] = False) -> bool:
try: try:
# Refresh whitelist based on wallet maintenance # Refresh whitelist based on wallet maintenance
refresh_whitelist( refresh_whitelist(
gen_pair_whitelist(_CONF['stake_currency']) if dynamic_whitelist else None gen_pair_whitelist(_CONF['stake_currency'], topn = dynamic_whitelist) if dynamic_whitelist else None
) )
# Query trades from persistence layer # Query trades from persistence layer
trades = Trade.query.filter(Trade.is_open.is_(True)).all() trades = Trade.query.filter(Trade.is_open.is_(True)).all()
@ -266,7 +266,7 @@ def gen_pair_whitelist(base_currency: str, topn: int = 20, key: str = 'BaseVolum
""" """
Updates the whitelist with with a dynamically generated list Updates the whitelist with with a dynamically generated list
:param base_currency: base currency as str :param base_currency: base currency as str
:param topn: maximum number of returned results :param topn: maximum number of returned results, must be greater than 0
:param key: sort key (defaults to 'BaseVolume') :param key: sort key (defaults to 'BaseVolume')
:return: List of pairs :return: List of pairs
""" """
@ -275,6 +275,11 @@ def gen_pair_whitelist(base_currency: str, topn: int = 20, key: str = 'BaseVolum
key=lambda s: s.get(key) or 0.0, key=lambda s: s.get(key) or 0.0,
reverse=True reverse=True
) )
# topn must be greater than 0
if not topn > 0:
topn = 20
return [s['MarketName'].replace('-', '_') for s in summaries[:topn]] return [s['MarketName'].replace('-', '_') for s in summaries[:topn]]

View File

@ -112,8 +112,12 @@ def parse_args(args: List[str]):
) )
parser.add_argument( parser.add_argument(
'--dynamic-whitelist', '--dynamic-whitelist',
help='dynamically generate and update whitelist based on 24h BaseVolume', help='dynamically generate and update whitelist based on 24h BaseVolume (Default 20 currencies)',
action='store_true', dest='dynamic_whitelist',
const=20,
type=int,
metavar='INT',
nargs='?',
) )
build_subcommands(parser) build_subcommands(parser)
parsed_args = parser.parse_args(args) parsed_args = parser.parse_args(args)

View File

@ -30,7 +30,7 @@ def test_parse_args_defaults():
args = parse_args([]) args = parse_args([])
assert args is not None assert args is not None
assert args.config == 'config.json' assert args.config == 'config.json'
assert args.dynamic_whitelist is False assert args.dynamic_whitelist is None
assert args.loglevel == 20 assert args.loglevel == 20
@ -58,7 +58,16 @@ def test_parse_args_verbose():
def test_parse_args_dynamic_whitelist(): def test_parse_args_dynamic_whitelist():
args = parse_args(['--dynamic-whitelist']) args = parse_args(['--dynamic-whitelist'])
assert args is not None assert args is not None
assert args.dynamic_whitelist is True assert args.dynamic_whitelist is 20
def test_parse_args_dynamic_whitelist_10():
args = parse_args(['--dynamic-whitelist', '10'])
assert args is not None
assert args.dynamic_whitelist is 10
def test_parse_args_dynamic_whitelist_invalid_values():
with pytest.raises(SystemExit, match=r'2'):
parse_args(['--dynamic-whitelist', 'abc'])
def test_parse_args_backtesting(mocker): def test_parse_args_backtesting(mocker):