use normal program flow to handle interrupts

This commit is contained in:
gcarq
2017-11-20 22:15:19 +01:00
parent 1931d31147
commit 55a69e4a45
7 changed files with 78 additions and 60 deletions

View File

@@ -6,16 +6,16 @@ import sys
import time
import traceback
from datetime import datetime
from signal import signal, SIGINT, SIGABRT, SIGTERM
from typing import Dict, Optional, List
import requests
from cachetools import cached, TTLCache
from freqtrade import __version__, exchange, persistence, rpc
from freqtrade import __version__, exchange, persistence, rpc, DependencyException, \
OperationalException
from freqtrade.analyze import get_signal, SignalType
from freqtrade.misc import State, get_state, update_state, parse_args, throttle, \
load_config, FreqtradeException
load_config
from freqtrade.persistence import Trade
logger = logging.getLogger('freqtrade')
@@ -76,7 +76,7 @@ def _process(dynamic_whitelist: Optional[bool] = False) -> bool:
'Checked all whitelisted currencies. '
'Found no suitable entry positions for buying. Will keep looking ...'
)
except FreqtradeException as e:
except DependencyException as e:
logger.warning('Unable to create trade: %s', e)
for trade in trades:
@@ -97,12 +97,12 @@ def _process(dynamic_whitelist: Optional[bool] = False) -> bool:
error
)
time.sleep(30)
except RuntimeError:
rpc.send_msg('*Status:* Got RuntimeError:\n```\n{traceback}```{hint}'.format(
except OperationalException:
rpc.send_msg('*Status:* Got OperationalException:\n```\n{traceback}```{hint}'.format(
traceback=traceback.format_exc(),
hint='Issue `/start` if you think it is safe to restart.'
))
logger.exception('Got RuntimeError. Stopping trader ...')
logger.exception('Got OperationalException. Stopping trader ...')
update_state(State.STOPPED)
return state_changed
@@ -185,7 +185,7 @@ def create_trade(stake_amount: float) -> Optional[Trade]:
whitelist = copy.deepcopy(_CONF['exchange']['pair_whitelist'])
# Check if stake_amount is fulfilled
if exchange.get_balance(_CONF['stake_currency']) < stake_amount:
raise FreqtradeException(
raise DependencyException(
'stake amount is not fulfilled (currency={})'.format(_CONF['stake_currency'])
)
@@ -195,7 +195,7 @@ def create_trade(stake_amount: float) -> Optional[Trade]:
whitelist.remove(trade.pair)
logger.debug('Ignoring %s in pair whitelist', trade.pair)
if not whitelist:
raise FreqtradeException('No pair in whitelist')
raise DependencyException('No pair in whitelist')
# Pick pair based on StochRSI buy signals
for _pair in whitelist:
@@ -248,10 +248,6 @@ def init(config: dict, db_url: Optional[str] = None) -> None:
else:
update_state(State.STOPPED)
# Register signal handlers
for sig in (SIGINT, SIGTERM, SIGABRT):
signal(sig, cleanup)
@cached(TTLCache(maxsize=1, ttl=1800))
def gen_pair_whitelist(base_currency: str, topn: int = 20, key: str = 'BaseVolume') -> List[str]:
@@ -270,7 +266,7 @@ def gen_pair_whitelist(base_currency: str, topn: int = 20, key: str = 'BaseVolum
return [s['MarketName'].replace('-', '_') for s in summaries[:topn]]
def cleanup(*args, **kwargs) -> None:
def cleanup() -> None:
"""
Cleanup the application state und finish all pending tasks
:return: None
@@ -283,7 +279,7 @@ def cleanup(*args, **kwargs) -> None:
exit(0)
def main():
def main() -> None:
"""
Loads and validates the config and handles the main loop
:return: None
@@ -311,24 +307,33 @@ def main():
# Initialize all modules and start main loop
if args.dynamic_whitelist:
logger.info('Using dynamically generated whitelist. (--dynamic-whitelist detected)')
init(_CONF)
old_state = None
while True:
new_state = get_state()
# Log state transition
if new_state != old_state:
rpc.send_msg('*Status:* `{}`'.format(new_state.name.lower()))
logger.info('Changing state to: %s', new_state.name)
if new_state == State.STOPPED:
time.sleep(1)
elif new_state == State.RUNNING:
throttle(
_process,
min_secs=_CONF['internals'].get('process_throttle_secs', 10),
dynamic_whitelist=args.dynamic_whitelist,
)
old_state = new_state
try:
init(_CONF)
old_state = None
while True:
new_state = get_state()
# Log state transition
if new_state != old_state:
rpc.send_msg('*Status:* `{}`'.format(new_state.name.lower()))
logger.info('Changing state to: %s', new_state.name)
if new_state == State.STOPPED:
time.sleep(1)
elif new_state == State.RUNNING:
throttle(
_process,
min_secs=_CONF['internals'].get('process_throttle_secs', 10),
dynamic_whitelist=args.dynamic_whitelist,
)
old_state = new_state
except RuntimeError:
logger.exception('Got fatal exception!')
except KeyboardInterrupt:
logger.info('Got SIGINT, aborting ...')
finally:
cleanup()
if __name__ == '__main__':