[1/3] Add support for multiple exchanges with ccxt (objectified version) (#585)

* remove obsolete helper functions and make _state a public member.

* remove function assertions

* revert worker() changes

* Update pytest from 3.4.2 to 3.5.0

* Adapt exchange functions to ccxt API
Remove get_market_summaries and get_wallet_health, add exception handling

* Add NetworkException

* Change pair format in constants.py

* Add tests for exchange functions that comply with ccxt

* Remove bittrex tests

* Remove Bittrex and Interface classes

* Add retrier decorator

* Remove cache from get_ticker

* Remove unused and duplicate imports

* Add keyword arguments for get_fee

* Implement 'get_pair_detail_url'

* Change get_ticker_history format to ccxt format

* Fix exchange urls dict, don't need to initialize exchanges

* Add "Using Exchange ..." logging line
This commit is contained in:
enenn
2018-04-06 09:57:08 +02:00
committed by Samuel Husso
parent f3847a3a9a
commit 1f75636e56
12 changed files with 586 additions and 486 deletions

View File

@@ -41,7 +41,7 @@ class FreqtradeBot(object):
self.logger = Logger(name=__name__, level=config.get('loglevel')).get_logger()
# Init bot states
self._state = State.STOPPED
self.state = State.STOPPED
# Init objects
self.config = config
@@ -71,9 +71,9 @@ class FreqtradeBot(object):
initial_state = self.config.get('initial_state')
if initial_state:
self.update_state(State[initial_state.upper()])
self.state = State[initial_state.upper()]
else:
self.update_state(State.STOPPED)
self.state = State.STOPPED
def clean(self) -> bool:
"""
@@ -82,41 +82,26 @@ class FreqtradeBot(object):
"""
self.rpc.send_msg('*Status:* `Stopping trader...`')
self.logger.info('Stopping trader and cleaning up modules...')
self.update_state(State.STOPPED)
self.state = State.STOPPED
self.rpc.cleanup()
persistence.cleanup()
return True
def update_state(self, state: State) -> None:
"""
Updates the application state
:param state: new state
:return: None
"""
self._state = state
def get_state(self) -> State:
"""
Gets the current application state
:return:
"""
return self._state
def worker(self, old_state: None) -> State:
"""
Trading routine that must be run at each loop
:param old_state: the previous service state from the previous call
:return: current service state
"""
new_state = self.get_state()
# Log state transition
if new_state != old_state:
self.rpc.send_msg('*Status:* `{}`'.format(new_state.name.lower()))
self.logger.info('Changing state to: %s', new_state.name)
state = self.state
if state != old_state:
self.rpc.send_msg('*Status:* `{}`'.format(state.name.lower()))
self.logger.info('Changing state to: %s', state.name)
if new_state == State.STOPPED:
if state == State.STOPPED:
time.sleep(1)
elif new_state == State.RUNNING:
elif state == State.RUNNING:
min_secs = self.config.get('internals', {}).get(
'process_throttle_secs',
Constants.PROCESS_THROTTLE_SECS
@@ -130,7 +115,7 @@ class FreqtradeBot(object):
self._throttle(func=self._process,
min_secs=min_secs,
nb_assets=nb_assets)
return new_state
return state
def _throttle(self, func: Callable[..., Any], min_secs: float, *args, **kwargs) -> Any:
"""
@@ -196,7 +181,7 @@ class FreqtradeBot(object):
)
)
self.logger.exception('OperationalException. Stopping trader ...')
self.update_state(State.STOPPED)
self.state = State.STOPPED
return state_changed
@cached(TTLCache(maxsize=1, ttl=1800))
@@ -483,8 +468,8 @@ class FreqtradeBot(object):
fmt_exp_profit = round(trade.calc_profit_percent(rate=limit) * 100, 2)
profit_trade = trade.calc_profit(rate=limit)
current_rate = exchange.get_ticker(trade.pair, False)['bid']
profit = trade.calc_profit_percent(current_rate)
current_rate = exchange.get_ticker(trade.pair)['bid']
profit = trade.calc_profit_percent(limit)
message = "*{exchange}:* Selling\n" \
"*Current Pair:* [{pair}]({pair_url})\n" \