define constants on module level (#596)
This commit is contained in:
		| @@ -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', | ||||
|         ) | ||||
|   | ||||
| @@ -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]: | ||||
|   | ||||
| @@ -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' | ||||
|     ] | ||||
| } | ||||
|   | ||||
| @@ -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}' | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user