Merge pull request #1257 from freqtrade/add_general_params
Add general ccxt configuration options
This commit is contained in:
commit
6dec05b2a5
@ -28,7 +28,10 @@
|
|||||||
"name": "bittrex",
|
"name": "bittrex",
|
||||||
"key": "your_exchange_key",
|
"key": "your_exchange_key",
|
||||||
"secret": "your_exchange_secret",
|
"secret": "your_exchange_secret",
|
||||||
"ccxt_rate_limit": true,
|
"ccxt_config": {"enableRateLimit": true},
|
||||||
|
"ccxt_async_config": {
|
||||||
|
"enableRateLimit": false
|
||||||
|
},
|
||||||
"pair_whitelist": [
|
"pair_whitelist": [
|
||||||
"ETH/BTC",
|
"ETH/BTC",
|
||||||
"LTC/BTC",
|
"LTC/BTC",
|
||||||
|
@ -37,7 +37,11 @@
|
|||||||
"name": "bittrex",
|
"name": "bittrex",
|
||||||
"key": "your_exchange_key",
|
"key": "your_exchange_key",
|
||||||
"secret": "your_exchange_secret",
|
"secret": "your_exchange_secret",
|
||||||
"ccxt_rate_limit": true,
|
"ccxt_config": {"enableRateLimit": true},
|
||||||
|
"ccxt_async_config": {
|
||||||
|
"enableRateLimit": false,
|
||||||
|
"aiohttp_trust_env": false
|
||||||
|
},
|
||||||
"pair_whitelist": [
|
"pair_whitelist": [
|
||||||
"ETH/BTC",
|
"ETH/BTC",
|
||||||
"LTC/BTC",
|
"LTC/BTC",
|
||||||
|
@ -44,7 +44,9 @@ The table below will list all configuration parameters.
|
|||||||
| `exchange.secret` | secret | No | API secret to use for the exchange. Only required when you are in production mode.
|
| `exchange.secret` | secret | No | API secret to use for the exchange. Only required when you are in production mode.
|
||||||
| `exchange.pair_whitelist` | [] | No | List of currency to use by the bot. Can be overrided with `--dynamic-whitelist` param.
|
| `exchange.pair_whitelist` | [] | No | List of currency to use by the bot. Can be overrided with `--dynamic-whitelist` param.
|
||||||
| `exchange.pair_blacklist` | [] | No | List of currency the bot must avoid. Useful when using `--dynamic-whitelist` param.
|
| `exchange.pair_blacklist` | [] | No | List of currency the bot must avoid. Useful when using `--dynamic-whitelist` param.
|
||||||
| `exchange.ccxt_rate_limit` | True | No | Have CCXT handle Exchange rate limits. Depending on the exchange, having this to false can lead to temporary bans from the exchange.
|
| `exchange.ccxt_rate_limit` | True | No | DEPRECATED!! Have CCXT handle Exchange rate limits. Depending on the exchange, having this to false can lead to temporary bans from the exchange.
|
||||||
|
| `exchange.ccxt_config` | None | No | Additional CCXT parameters passed to the regular ccxt instance. Parameters may differ from exchange to exchange and are documented in the [ccxt documentation](https://ccxt.readthedocs.io/en/latest/manual.html#instantiation)
|
||||||
|
| `exchange.ccxt_async_config` | None | No | Additional CCXT parameters passed to the async ccxt instance. Parameters may differ from exchange to exchange and are documented in the [ccxt documentation](https://ccxt.readthedocs.io/en/latest/manual.html#instantiation)
|
||||||
| `experimental.use_sell_signal` | false | No | Use your sell strategy in addition of the `minimal_roi`.
|
| `experimental.use_sell_signal` | false | No | Use your sell strategy in addition of the `minimal_roi`.
|
||||||
| `experimental.sell_profit_only` | false | No | waits until you have made a positive profit before taking a sell decision.
|
| `experimental.sell_profit_only` | false | No | waits until you have made a positive profit before taking a sell decision.
|
||||||
| `experimental.ignore_roi_if_buy_signal` | false | No | Does not sell if the buy-signal is still active. Takes preference over `minimal_roi` and `use_sell_signal`
|
| `experimental.ignore_roi_if_buy_signal` | false | No | Does not sell if the buy-signal is still active. Takes preference over `minimal_roi` and `use_sell_signal`
|
||||||
@ -204,8 +206,29 @@ you run it in production mode.
|
|||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If you have not your Bittrex API key yet, [see our tutorial](https://github.com/freqtrade/freqtrade/blob/develop/docs/pre-requisite.md).
|
If you have not your Bittrex API key yet, [see our tutorial](https://github.com/freqtrade/freqtrade/blob/develop/docs/pre-requisite.md).
|
||||||
|
|
||||||
|
### Using proxy with FreqTrade
|
||||||
|
|
||||||
|
To use a proxy with freqtrade, add the kwarg `"aiohttp_trust_env"=true` to the `"ccxt_async_kwargs"` dict in the exchange section of the configuration.
|
||||||
|
|
||||||
|
An example for this can be found in `config_full.json.example`
|
||||||
|
|
||||||
|
``` json
|
||||||
|
"ccxt_async_config": {
|
||||||
|
"aiohttp_trust_env": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, export your proxy settings using the variables `"HTTP_PROXY"` and `"HTTPS_PROXY"` set to the appropriate values
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
export HTTP_PROXY="http://addr:port"
|
||||||
|
export HTTPS_PROXY="http://addr:port"
|
||||||
|
freqtrade
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### Embedding Strategies
|
### Embedding Strategies
|
||||||
|
|
||||||
@ -213,7 +236,7 @@ FreqTrade provides you with with an easy way to embed the strategy into your con
|
|||||||
This is done by utilizing BASE64 encoding and providing this string at the strategy configuration field,
|
This is done by utilizing BASE64 encoding and providing this string at the strategy configuration field,
|
||||||
in your chosen config file.
|
in your chosen config file.
|
||||||
|
|
||||||
##### Encoding a string as BASE64
|
#### Encoding a string as BASE64
|
||||||
|
|
||||||
This is a quick example, how to generate the BASE64 string in python
|
This is a quick example, how to generate the BASE64 string in python
|
||||||
|
|
||||||
|
@ -129,9 +129,3 @@ Day Profit BTC Profit USD
|
|||||||
## /version
|
## /version
|
||||||
> **Version:** `0.14.3`
|
> **Version:** `0.14.3`
|
||||||
|
|
||||||
### using proxy with telegram
|
|
||||||
```
|
|
||||||
$ export HTTP_PROXY="http://addr:port"
|
|
||||||
$ export HTTPS_PROXY="http://addr:port"
|
|
||||||
$ freqtrade
|
|
||||||
```
|
|
||||||
|
@ -271,6 +271,11 @@ class Configuration(object):
|
|||||||
raise OperationalException(
|
raise OperationalException(
|
||||||
exception_msg
|
exception_msg
|
||||||
)
|
)
|
||||||
|
# Depreciation warning
|
||||||
|
if 'ccxt_rate_limit' in config.get('exchange', {}):
|
||||||
|
logger.warning("`ccxt_rate_limit` has been deprecated in favor of "
|
||||||
|
"`ccxt_config` and `ccxt_async_config` and will be removed "
|
||||||
|
"in a future version.")
|
||||||
|
|
||||||
logger.debug('Exchange "%s" supported', exchange)
|
logger.debug('Exchange "%s" supported', exchange)
|
||||||
return True
|
return True
|
||||||
|
@ -164,7 +164,9 @@ CONF_SCHEMA = {
|
|||||||
},
|
},
|
||||||
'uniqueItems': True
|
'uniqueItems': True
|
||||||
},
|
},
|
||||||
'outdated_offset': {'type': 'integer', 'minimum': 1}
|
'outdated_offset': {'type': 'integer', 'minimum': 1},
|
||||||
|
'ccxt_config': {'type': 'object'},
|
||||||
|
'ccxt_async_config': {'type': 'object'}
|
||||||
},
|
},
|
||||||
'required': ['name', 'key', 'secret', 'pair_whitelist']
|
'required': ['name', 'key', 'secret', 'pair_whitelist']
|
||||||
}
|
}
|
||||||
|
@ -93,8 +93,9 @@ class Exchange(object):
|
|||||||
logger.info('Instance is running with dry_run enabled')
|
logger.info('Instance is running with dry_run enabled')
|
||||||
|
|
||||||
exchange_config = config['exchange']
|
exchange_config = config['exchange']
|
||||||
self._api = self._init_ccxt(exchange_config)
|
self._api = self._init_ccxt(exchange_config, ccxt_kwargs=exchange_config.get('ccxt_config'))
|
||||||
self._api_async = self._init_ccxt(exchange_config, ccxt_async)
|
self._api_async = self._init_ccxt(exchange_config, ccxt_async,
|
||||||
|
ccxt_kwargs=exchange_config.get('ccxt_async_config'))
|
||||||
|
|
||||||
logger.info('Using Exchange "%s"', self.name)
|
logger.info('Using Exchange "%s"', self.name)
|
||||||
|
|
||||||
@ -114,7 +115,8 @@ class Exchange(object):
|
|||||||
if self._api_async and inspect.iscoroutinefunction(self._api_async.close):
|
if self._api_async and inspect.iscoroutinefunction(self._api_async.close):
|
||||||
asyncio.get_event_loop().run_until_complete(self._api_async.close())
|
asyncio.get_event_loop().run_until_complete(self._api_async.close())
|
||||||
|
|
||||||
def _init_ccxt(self, exchange_config: dict, ccxt_module=ccxt) -> ccxt.Exchange:
|
def _init_ccxt(self, exchange_config: dict, ccxt_module=ccxt,
|
||||||
|
ccxt_kwargs: dict = None) -> ccxt.Exchange:
|
||||||
"""
|
"""
|
||||||
Initialize ccxt with given config and return valid
|
Initialize ccxt with given config and return valid
|
||||||
ccxt instance.
|
ccxt instance.
|
||||||
@ -124,14 +126,20 @@ class Exchange(object):
|
|||||||
|
|
||||||
if name not in ccxt_module.exchanges:
|
if name not in ccxt_module.exchanges:
|
||||||
raise OperationalException(f'Exchange {name} is not supported')
|
raise OperationalException(f'Exchange {name} is not supported')
|
||||||
try:
|
|
||||||
api = getattr(ccxt_module, name.lower())({
|
ex_config = {
|
||||||
'apiKey': exchange_config.get('key'),
|
'apiKey': exchange_config.get('key'),
|
||||||
'secret': exchange_config.get('secret'),
|
'secret': exchange_config.get('secret'),
|
||||||
'password': exchange_config.get('password'),
|
'password': exchange_config.get('password'),
|
||||||
'uid': exchange_config.get('uid', ''),
|
'uid': exchange_config.get('uid', ''),
|
||||||
'enableRateLimit': exchange_config.get('ccxt_rate_limit', True)
|
'enableRateLimit': exchange_config.get('ccxt_rate_limit', True)
|
||||||
})
|
}
|
||||||
|
if ccxt_kwargs:
|
||||||
|
logger.info('Applying additional ccxt config: %s', ccxt_kwargs)
|
||||||
|
ex_config.update(ccxt_kwargs)
|
||||||
|
try:
|
||||||
|
|
||||||
|
api = getattr(ccxt_module, name.lower())(ex_config)
|
||||||
except (KeyError, AttributeError):
|
except (KeyError, AttributeError):
|
||||||
raise OperationalException(f'Exchange {name} is not supported')
|
raise OperationalException(f'Exchange {name} is not supported')
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# pragma pylint: disable=missing-docstring, C0103, bad-continuation, global-statement
|
# pragma pylint: disable=missing-docstring, C0103, bad-continuation, global-statement
|
||||||
# pragma pylint: disable=protected-access
|
# pragma pylint: disable=protected-access
|
||||||
|
import copy
|
||||||
import logging
|
import logging
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from random import randint
|
from random import randint
|
||||||
@ -56,6 +57,32 @@ def test_init(default_conf, mocker, caplog):
|
|||||||
assert log_has('Instance is running with dry_run enabled', caplog.record_tuples)
|
assert log_has('Instance is running with dry_run enabled', caplog.record_tuples)
|
||||||
|
|
||||||
|
|
||||||
|
def test_init_ccxt_kwargs(default_conf, mocker, caplog):
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange._load_markets', MagicMock(return_value={}))
|
||||||
|
caplog.set_level(logging.INFO)
|
||||||
|
conf = copy.deepcopy(default_conf)
|
||||||
|
conf['exchange']['ccxt_async_config'] = {'aiohttp_trust_env': True}
|
||||||
|
ex = Exchange(conf)
|
||||||
|
assert log_has("Applying additional ccxt config: {'aiohttp_trust_env': True}",
|
||||||
|
caplog.record_tuples)
|
||||||
|
assert ex._api_async.aiohttp_trust_env
|
||||||
|
assert not ex._api.aiohttp_trust_env
|
||||||
|
|
||||||
|
# Reset logging and config
|
||||||
|
caplog.clear()
|
||||||
|
conf = copy.deepcopy(default_conf)
|
||||||
|
conf['exchange']['ccxt_config'] = {'TestKWARG': 11}
|
||||||
|
ex = Exchange(conf)
|
||||||
|
assert not log_has("Applying additional ccxt config: {'aiohttp_trust_env': True}",
|
||||||
|
caplog.record_tuples)
|
||||||
|
assert not ex._api_async.aiohttp_trust_env
|
||||||
|
assert hasattr(ex._api, 'TestKWARG')
|
||||||
|
assert ex._api.TestKWARG == 11
|
||||||
|
assert not hasattr(ex._api_async, 'TestKWARG')
|
||||||
|
assert log_has("Applying additional ccxt config: {'TestKWARG': 11}",
|
||||||
|
caplog.record_tuples)
|
||||||
|
|
||||||
|
|
||||||
def test_destroy(default_conf, mocker, caplog):
|
def test_destroy(default_conf, mocker, caplog):
|
||||||
caplog.set_level(logging.DEBUG)
|
caplog.set_level(logging.DEBUG)
|
||||||
get_patched_exchange(mocker, default_conf)
|
get_patched_exchange(mocker, default_conf)
|
||||||
|
@ -371,7 +371,7 @@ def test_hyperopt_with_arguments(mocker, default_conf, caplog) -> None:
|
|||||||
assert log_has('Parameter -s/--spaces detected: [\'all\']', caplog.record_tuples)
|
assert log_has('Parameter -s/--spaces detected: [\'all\']', caplog.record_tuples)
|
||||||
|
|
||||||
|
|
||||||
def test_check_exchange(default_conf) -> None:
|
def test_check_exchange(default_conf, caplog) -> None:
|
||||||
configuration = Configuration(Namespace())
|
configuration = Configuration(Namespace())
|
||||||
|
|
||||||
# Test a valid exchange
|
# Test a valid exchange
|
||||||
@ -392,6 +392,15 @@ def test_check_exchange(default_conf) -> None:
|
|||||||
):
|
):
|
||||||
configuration.check_exchange(default_conf)
|
configuration.check_exchange(default_conf)
|
||||||
|
|
||||||
|
# Test ccxt_rate_limit depreciation
|
||||||
|
default_conf.get('exchange').update({'name': 'binance'})
|
||||||
|
default_conf['exchange']['ccxt_rate_limit'] = True
|
||||||
|
configuration.check_exchange(default_conf)
|
||||||
|
assert log_has("`ccxt_rate_limit` has been deprecated in favor of "
|
||||||
|
"`ccxt_config` and `ccxt_async_config` and will be removed "
|
||||||
|
"in a future version.",
|
||||||
|
caplog.record_tuples)
|
||||||
|
|
||||||
|
|
||||||
def test_cli_verbose_with_params(default_conf, mocker, caplog) -> None:
|
def test_cli_verbose_with_params(default_conf, mocker, caplog) -> None:
|
||||||
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
||||||
|
@ -10,7 +10,14 @@ from freqtrade import arguments
|
|||||||
from freqtrade.arguments import TimeRange
|
from freqtrade.arguments import TimeRange
|
||||||
from freqtrade.exchange import Exchange
|
from freqtrade.exchange import Exchange
|
||||||
from freqtrade.optimize import download_backtesting_testdata
|
from freqtrade.optimize import download_backtesting_testdata
|
||||||
|
from freqtrade.configuration import set_loggers
|
||||||
|
|
||||||
|
import logging
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||||
|
)
|
||||||
|
set_loggers(0)
|
||||||
|
|
||||||
DEFAULT_DL_PATH = 'user_data/data'
|
DEFAULT_DL_PATH = 'user_data/data'
|
||||||
|
|
||||||
@ -54,7 +61,9 @@ exchange = Exchange({'key': '',
|
|||||||
'exchange': {
|
'exchange': {
|
||||||
'name': args.exchange,
|
'name': args.exchange,
|
||||||
'pair_whitelist': [],
|
'pair_whitelist': [],
|
||||||
'ccxt_rate_limit': False
|
'ccxt_async_config': {
|
||||||
|
"enableRateLimit": False
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
pairs_not_available = []
|
pairs_not_available = []
|
||||||
|
Loading…
Reference in New Issue
Block a user