Add deep_merge for _ft_has and test
This commit is contained in:
parent
9c497bf15c
commit
7108a2e57d
@ -2,23 +2,24 @@
|
|||||||
"""
|
"""
|
||||||
Cryptocurrency Exchanges support
|
Cryptocurrency Exchanges support
|
||||||
"""
|
"""
|
||||||
import logging
|
import asyncio
|
||||||
import inspect
|
import inspect
|
||||||
from random import randint
|
import logging
|
||||||
from typing import List, Dict, Tuple, Any, Optional
|
from copy import deepcopy
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from math import floor, ceil
|
from math import ceil, floor
|
||||||
|
from random import randint
|
||||||
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
import arrow
|
import arrow
|
||||||
import asyncio
|
|
||||||
import ccxt
|
import ccxt
|
||||||
import ccxt.async_support as ccxt_async
|
import ccxt.async_support as ccxt_async
|
||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
|
|
||||||
from freqtrade import (constants, DependencyException, OperationalException,
|
from freqtrade import (DependencyException, InvalidOrderException,
|
||||||
TemporaryError, InvalidOrderException)
|
OperationalException, TemporaryError, constants)
|
||||||
from freqtrade.data.converter import parse_ticker_dataframe
|
from freqtrade.data.converter import parse_ticker_dataframe
|
||||||
|
from freqtrade.misc import deep_merge_dicts
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -68,12 +69,13 @@ class Exchange(object):
|
|||||||
_params: Dict = {}
|
_params: Dict = {}
|
||||||
|
|
||||||
# Dict to specify which options each exchange implements
|
# Dict to specify which options each exchange implements
|
||||||
# TODO: this should be merged with attributes from subclasses
|
# This defines defaults, which can be selectively overridden by subclasses using _ft_has
|
||||||
# To avoid having to copy/paste this to all subclasses.
|
# or by specifying them in the configuration.
|
||||||
_ft_has: Dict = {
|
_ft_has_default: Dict = {
|
||||||
"stoploss_on_exchange": False,
|
"stoploss_on_exchange": False,
|
||||||
"order_time_in_force": ["gtc"],
|
"order_time_in_force": ["gtc"],
|
||||||
}
|
}
|
||||||
|
_ft_has: Dict = {}
|
||||||
|
|
||||||
def __init__(self, config: dict) -> None:
|
def __init__(self, config: dict) -> None:
|
||||||
"""
|
"""
|
||||||
@ -100,6 +102,13 @@ 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']
|
||||||
|
|
||||||
|
# Deep merge ft_has with default ft_has options
|
||||||
|
self._ft_has = deep_merge_dicts(self._ft_has, deepcopy(self._ft_has_default))
|
||||||
|
if exchange_config.get("_ft_has_params"):
|
||||||
|
self._ft_has = deep_merge_dicts(exchange_config.get("_ft_has_params"),
|
||||||
|
self._ft_has)
|
||||||
|
|
||||||
self._api: ccxt.Exchange = self._init_ccxt(
|
self._api: ccxt.Exchange = self._init_ccxt(
|
||||||
exchange_config, ccxt_kwargs=exchange_config.get('ccxt_config'))
|
exchange_config, ccxt_kwargs=exchange_config.get('ccxt_config'))
|
||||||
self._api_async: ccxt_async.Exchange = self._init_ccxt(
|
self._api_async: ccxt_async.Exchange = self._init_ccxt(
|
||||||
|
@ -1435,3 +1435,30 @@ def test_stoploss_limit_order_dry_run(default_conf, mocker):
|
|||||||
assert order['type'] == order_type
|
assert order['type'] == order_type
|
||||||
assert order['price'] == 220
|
assert order['price'] == 220
|
||||||
assert order['amount'] == 1
|
assert order['amount'] == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_merge_ft_has_dict(default_conf, mocker):
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=MagicMock()))
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange._load_async_markets', MagicMock())
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock())
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
|
||||||
|
ex = Exchange(default_conf)
|
||||||
|
assert ex._ft_has == Exchange._ft_has_default
|
||||||
|
|
||||||
|
ex = Kraken(default_conf)
|
||||||
|
assert ex._ft_has == Exchange._ft_has_default
|
||||||
|
|
||||||
|
# Binance defines different values
|
||||||
|
ex = Binance(default_conf)
|
||||||
|
assert ex._ft_has != Exchange._ft_has_default
|
||||||
|
assert ex._ft_has['stoploss_on_exchange']
|
||||||
|
assert ex._ft_has['order_time_in_force'] == ['gtc', 'fok', 'ioc']
|
||||||
|
|
||||||
|
conf = copy.deepcopy(default_conf)
|
||||||
|
conf['exchange']['_ft_has_params'] = {"DeadBeef": 20,
|
||||||
|
"stoploss_on_exchange": False}
|
||||||
|
# Use settings from configuration (overriding stoploss_on_exchange)
|
||||||
|
ex = Binance(conf)
|
||||||
|
assert ex._ft_has != Exchange._ft_has_default
|
||||||
|
assert not ex._ft_has['stoploss_on_exchange']
|
||||||
|
assert ex._ft_has['DeadBeef'] == 20
|
||||||
|
Loading…
Reference in New Issue
Block a user