From 9019f6492f8efb9b8eaf4bf60dab49313d16a6e2 Mon Sep 17 00:00:00 2001 From: Michael Egger Date: Mon, 2 Apr 2018 16:42:53 +0200 Subject: [PATCH] define constants on module level (#596) --- freqtrade/arguments.py | 7 +- freqtrade/configuration.py | 8 +- freqtrade/constants.py | 218 +++++++++++++++--------------- freqtrade/freqtradebot.py | 6 +- freqtrade/strategy/resolver.py | 4 +- freqtrade/tests/conftest.py | 4 +- freqtrade/tests/test_constants.py | 19 ++- 7 files changed, 129 insertions(+), 137 deletions(-) diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index 35f8c6609..791ef85f2 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -8,8 +8,7 @@ import os import re from typing import List, Tuple, Optional -from freqtrade import __version__ -from freqtrade.constants import Constants +from freqtrade import __version__, constants class Arguments(object): @@ -98,7 +97,7 @@ class Arguments(object): help='dynamically generate and update whitelist \ based on 24h BaseVolume (Default 20 currencies)', # noqa dest='dynamic_whitelist', - const=Constants.DYNAMIC_WHITELIST, + const=constants.DYNAMIC_WHITELIST, type=int, metavar='INT', nargs='?', @@ -170,7 +169,7 @@ class Arguments(object): '-e', '--epochs', help='specify number of epochs (default: %(default)d)', dest='epochs', - default=Constants.HYPEROPT_EPOCH, + default=constants.HYPEROPT_EPOCH, type=int, metavar='INT', ) diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index 4922bf402..fd9f31ad2 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -10,7 +10,7 @@ from typing import Dict, Any from jsonschema import Draft4Validator, validate from jsonschema.exceptions import ValidationError, best_match -from freqtrade.constants import Constants +from freqtrade import constants logger = logging.getLogger(__name__) @@ -34,7 +34,7 @@ class Configuration(object): config = self._load_config_file(self.args.config) # Set strategy if not specified in config and or if it's non default - if self.args.strategy != Constants.DEFAULT_STRATEGY or not config.get('strategy'): + if self.args.strategy != constants.DEFAULT_STRATEGY or not config.get('strategy'): config.update({'strategy': self.args.strategy}) if self.args.strategy_path: @@ -186,7 +186,7 @@ class Configuration(object): :return: Returns the config if valid, otherwise throw an exception """ try: - validate(conf, Constants.CONF_SCHEMA) + validate(conf, constants.CONF_SCHEMA) return conf except ValidationError as exception: logger.fatal( @@ -194,7 +194,7 @@ class Configuration(object): exception ) raise ValidationError( - best_match(Draft4Validator(Constants.CONF_SCHEMA).iter_errors(conf)).message + best_match(Draft4Validator(constants.CONF_SCHEMA).iter_errors(conf)).message ) def get_config(self) -> Dict[str, Any]: diff --git a/freqtrade/constants.py b/freqtrade/constants.py index 61adf307a..382f19ef1 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -1,122 +1,116 @@ # pragma pylint: disable=too-few-public-methods """ -List bot constants +bot constants """ +DYNAMIC_WHITELIST = 20 # pairs +PROCESS_THROTTLE_SECS = 5 # sec +TICKER_INTERVAL = 5 # min +HYPEROPT_EPOCH = 100 # epochs +RETRY_TIMEOUT = 30 # sec +DEFAULT_STRATEGY = 'DefaultStrategy' - -class Constants(object): - """ - Static class that contain all bot constants - """ - DYNAMIC_WHITELIST = 20 # pairs - PROCESS_THROTTLE_SECS = 5 # sec - TICKER_INTERVAL = 5 # min - HYPEROPT_EPOCH = 100 # epochs - RETRY_TIMEOUT = 30 # sec - DEFAULT_STRATEGY = 'DefaultStrategy' - - # Required json-schema for user specified config - CONF_SCHEMA = { - 'type': 'object', - 'properties': { - 'max_open_trades': {'type': 'integer', 'minimum': 1}, - 'ticker_interval': {'type': 'integer', 'enum': [1, 5, 30, 60, 1440]}, - 'stake_currency': {'type': 'string', 'enum': ['BTC', 'ETH', 'USDT']}, - 'stake_amount': {'type': 'number', 'minimum': 0.0005}, - 'fiat_display_currency': {'type': 'string', 'enum': ['AUD', 'BRL', 'CAD', 'CHF', - 'CLP', 'CNY', 'CZK', 'DKK', - 'EUR', 'GBP', 'HKD', 'HUF', - 'IDR', 'ILS', 'INR', 'JPY', - 'KRW', 'MXN', 'MYR', 'NOK', - 'NZD', 'PHP', 'PKR', 'PLN', - 'RUB', 'SEK', 'SGD', 'THB', - 'TRY', 'TWD', 'ZAR', 'USD']}, - 'dry_run': {'type': 'boolean'}, - 'minimal_roi': { - 'type': 'object', - 'patternProperties': { - '^[0-9.]+$': {'type': 'number'} +# Required json-schema for user specified config +CONF_SCHEMA = { + 'type': 'object', + 'properties': { + 'max_open_trades': {'type': 'integer', 'minimum': 1}, + 'ticker_interval': {'type': 'integer', 'enum': [1, 5, 30, 60, 1440]}, + 'stake_currency': {'type': 'string', 'enum': ['BTC', 'ETH', 'USDT']}, + 'stake_amount': {'type': 'number', 'minimum': 0.0005}, + 'fiat_display_currency': {'type': 'string', 'enum': ['AUD', 'BRL', 'CAD', 'CHF', + 'CLP', 'CNY', 'CZK', 'DKK', + 'EUR', 'GBP', 'HKD', 'HUF', + 'IDR', 'ILS', 'INR', 'JPY', + 'KRW', 'MXN', 'MYR', 'NOK', + 'NZD', 'PHP', 'PKR', 'PLN', + 'RUB', 'SEK', 'SGD', 'THB', + 'TRY', 'TWD', 'ZAR', 'USD']}, + 'dry_run': {'type': 'boolean'}, + 'minimal_roi': { + 'type': 'object', + 'patternProperties': { + '^[0-9.]+$': {'type': 'number'} + }, + 'minProperties': 1 + }, + 'stoploss': {'type': 'number', 'maximum': 0, 'exclusiveMaximum': True}, + 'unfilledtimeout': {'type': 'integer', 'minimum': 0}, + 'bid_strategy': { + 'type': 'object', + 'properties': { + 'ask_last_balance': { + 'type': 'number', + 'minimum': 0, + 'maximum': 1, + 'exclusiveMaximum': False }, - 'minProperties': 1 }, - 'stoploss': {'type': 'number', 'maximum': 0, 'exclusiveMaximum': True}, - 'unfilledtimeout': {'type': 'integer', 'minimum': 0}, - 'bid_strategy': { - 'type': 'object', - 'properties': { - 'ask_last_balance': { - 'type': 'number', - 'minimum': 0, - 'maximum': 1, - 'exclusiveMaximum': False - }, - }, - 'required': ['ask_last_balance'] - }, - 'exchange': {'$ref': '#/definitions/exchange'}, - 'experimental': { - 'type': 'object', - 'properties': { - 'use_sell_signal': {'type': 'boolean'}, - 'sell_profit_only': {'type': 'boolean'} - } - }, - 'telegram': { - 'type': 'object', - 'properties': { - 'enabled': {'type': 'boolean'}, - 'token': {'type': 'string'}, - 'chat_id': {'type': 'string'}, - }, - 'required': ['enabled', 'token', 'chat_id'] - }, - 'initial_state': {'type': 'string', 'enum': ['running', 'stopped']}, - 'internals': { - 'type': 'object', - 'properties': { - 'process_throttle_secs': {'type': 'number'}, - 'interval': {'type': 'integer'} - } + 'required': ['ask_last_balance'] + }, + 'exchange': {'$ref': '#/definitions/exchange'}, + 'experimental': { + 'type': 'object', + 'properties': { + 'use_sell_signal': {'type': 'boolean'}, + 'sell_profit_only': {'type': 'boolean'} } }, - 'definitions': { - 'exchange': { - 'type': 'object', - 'properties': { - 'name': {'type': 'string'}, - 'key': {'type': 'string'}, - 'secret': {'type': 'string'}, - 'pair_whitelist': { - 'type': 'array', - 'items': { - 'type': 'string', - 'pattern': '^[0-9A-Z]+_[0-9A-Z]+$' - }, - 'uniqueItems': True - }, - 'pair_blacklist': { - 'type': 'array', - 'items': { - 'type': 'string', - 'pattern': '^[0-9A-Z]+_[0-9A-Z]+$' - }, - 'uniqueItems': True - } - }, - 'required': ['name', 'key', 'secret', 'pair_whitelist'] - } + 'telegram': { + 'type': 'object', + 'properties': { + 'enabled': {'type': 'boolean'}, + 'token': {'type': 'string'}, + 'chat_id': {'type': 'string'}, + }, + 'required': ['enabled', 'token', 'chat_id'] }, - 'anyOf': [ - {'required': ['exchange']} - ], - 'required': [ - 'max_open_trades', - 'stake_currency', - 'stake_amount', - 'fiat_display_currency', - 'dry_run', - 'bid_strategy', - 'telegram' - ] - } + 'initial_state': {'type': 'string', 'enum': ['running', 'stopped']}, + 'internals': { + 'type': 'object', + 'properties': { + 'process_throttle_secs': {'type': 'number'}, + 'interval': {'type': 'integer'} + } + } + }, + 'definitions': { + 'exchange': { + 'type': 'object', + 'properties': { + 'name': {'type': 'string'}, + 'key': {'type': 'string'}, + 'secret': {'type': 'string'}, + 'pair_whitelist': { + 'type': 'array', + 'items': { + 'type': 'string', + 'pattern': '^[0-9A-Z]+_[0-9A-Z]+$' + }, + 'uniqueItems': True + }, + 'pair_blacklist': { + 'type': 'array', + 'items': { + 'type': 'string', + 'pattern': '^[0-9A-Z]+_[0-9A-Z]+$' + }, + 'uniqueItems': True + } + }, + 'required': ['name', 'key', 'secret', 'pair_whitelist'] + } + }, + 'anyOf': [ + {'required': ['exchange']} + ], + 'required': [ + 'max_open_trades', + 'stake_currency', + 'stake_amount', + 'fiat_display_currency', + 'dry_run', + 'bid_strategy', + 'telegram' + ] +} diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index f5de95826..0a730882c 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -18,7 +18,7 @@ from freqtrade import ( DependencyException, OperationalException, exchange, persistence, __version__ ) from freqtrade.analyze import Analyze -from freqtrade.constants import Constants +from freqtrade import constants from freqtrade.fiat_convert import CryptoToFiatConverter from freqtrade.persistence import Trade from freqtrade.rpc.rpc_manager import RPCManager @@ -111,7 +111,7 @@ class FreqtradeBot(object): elif state == State.RUNNING: min_secs = self.config.get('internals', {}).get( 'process_throttle_secs', - Constants.PROCESS_THROTTLE_SECS + constants.PROCESS_THROTTLE_SECS ) nb_assets = self.config.get('dynamic_whitelist', None) @@ -175,7 +175,7 @@ class FreqtradeBot(object): except (requests.exceptions.RequestException, json.JSONDecodeError) as error: logger.warning('%s, retrying in 30 seconds...', error) - time.sleep(Constants.RETRY_TIMEOUT) + time.sleep(constants.RETRY_TIMEOUT) except OperationalException: self.rpc.send_msg( '*Status:* OperationalException:\n```\n{traceback}```{hint}' diff --git a/freqtrade/strategy/resolver.py b/freqtrade/strategy/resolver.py index de38cf67a..bde852c92 100644 --- a/freqtrade/strategy/resolver.py +++ b/freqtrade/strategy/resolver.py @@ -10,7 +10,7 @@ import os from collections import OrderedDict from typing import Optional, Dict, Type -from freqtrade.constants import Constants +from freqtrade import constants from freqtrade.strategy.interface import IStrategy @@ -32,7 +32,7 @@ class StrategyResolver(object): config = config or {} # Verify the strategy is in the configuration, otherwise fallback to the default strategy - strategy_name = config.get('strategy') or Constants.DEFAULT_STRATEGY + strategy_name = config.get('strategy') or constants.DEFAULT_STRATEGY self.strategy = self._load_strategy(strategy_name, extra_dir=config.get('strategy_path')) # Set attributes diff --git a/freqtrade/tests/conftest.py b/freqtrade/tests/conftest.py index 07dc45a3e..48bfcaf89 100644 --- a/freqtrade/tests/conftest.py +++ b/freqtrade/tests/conftest.py @@ -12,7 +12,7 @@ from sqlalchemy import create_engine from telegram import Chat, Message, Update from freqtrade.analyze import Analyze -from freqtrade.constants import Constants +from freqtrade import constants from freqtrade.freqtradebot import FreqtradeBot logging.getLogger('').setLevel(logging.INFO) @@ -88,7 +88,7 @@ def default_conf(): "initial_state": "running", "loglevel": logging.DEBUG } - validate(configuration, Constants.CONF_SCHEMA) + validate(configuration, constants.CONF_SCHEMA) return configuration diff --git a/freqtrade/tests/test_constants.py b/freqtrade/tests/test_constants.py index 6d544502f..541c6e533 100644 --- a/freqtrade/tests/test_constants.py +++ b/freqtrade/tests/test_constants.py @@ -2,25 +2,24 @@ Unit test file for constants.py """ -from freqtrade.constants import Constants +from freqtrade import constants def test_constant_object() -> None: """ Test the Constants object has the mandatory Constants """ - assert hasattr(Constants, 'CONF_SCHEMA') - assert hasattr(Constants, 'DYNAMIC_WHITELIST') - assert hasattr(Constants, 'PROCESS_THROTTLE_SECS') - assert hasattr(Constants, 'TICKER_INTERVAL') - assert hasattr(Constants, 'HYPEROPT_EPOCH') - assert hasattr(Constants, 'RETRY_TIMEOUT') - assert hasattr(Constants, 'DEFAULT_STRATEGY') + assert hasattr(constants, 'CONF_SCHEMA') + assert hasattr(constants, 'DYNAMIC_WHITELIST') + assert hasattr(constants, 'PROCESS_THROTTLE_SECS') + assert hasattr(constants, 'TICKER_INTERVAL') + assert hasattr(constants, 'HYPEROPT_EPOCH') + assert hasattr(constants, 'RETRY_TIMEOUT') + assert hasattr(constants, 'DEFAULT_STRATEGY') def test_conf_schema() -> None: """ Test the CONF_SCHEMA is from the right type """ - constant = Constants() - assert isinstance(constant.CONF_SCHEMA, dict) + assert isinstance(constants.CONF_SCHEMA, dict)