use normal program flow to handle interrupts
This commit is contained in:
@@ -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__':
|
||||
|
Reference in New Issue
Block a user