diff --git a/freqtrade/configuration/config_schema.py b/freqtrade/configuration/config_schema.py new file mode 100644 index 000000000..aec0cb94a --- /dev/null +++ b/freqtrade/configuration/config_schema.py @@ -0,0 +1,623 @@ +# Required json-schema for user specified config +from typing import Dict + +from freqtrade.constants import ( + AVAILABLE_DATAHANDLERS, + AVAILABLE_PAIRLISTS, + AVAILABLE_PROTECTIONS, + BACKTEST_BREAKDOWNS, + DRY_RUN_WALLET, + EXPORT_OPTIONS, + MARGIN_MODES, + ORDERTIF_POSSIBILITIES, + ORDERTYPE_POSSIBILITIES, + PRICING_SIDES, + REQUIRED_ORDERTIF, + STOPLOSS_PRICE_TYPES, + SUPPORTED_FIAT, + TELEGRAM_SETTING_OPTIONS, + TIMEOUT_UNITS, + TRADING_MODES, + UNLIMITED_STAKE_AMOUNT, + WEBHOOK_FORMAT_OPTIONS, +) +from freqtrade.enums import RPCMessageType + + +__MESSAGE_TYPE_DICT: Dict[str, Dict[str, str]] = {x: {"type": "object"} for x in RPCMessageType} + +CONF_SCHEMA = { + "type": "object", + "properties": { + "max_open_trades": {"type": ["integer", "number"], "minimum": -1}, + "new_pairs_days": {"type": "integer", "default": 30}, + "timeframe": {"type": "string"}, + "stake_currency": {"type": "string"}, + "stake_amount": { + "type": ["number", "string"], + "minimum": 0.0001, + "pattern": UNLIMITED_STAKE_AMOUNT, + }, + "tradable_balance_ratio": {"type": "number", "minimum": 0.0, "maximum": 1, "default": 0.99}, + "available_capital": { + "type": "number", + "minimum": 0, + }, + "amend_last_stake_amount": {"type": "boolean", "default": False}, + "last_stake_amount_min_ratio": { + "type": "number", + "minimum": 0.0, + "maximum": 1.0, + "default": 0.5, + }, + "fiat_display_currency": {"type": "string", "enum": SUPPORTED_FIAT}, + "dry_run": {"type": "boolean"}, + "dry_run_wallet": {"type": "number", "default": DRY_RUN_WALLET}, + "cancel_open_orders_on_exit": {"type": "boolean", "default": False}, + "process_only_new_candles": {"type": "boolean"}, + "minimal_roi": { + "type": "object", + "patternProperties": {"^[0-9.]+$": {"type": "number"}}, + }, + "amount_reserve_percent": {"type": "number", "minimum": 0.0, "maximum": 0.5}, + "stoploss": {"type": "number", "maximum": 0, "exclusiveMaximum": True}, + "trailing_stop": {"type": "boolean"}, + "trailing_stop_positive": {"type": "number", "minimum": 0, "maximum": 1}, + "trailing_stop_positive_offset": {"type": "number", "minimum": 0, "maximum": 1}, + "trailing_only_offset_is_reached": {"type": "boolean"}, + "use_exit_signal": {"type": "boolean"}, + "exit_profit_only": {"type": "boolean"}, + "exit_profit_offset": {"type": "number"}, + "fee": {"type": "number", "minimum": 0, "maximum": 0.1}, + "ignore_roi_if_entry_signal": {"type": "boolean"}, + "ignore_buying_expired_candle_after": {"type": "number"}, + "trading_mode": {"type": "string", "enum": TRADING_MODES}, + "margin_mode": {"type": "string", "enum": MARGIN_MODES}, + "reduce_df_footprint": {"type": "boolean", "default": False}, + "minimum_trade_amount": {"type": "number", "default": 10}, + "targeted_trade_amount": {"type": "number", "default": 20}, + "lookahead_analysis_exportfilename": {"type": "string"}, + "startup_candle": { + "type": "array", + "uniqueItems": True, + "default": [199, 399, 499, 999, 1999], + }, + "liquidation_buffer": {"type": "number", "minimum": 0.0, "maximum": 0.99}, + "backtest_breakdown": { + "type": "array", + "items": {"type": "string", "enum": BACKTEST_BREAKDOWNS}, + }, + "bot_name": {"type": "string"}, + "unfilledtimeout": { + "type": "object", + "properties": { + "entry": {"type": "number", "minimum": 1}, + "exit": {"type": "number", "minimum": 1}, + "exit_timeout_count": {"type": "number", "minimum": 0, "default": 0}, + "unit": {"type": "string", "enum": TIMEOUT_UNITS, "default": "minutes"}, + }, + }, + "entry_pricing": { + "type": "object", + "properties": { + "price_last_balance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "exclusiveMaximum": False, + }, + "price_side": {"type": "string", "enum": PRICING_SIDES, "default": "same"}, + "use_order_book": {"type": "boolean"}, + "order_book_top": { + "type": "integer", + "minimum": 1, + "maximum": 50, + }, + "check_depth_of_market": { + "type": "object", + "properties": { + "enabled": {"type": "boolean"}, + "bids_to_ask_delta": {"type": "number", "minimum": 0}, + }, + }, + }, + "required": ["price_side"], + }, + "exit_pricing": { + "type": "object", + "properties": { + "price_side": {"type": "string", "enum": PRICING_SIDES, "default": "same"}, + "price_last_balance": { + "type": "number", + "minimum": 0, + "maximum": 1, + "exclusiveMaximum": False, + }, + "use_order_book": {"type": "boolean"}, + "order_book_top": { + "type": "integer", + "minimum": 1, + "maximum": 50, + }, + }, + "required": ["price_side"], + }, + "custom_price_max_distance_ratio": {"type": "number", "minimum": 0.0}, + "order_types": { + "type": "object", + "properties": { + "entry": {"type": "string", "enum": ORDERTYPE_POSSIBILITIES}, + "exit": {"type": "string", "enum": ORDERTYPE_POSSIBILITIES}, + "force_exit": {"type": "string", "enum": ORDERTYPE_POSSIBILITIES}, + "force_entry": {"type": "string", "enum": ORDERTYPE_POSSIBILITIES}, + "emergency_exit": { + "type": "string", + "enum": ORDERTYPE_POSSIBILITIES, + "default": "market", + }, + "stoploss": {"type": "string", "enum": ORDERTYPE_POSSIBILITIES}, + "stoploss_on_exchange": {"type": "boolean"}, + "stoploss_price_type": {"type": "string", "enum": STOPLOSS_PRICE_TYPES}, + "stoploss_on_exchange_interval": {"type": "number"}, + "stoploss_on_exchange_limit_ratio": { + "type": "number", + "minimum": 0.0, + "maximum": 1.0, + }, + }, + "required": ["entry", "exit", "stoploss", "stoploss_on_exchange"], + }, + "order_time_in_force": { + "type": "object", + "properties": { + "entry": {"type": "string", "enum": ORDERTIF_POSSIBILITIES}, + "exit": {"type": "string", "enum": ORDERTIF_POSSIBILITIES}, + }, + "required": REQUIRED_ORDERTIF, + }, + "coingecko": { + "type": "object", + "properties": { + "is_demo": {"type": "boolean", "default": True}, + "api_key": {"type": "string"}, + }, + "required": ["is_demo", "api_key"], + }, + "exchange": {"$ref": "#/definitions/exchange"}, + "edge": {"$ref": "#/definitions/edge"}, + "freqai": {"$ref": "#/definitions/freqai"}, + "external_message_consumer": {"$ref": "#/definitions/external_message_consumer"}, + "experimental": { + "type": "object", + "properties": {"block_bad_exchanges": {"type": "boolean"}}, + }, + "pairlists": { + "type": "array", + "items": { + "type": "object", + "properties": { + "method": {"type": "string", "enum": AVAILABLE_PAIRLISTS}, + }, + "required": ["method"], + }, + }, + "protections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "method": {"type": "string", "enum": AVAILABLE_PROTECTIONS}, + "stop_duration": {"type": "number", "minimum": 0.0}, + "stop_duration_candles": {"type": "number", "minimum": 0}, + "trade_limit": {"type": "number", "minimum": 1}, + "lookback_period": {"type": "number", "minimum": 1}, + "lookback_period_candles": {"type": "number", "minimum": 1}, + }, + "required": ["method"], + }, + }, + "telegram": { + "type": "object", + "properties": { + "enabled": {"type": "boolean"}, + "token": {"type": "string"}, + "chat_id": {"type": "string"}, + "allow_custom_messages": {"type": "boolean", "default": True}, + "balance_dust_level": {"type": "number", "minimum": 0.0}, + "notification_settings": { + "type": "object", + "default": {}, + "properties": { + "status": {"type": "string", "enum": TELEGRAM_SETTING_OPTIONS}, + "warning": {"type": "string", "enum": TELEGRAM_SETTING_OPTIONS}, + "startup": {"type": "string", "enum": TELEGRAM_SETTING_OPTIONS}, + "entry": {"type": "string", "enum": TELEGRAM_SETTING_OPTIONS}, + "entry_fill": { + "type": "string", + "enum": TELEGRAM_SETTING_OPTIONS, + "default": "off", + }, + "entry_cancel": { + "type": "string", + "enum": TELEGRAM_SETTING_OPTIONS, + }, + "exit": { + "type": ["string", "object"], + "additionalProperties": { + "type": "string", + "enum": TELEGRAM_SETTING_OPTIONS, + }, + }, + "exit_fill": { + "type": "string", + "enum": TELEGRAM_SETTING_OPTIONS, + "default": "on", + }, + "exit_cancel": {"type": "string", "enum": TELEGRAM_SETTING_OPTIONS}, + "protection_trigger": { + "type": "string", + "enum": TELEGRAM_SETTING_OPTIONS, + "default": "on", + }, + "protection_trigger_global": { + "type": "string", + "enum": TELEGRAM_SETTING_OPTIONS, + "default": "on", + }, + "show_candle": { + "type": "string", + "enum": ["off", "ohlc"], + "default": "off", + }, + "strategy_msg": { + "type": "string", + "enum": TELEGRAM_SETTING_OPTIONS, + "default": "on", + }, + }, + }, + "reload": {"type": "boolean"}, + }, + "required": ["enabled", "token", "chat_id"], + }, + "webhook": { + "type": "object", + "properties": { + "enabled": {"type": "boolean"}, + "url": {"type": "string"}, + "format": {"type": "string", "enum": WEBHOOK_FORMAT_OPTIONS, "default": "form"}, + "retries": {"type": "integer", "minimum": 0}, + "retry_delay": {"type": "number", "minimum": 0}, + **__MESSAGE_TYPE_DICT, + # **{x: {'type': 'object'} for x in RPCMessageType}, + # Below -> Deprecated + "webhookentry": {"type": "object"}, + "webhookentrycancel": {"type": "object"}, + "webhookentryfill": {"type": "object"}, + "webhookexit": {"type": "object"}, + "webhookexitcancel": {"type": "object"}, + "webhookexitfill": {"type": "object"}, + "webhookstatus": {"type": "object"}, + }, + }, + "discord": { + "type": "object", + "properties": { + "enabled": {"type": "boolean"}, + "webhook_url": {"type": "string"}, + "exit_fill": { + "type": "array", + "items": {"type": "object"}, + "default": [ + {"Trade ID": "{trade_id}"}, + {"Exchange": "{exchange}"}, + {"Pair": "{pair}"}, + {"Direction": "{direction}"}, + {"Open rate": "{open_rate}"}, + {"Close rate": "{close_rate}"}, + {"Amount": "{amount}"}, + {"Open date": "{open_date:%Y-%m-%d %H:%M:%S}"}, + {"Close date": "{close_date:%Y-%m-%d %H:%M:%S}"}, + {"Profit": "{profit_amount} {stake_currency}"}, + {"Profitability": "{profit_ratio:.2%}"}, + {"Enter tag": "{enter_tag}"}, + {"Exit Reason": "{exit_reason}"}, + {"Strategy": "{strategy}"}, + {"Timeframe": "{timeframe}"}, + ], + }, + "entry_fill": { + "type": "array", + "items": {"type": "object"}, + "default": [ + {"Trade ID": "{trade_id}"}, + {"Exchange": "{exchange}"}, + {"Pair": "{pair}"}, + {"Direction": "{direction}"}, + {"Open rate": "{open_rate}"}, + {"Amount": "{amount}"}, + {"Open date": "{open_date:%Y-%m-%d %H:%M:%S}"}, + {"Enter tag": "{enter_tag}"}, + {"Strategy": "{strategy} {timeframe}"}, + ], + }, + }, + }, + "api_server": { + "type": "object", + "properties": { + "enabled": {"type": "boolean"}, + "listen_ip_address": {"format": "ipv4"}, + "listen_port": {"type": "integer", "minimum": 1024, "maximum": 65535}, + "username": {"type": "string"}, + "password": {"type": "string"}, + "ws_token": {"type": ["string", "array"], "items": {"type": "string"}}, + "jwt_secret_key": {"type": "string"}, + "CORS_origins": {"type": "array", "items": {"type": "string"}}, + "verbosity": {"type": "string", "enum": ["error", "info"]}, + }, + "required": ["enabled", "listen_ip_address", "listen_port", "username", "password"], + }, + "db_url": {"type": "string"}, + "export": {"type": "string", "enum": EXPORT_OPTIONS, "default": "trades"}, + "disableparamexport": {"type": "boolean"}, + "initial_state": {"type": "string", "enum": ["running", "stopped"]}, + "force_entry_enable": {"type": "boolean"}, + "disable_dataframe_checks": {"type": "boolean"}, + "internals": { + "type": "object", + "default": {}, + "properties": { + "process_throttle_secs": {"type": "integer"}, + "interval": {"type": "integer"}, + "sd_notify": {"type": "boolean"}, + }, + }, + "dataformat_ohlcv": { + "type": "string", + "enum": AVAILABLE_DATAHANDLERS, + "default": "feather", + }, + "dataformat_trades": { + "type": "string", + "enum": AVAILABLE_DATAHANDLERS, + "default": "feather", + }, + "position_adjustment_enable": {"type": "boolean"}, + "max_entry_position_adjustment": {"type": ["integer", "number"], "minimum": -1}, + "orderflow": { + "type": "object", + "properties": { + "cache_size": {"type": "number", "minimum": 1, "default": 1500}, + "max_candles": {"type": "number", "minimum": 1, "default": 1500}, + "scale": {"type": "number", "minimum": 0.0}, + "stacked_imbalance_range": {"type": "number", "minimum": 0}, + "imbalance_volume": {"type": "number", "minimum": 0}, + "imbalance_ratio": {"type": "number", "minimum": 0.0}, + }, + "required": [ + "max_candles", + "scale", + "stacked_imbalance_range", + "imbalance_volume", + "imbalance_ratio", + ], + }, + }, + "definitions": { + "exchange": { + "type": "object", + "properties": { + "name": {"type": "string"}, + "enable_ws": {"type": "boolean", "default": True}, + "key": {"type": "string", "default": ""}, + "secret": {"type": "string", "default": ""}, + "password": {"type": "string", "default": ""}, + "uid": {"type": "string"}, + "pair_whitelist": { + "type": "array", + "items": { + "type": "string", + }, + "uniqueItems": True, + }, + "pair_blacklist": { + "type": "array", + "items": { + "type": "string", + }, + "uniqueItems": True, + }, + "unknown_fee_rate": {"type": "number"}, + "outdated_offset": {"type": "integer", "minimum": 1}, + "markets_refresh_interval": {"type": "integer"}, + "ccxt_config": {"type": "object"}, + "ccxt_async_config": {"type": "object"}, + }, + "required": ["name"], + }, + "edge": { + "type": "object", + "properties": { + "enabled": {"type": "boolean"}, + "process_throttle_secs": {"type": "integer", "minimum": 600}, + "calculate_since_number_of_days": {"type": "integer"}, + "allowed_risk": {"type": "number"}, + "stoploss_range_min": {"type": "number"}, + "stoploss_range_max": {"type": "number"}, + "stoploss_range_step": {"type": "number"}, + "minimum_winrate": {"type": "number"}, + "minimum_expectancy": {"type": "number"}, + "min_trade_number": {"type": "number"}, + "max_trade_duration_minute": {"type": "integer"}, + "remove_pumps": {"type": "boolean"}, + }, + "required": ["process_throttle_secs", "allowed_risk"], + }, + "external_message_consumer": { + "type": "object", + "properties": { + "enabled": {"type": "boolean", "default": False}, + "producers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": {"type": "string"}, + "host": {"type": "string"}, + "port": { + "type": "integer", + "default": 8080, + "minimum": 0, + "maximum": 65535, + }, + "secure": {"type": "boolean", "default": False}, + "ws_token": {"type": "string"}, + }, + "required": ["name", "host", "ws_token"], + }, + }, + "wait_timeout": {"type": "integer", "minimum": 0}, + "sleep_time": {"type": "integer", "minimum": 0}, + "ping_timeout": {"type": "integer", "minimum": 0}, + "remove_entry_exit_signals": {"type": "boolean", "default": False}, + "initial_candle_limit": { + "type": "integer", + "minimum": 0, + "maximum": 1500, + "default": 1500, + }, + "message_size_limit": { # In megabytes + "type": "integer", + "minimum": 1, + "maximum": 20, + "default": 8, + }, + }, + "required": ["producers"], + }, + "freqai": { + "type": "object", + "properties": { + "enabled": {"type": "boolean", "default": False}, + "keras": {"type": "boolean", "default": False}, + "write_metrics_to_disk": {"type": "boolean", "default": False}, + "purge_old_models": {"type": ["boolean", "number"], "default": 2}, + "conv_width": {"type": "integer", "default": 1}, + "train_period_days": {"type": "integer", "default": 0}, + "backtest_period_days": {"type": "number", "default": 7}, + "identifier": {"type": "string", "default": "example"}, + "feature_parameters": { + "type": "object", + "properties": { + "include_corr_pairlist": {"type": "array"}, + "include_timeframes": {"type": "array"}, + "label_period_candles": {"type": "integer"}, + "include_shifted_candles": {"type": "integer", "default": 0}, + "DI_threshold": {"type": "number", "default": 0}, + "weight_factor": {"type": "number", "default": 0}, + "principal_component_analysis": {"type": "boolean", "default": False}, + "use_SVM_to_remove_outliers": {"type": "boolean", "default": False}, + "plot_feature_importances": {"type": "integer", "default": 0}, + "svm_params": { + "type": "object", + "properties": { + "shuffle": {"type": "boolean", "default": False}, + "nu": {"type": "number", "default": 0.1}, + }, + }, + "shuffle_after_split": {"type": "boolean", "default": False}, + "buffer_train_data_candles": {"type": "integer", "default": 0}, + }, + "required": [ + "include_timeframes", + "include_corr_pairlist", + ], + }, + "data_split_parameters": { + "type": "object", + "properties": { + "test_size": {"type": "number"}, + "random_state": {"type": "integer"}, + "shuffle": {"type": "boolean", "default": False}, + }, + }, + "model_training_parameters": {"type": "object"}, + "rl_config": { + "type": "object", + "properties": { + "drop_ohlc_from_features": {"type": "boolean", "default": False}, + "train_cycles": {"type": "integer"}, + "max_trade_duration_candles": {"type": "integer"}, + "add_state_info": {"type": "boolean", "default": False}, + "max_training_drawdown_pct": {"type": "number", "default": 0.02}, + "cpu_count": {"type": "integer", "default": 1}, + "model_type": {"type": "string", "default": "PPO"}, + "policy_type": {"type": "string", "default": "MlpPolicy"}, + "net_arch": {"type": "array", "default": [128, 128]}, + "randomize_starting_position": {"type": "boolean", "default": False}, + "progress_bar": {"type": "boolean", "default": True}, + "model_reward_parameters": { + "type": "object", + "properties": { + "rr": {"type": "number", "default": 1}, + "profit_aim": {"type": "number", "default": 0.025}, + }, + }, + }, + }, + }, + "required": [ + "enabled", + "train_period_days", + "backtest_period_days", + "identifier", + "feature_parameters", + "data_split_parameters", + ], + }, + }, +} + +SCHEMA_TRADE_REQUIRED = [ + "exchange", + "timeframe", + "max_open_trades", + "stake_currency", + "stake_amount", + "tradable_balance_ratio", + "last_stake_amount_min_ratio", + "dry_run", + "dry_run_wallet", + "exit_pricing", + "entry_pricing", + "stoploss", + "minimal_roi", + "internals", + "dataformat_ohlcv", + "dataformat_trades", +] + +SCHEMA_BACKTEST_REQUIRED = [ + "exchange", + "stake_currency", + "stake_amount", + "dry_run_wallet", + "dataformat_ohlcv", + "dataformat_trades", +] +SCHEMA_BACKTEST_REQUIRED_FINAL = SCHEMA_BACKTEST_REQUIRED + [ + "stoploss", + "minimal_roi", + "max_open_trades", +] + +SCHEMA_MINIMAL_REQUIRED = [ + "exchange", + "dry_run", + "dataformat_ohlcv", + "dataformat_trades", +] +SCHEMA_MINIMAL_WEBSERVER = SCHEMA_MINIMAL_REQUIRED + [ + "api_server", +] diff --git a/freqtrade/configuration/config_validation.py b/freqtrade/configuration/config_validation.py index 301ddcd0c..f7f021b9c 100644 --- a/freqtrade/configuration/config_validation.py +++ b/freqtrade/configuration/config_validation.py @@ -6,8 +6,16 @@ from typing import Any, Dict from jsonschema import Draft4Validator, validators from jsonschema.exceptions import ValidationError, best_match -from freqtrade import constants +from freqtrade.configuration.config_schema import ( + CONF_SCHEMA, + SCHEMA_BACKTEST_REQUIRED, + SCHEMA_BACKTEST_REQUIRED_FINAL, + SCHEMA_MINIMAL_REQUIRED, + SCHEMA_MINIMAL_WEBSERVER, + SCHEMA_TRADE_REQUIRED, +) from freqtrade.configuration.deprecated_settings import process_deprecated_setting +from freqtrade.constants import UNLIMITED_STAKE_AMOUNT from freqtrade.enums import RunMode, TradingMode from freqtrade.exceptions import ConfigurationError @@ -41,18 +49,18 @@ def validate_config_schema(conf: Dict[str, Any], preliminary: bool = False) -> D :param conf: Config in JSON format :return: Returns the config if valid, otherwise throw an exception """ - conf_schema = deepcopy(constants.CONF_SCHEMA) + conf_schema = deepcopy(CONF_SCHEMA) if conf.get("runmode", RunMode.OTHER) in (RunMode.DRY_RUN, RunMode.LIVE): - conf_schema["required"] = constants.SCHEMA_TRADE_REQUIRED + conf_schema["required"] = SCHEMA_TRADE_REQUIRED elif conf.get("runmode", RunMode.OTHER) in (RunMode.BACKTEST, RunMode.HYPEROPT): if preliminary: - conf_schema["required"] = constants.SCHEMA_BACKTEST_REQUIRED + conf_schema["required"] = SCHEMA_BACKTEST_REQUIRED else: - conf_schema["required"] = constants.SCHEMA_BACKTEST_REQUIRED_FINAL + conf_schema["required"] = SCHEMA_BACKTEST_REQUIRED_FINAL elif conf.get("runmode", RunMode.OTHER) == RunMode.WEBSERVER: - conf_schema["required"] = constants.SCHEMA_MINIMAL_WEBSERVER + conf_schema["required"] = SCHEMA_MINIMAL_WEBSERVER else: - conf_schema["required"] = constants.SCHEMA_MINIMAL_REQUIRED + conf_schema["required"] = SCHEMA_MINIMAL_REQUIRED try: FreqtradeValidator(conf_schema).validate(conf) return conf @@ -98,7 +106,7 @@ def _validate_unlimited_amount(conf: Dict[str, Any]) -> None: if ( not conf.get("edge", {}).get("enabled") and conf.get("max_open_trades") == float("inf") - and conf.get("stake_amount") == constants.UNLIMITED_STAKE_AMOUNT + and conf.get("stake_amount") == UNLIMITED_STAKE_AMOUNT ): raise ConfigurationError("`max_open_trades` and `stake_amount` cannot both be unlimited.") diff --git a/freqtrade/constants.py b/freqtrade/constants.py index ca102ebcd..c8990a02a 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -6,7 +6,7 @@ bot constants from typing import Any, Dict, List, Literal, Optional, Tuple -from freqtrade.enums import CandleType, PriceType, RPCMessageType +from freqtrade.enums import CandleType, PriceType DOCS_LINK = "https://www.freqtrade.io/en/stable" @@ -172,604 +172,6 @@ MINIMAL_CONFIG = { }, } -__MESSAGE_TYPE_DICT: Dict[str, Dict[str, str]] = {x: {"type": "object"} for x in RPCMessageType} - -# Required json-schema for user specified config -CONF_SCHEMA = { - "type": "object", - "properties": { - "max_open_trades": {"type": ["integer", "number"], "minimum": -1}, - "new_pairs_days": {"type": "integer", "default": 30}, - "timeframe": {"type": "string"}, - "stake_currency": {"type": "string"}, - "stake_amount": { - "type": ["number", "string"], - "minimum": 0.0001, - "pattern": UNLIMITED_STAKE_AMOUNT, - }, - "tradable_balance_ratio": {"type": "number", "minimum": 0.0, "maximum": 1, "default": 0.99}, - "available_capital": { - "type": "number", - "minimum": 0, - }, - "amend_last_stake_amount": {"type": "boolean", "default": False}, - "last_stake_amount_min_ratio": { - "type": "number", - "minimum": 0.0, - "maximum": 1.0, - "default": 0.5, - }, - "fiat_display_currency": {"type": "string", "enum": SUPPORTED_FIAT}, - "dry_run": {"type": "boolean"}, - "dry_run_wallet": {"type": "number", "default": DRY_RUN_WALLET}, - "cancel_open_orders_on_exit": {"type": "boolean", "default": False}, - "process_only_new_candles": {"type": "boolean"}, - "minimal_roi": { - "type": "object", - "patternProperties": {"^[0-9.]+$": {"type": "number"}}, - }, - "amount_reserve_percent": {"type": "number", "minimum": 0.0, "maximum": 0.5}, - "stoploss": {"type": "number", "maximum": 0, "exclusiveMaximum": True}, - "trailing_stop": {"type": "boolean"}, - "trailing_stop_positive": {"type": "number", "minimum": 0, "maximum": 1}, - "trailing_stop_positive_offset": {"type": "number", "minimum": 0, "maximum": 1}, - "trailing_only_offset_is_reached": {"type": "boolean"}, - "use_exit_signal": {"type": "boolean"}, - "exit_profit_only": {"type": "boolean"}, - "exit_profit_offset": {"type": "number"}, - "fee": {"type": "number", "minimum": 0, "maximum": 0.1}, - "ignore_roi_if_entry_signal": {"type": "boolean"}, - "ignore_buying_expired_candle_after": {"type": "number"}, - "trading_mode": {"type": "string", "enum": TRADING_MODES}, - "margin_mode": {"type": "string", "enum": MARGIN_MODES}, - "reduce_df_footprint": {"type": "boolean", "default": False}, - "minimum_trade_amount": {"type": "number", "default": 10}, - "targeted_trade_amount": {"type": "number", "default": 20}, - "lookahead_analysis_exportfilename": {"type": "string"}, - "startup_candle": { - "type": "array", - "uniqueItems": True, - "default": [199, 399, 499, 999, 1999], - }, - "liquidation_buffer": {"type": "number", "minimum": 0.0, "maximum": 0.99}, - "backtest_breakdown": { - "type": "array", - "items": {"type": "string", "enum": BACKTEST_BREAKDOWNS}, - }, - "bot_name": {"type": "string"}, - "unfilledtimeout": { - "type": "object", - "properties": { - "entry": {"type": "number", "minimum": 1}, - "exit": {"type": "number", "minimum": 1}, - "exit_timeout_count": {"type": "number", "minimum": 0, "default": 0}, - "unit": {"type": "string", "enum": TIMEOUT_UNITS, "default": "minutes"}, - }, - }, - "entry_pricing": { - "type": "object", - "properties": { - "price_last_balance": { - "type": "number", - "minimum": 0, - "maximum": 1, - "exclusiveMaximum": False, - }, - "price_side": {"type": "string", "enum": PRICING_SIDES, "default": "same"}, - "use_order_book": {"type": "boolean"}, - "order_book_top": { - "type": "integer", - "minimum": 1, - "maximum": 50, - }, - "check_depth_of_market": { - "type": "object", - "properties": { - "enabled": {"type": "boolean"}, - "bids_to_ask_delta": {"type": "number", "minimum": 0}, - }, - }, - }, - "required": ["price_side"], - }, - "exit_pricing": { - "type": "object", - "properties": { - "price_side": {"type": "string", "enum": PRICING_SIDES, "default": "same"}, - "price_last_balance": { - "type": "number", - "minimum": 0, - "maximum": 1, - "exclusiveMaximum": False, - }, - "use_order_book": {"type": "boolean"}, - "order_book_top": { - "type": "integer", - "minimum": 1, - "maximum": 50, - }, - }, - "required": ["price_side"], - }, - "custom_price_max_distance_ratio": {"type": "number", "minimum": 0.0}, - "order_types": { - "type": "object", - "properties": { - "entry": {"type": "string", "enum": ORDERTYPE_POSSIBILITIES}, - "exit": {"type": "string", "enum": ORDERTYPE_POSSIBILITIES}, - "force_exit": {"type": "string", "enum": ORDERTYPE_POSSIBILITIES}, - "force_entry": {"type": "string", "enum": ORDERTYPE_POSSIBILITIES}, - "emergency_exit": { - "type": "string", - "enum": ORDERTYPE_POSSIBILITIES, - "default": "market", - }, - "stoploss": {"type": "string", "enum": ORDERTYPE_POSSIBILITIES}, - "stoploss_on_exchange": {"type": "boolean"}, - "stoploss_price_type": {"type": "string", "enum": STOPLOSS_PRICE_TYPES}, - "stoploss_on_exchange_interval": {"type": "number"}, - "stoploss_on_exchange_limit_ratio": { - "type": "number", - "minimum": 0.0, - "maximum": 1.0, - }, - }, - "required": ["entry", "exit", "stoploss", "stoploss_on_exchange"], - }, - "order_time_in_force": { - "type": "object", - "properties": { - "entry": {"type": "string", "enum": ORDERTIF_POSSIBILITIES}, - "exit": {"type": "string", "enum": ORDERTIF_POSSIBILITIES}, - }, - "required": REQUIRED_ORDERTIF, - }, - "coingecko": { - "type": "object", - "properties": { - "is_demo": {"type": "boolean", "default": True}, - "api_key": {"type": "string"}, - }, - "required": ["is_demo", "api_key"], - }, - "exchange": {"$ref": "#/definitions/exchange"}, - "edge": {"$ref": "#/definitions/edge"}, - "freqai": {"$ref": "#/definitions/freqai"}, - "external_message_consumer": {"$ref": "#/definitions/external_message_consumer"}, - "experimental": { - "type": "object", - "properties": {"block_bad_exchanges": {"type": "boolean"}}, - }, - "pairlists": { - "type": "array", - "items": { - "type": "object", - "properties": { - "method": {"type": "string", "enum": AVAILABLE_PAIRLISTS}, - }, - "required": ["method"], - }, - }, - "protections": { - "type": "array", - "items": { - "type": "object", - "properties": { - "method": {"type": "string", "enum": AVAILABLE_PROTECTIONS}, - "stop_duration": {"type": "number", "minimum": 0.0}, - "stop_duration_candles": {"type": "number", "minimum": 0}, - "trade_limit": {"type": "number", "minimum": 1}, - "lookback_period": {"type": "number", "minimum": 1}, - "lookback_period_candles": {"type": "number", "minimum": 1}, - }, - "required": ["method"], - }, - }, - "telegram": { - "type": "object", - "properties": { - "enabled": {"type": "boolean"}, - "token": {"type": "string"}, - "chat_id": {"type": "string"}, - "allow_custom_messages": {"type": "boolean", "default": True}, - "balance_dust_level": {"type": "number", "minimum": 0.0}, - "notification_settings": { - "type": "object", - "default": {}, - "properties": { - "status": {"type": "string", "enum": TELEGRAM_SETTING_OPTIONS}, - "warning": {"type": "string", "enum": TELEGRAM_SETTING_OPTIONS}, - "startup": {"type": "string", "enum": TELEGRAM_SETTING_OPTIONS}, - "entry": {"type": "string", "enum": TELEGRAM_SETTING_OPTIONS}, - "entry_fill": { - "type": "string", - "enum": TELEGRAM_SETTING_OPTIONS, - "default": "off", - }, - "entry_cancel": { - "type": "string", - "enum": TELEGRAM_SETTING_OPTIONS, - }, - "exit": { - "type": ["string", "object"], - "additionalProperties": { - "type": "string", - "enum": TELEGRAM_SETTING_OPTIONS, - }, - }, - "exit_fill": { - "type": "string", - "enum": TELEGRAM_SETTING_OPTIONS, - "default": "on", - }, - "exit_cancel": {"type": "string", "enum": TELEGRAM_SETTING_OPTIONS}, - "protection_trigger": { - "type": "string", - "enum": TELEGRAM_SETTING_OPTIONS, - "default": "on", - }, - "protection_trigger_global": { - "type": "string", - "enum": TELEGRAM_SETTING_OPTIONS, - "default": "on", - }, - "show_candle": { - "type": "string", - "enum": ["off", "ohlc"], - "default": "off", - }, - "strategy_msg": { - "type": "string", - "enum": TELEGRAM_SETTING_OPTIONS, - "default": "on", - }, - }, - }, - "reload": {"type": "boolean"}, - }, - "required": ["enabled", "token", "chat_id"], - }, - "webhook": { - "type": "object", - "properties": { - "enabled": {"type": "boolean"}, - "url": {"type": "string"}, - "format": {"type": "string", "enum": WEBHOOK_FORMAT_OPTIONS, "default": "form"}, - "retries": {"type": "integer", "minimum": 0}, - "retry_delay": {"type": "number", "minimum": 0}, - **__MESSAGE_TYPE_DICT, - # **{x: {'type': 'object'} for x in RPCMessageType}, - # Below -> Deprecated - "webhookentry": {"type": "object"}, - "webhookentrycancel": {"type": "object"}, - "webhookentryfill": {"type": "object"}, - "webhookexit": {"type": "object"}, - "webhookexitcancel": {"type": "object"}, - "webhookexitfill": {"type": "object"}, - "webhookstatus": {"type": "object"}, - }, - }, - "discord": { - "type": "object", - "properties": { - "enabled": {"type": "boolean"}, - "webhook_url": {"type": "string"}, - "exit_fill": { - "type": "array", - "items": {"type": "object"}, - "default": [ - {"Trade ID": "{trade_id}"}, - {"Exchange": "{exchange}"}, - {"Pair": "{pair}"}, - {"Direction": "{direction}"}, - {"Open rate": "{open_rate}"}, - {"Close rate": "{close_rate}"}, - {"Amount": "{amount}"}, - {"Open date": "{open_date:%Y-%m-%d %H:%M:%S}"}, - {"Close date": "{close_date:%Y-%m-%d %H:%M:%S}"}, - {"Profit": "{profit_amount} {stake_currency}"}, - {"Profitability": "{profit_ratio:.2%}"}, - {"Enter tag": "{enter_tag}"}, - {"Exit Reason": "{exit_reason}"}, - {"Strategy": "{strategy}"}, - {"Timeframe": "{timeframe}"}, - ], - }, - "entry_fill": { - "type": "array", - "items": {"type": "object"}, - "default": [ - {"Trade ID": "{trade_id}"}, - {"Exchange": "{exchange}"}, - {"Pair": "{pair}"}, - {"Direction": "{direction}"}, - {"Open rate": "{open_rate}"}, - {"Amount": "{amount}"}, - {"Open date": "{open_date:%Y-%m-%d %H:%M:%S}"}, - {"Enter tag": "{enter_tag}"}, - {"Strategy": "{strategy} {timeframe}"}, - ], - }, - }, - }, - "api_server": { - "type": "object", - "properties": { - "enabled": {"type": "boolean"}, - "listen_ip_address": {"format": "ipv4"}, - "listen_port": {"type": "integer", "minimum": 1024, "maximum": 65535}, - "username": {"type": "string"}, - "password": {"type": "string"}, - "ws_token": {"type": ["string", "array"], "items": {"type": "string"}}, - "jwt_secret_key": {"type": "string"}, - "CORS_origins": {"type": "array", "items": {"type": "string"}}, - "verbosity": {"type": "string", "enum": ["error", "info"]}, - }, - "required": ["enabled", "listen_ip_address", "listen_port", "username", "password"], - }, - "db_url": {"type": "string"}, - "export": {"type": "string", "enum": EXPORT_OPTIONS, "default": "trades"}, - "disableparamexport": {"type": "boolean"}, - "initial_state": {"type": "string", "enum": ["running", "stopped"]}, - "force_entry_enable": {"type": "boolean"}, - "disable_dataframe_checks": {"type": "boolean"}, - "internals": { - "type": "object", - "default": {}, - "properties": { - "process_throttle_secs": {"type": "integer"}, - "interval": {"type": "integer"}, - "sd_notify": {"type": "boolean"}, - }, - }, - "dataformat_ohlcv": { - "type": "string", - "enum": AVAILABLE_DATAHANDLERS, - "default": "feather", - }, - "dataformat_trades": { - "type": "string", - "enum": AVAILABLE_DATAHANDLERS, - "default": "feather", - }, - "position_adjustment_enable": {"type": "boolean"}, - "max_entry_position_adjustment": {"type": ["integer", "number"], "minimum": -1}, - "orderflow": { - "type": "object", - "properties": { - "cache_size": {"type": "number", "minimum": 1, "default": 1500}, - "max_candles": {"type": "number", "minimum": 1, "default": 1500}, - "scale": {"type": "number", "minimum": 0.0}, - "stacked_imbalance_range": {"type": "number", "minimum": 0}, - "imbalance_volume": {"type": "number", "minimum": 0}, - "imbalance_ratio": {"type": "number", "minimum": 0.0}, - }, - "required": [ - "max_candles", - "scale", - "stacked_imbalance_range", - "imbalance_volume", - "imbalance_ratio", - ], - }, - }, - "definitions": { - "exchange": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "enable_ws": {"type": "boolean", "default": True}, - "key": {"type": "string", "default": ""}, - "secret": {"type": "string", "default": ""}, - "password": {"type": "string", "default": ""}, - "uid": {"type": "string"}, - "pair_whitelist": { - "type": "array", - "items": { - "type": "string", - }, - "uniqueItems": True, - }, - "pair_blacklist": { - "type": "array", - "items": { - "type": "string", - }, - "uniqueItems": True, - }, - "unknown_fee_rate": {"type": "number"}, - "outdated_offset": {"type": "integer", "minimum": 1}, - "markets_refresh_interval": {"type": "integer"}, - "ccxt_config": {"type": "object"}, - "ccxt_async_config": {"type": "object"}, - }, - "required": ["name"], - }, - "edge": { - "type": "object", - "properties": { - "enabled": {"type": "boolean"}, - "process_throttle_secs": {"type": "integer", "minimum": 600}, - "calculate_since_number_of_days": {"type": "integer"}, - "allowed_risk": {"type": "number"}, - "stoploss_range_min": {"type": "number"}, - "stoploss_range_max": {"type": "number"}, - "stoploss_range_step": {"type": "number"}, - "minimum_winrate": {"type": "number"}, - "minimum_expectancy": {"type": "number"}, - "min_trade_number": {"type": "number"}, - "max_trade_duration_minute": {"type": "integer"}, - "remove_pumps": {"type": "boolean"}, - }, - "required": ["process_throttle_secs", "allowed_risk"], - }, - "external_message_consumer": { - "type": "object", - "properties": { - "enabled": {"type": "boolean", "default": False}, - "producers": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "host": {"type": "string"}, - "port": { - "type": "integer", - "default": 8080, - "minimum": 0, - "maximum": 65535, - }, - "secure": {"type": "boolean", "default": False}, - "ws_token": {"type": "string"}, - }, - "required": ["name", "host", "ws_token"], - }, - }, - "wait_timeout": {"type": "integer", "minimum": 0}, - "sleep_time": {"type": "integer", "minimum": 0}, - "ping_timeout": {"type": "integer", "minimum": 0}, - "remove_entry_exit_signals": {"type": "boolean", "default": False}, - "initial_candle_limit": { - "type": "integer", - "minimum": 0, - "maximum": 1500, - "default": 1500, - }, - "message_size_limit": { # In megabytes - "type": "integer", - "minimum": 1, - "maximum": 20, - "default": 8, - }, - }, - "required": ["producers"], - }, - "freqai": { - "type": "object", - "properties": { - "enabled": {"type": "boolean", "default": False}, - "keras": {"type": "boolean", "default": False}, - "write_metrics_to_disk": {"type": "boolean", "default": False}, - "purge_old_models": {"type": ["boolean", "number"], "default": 2}, - "conv_width": {"type": "integer", "default": 1}, - "train_period_days": {"type": "integer", "default": 0}, - "backtest_period_days": {"type": "number", "default": 7}, - "identifier": {"type": "string", "default": "example"}, - "feature_parameters": { - "type": "object", - "properties": { - "include_corr_pairlist": {"type": "array"}, - "include_timeframes": {"type": "array"}, - "label_period_candles": {"type": "integer"}, - "include_shifted_candles": {"type": "integer", "default": 0}, - "DI_threshold": {"type": "number", "default": 0}, - "weight_factor": {"type": "number", "default": 0}, - "principal_component_analysis": {"type": "boolean", "default": False}, - "use_SVM_to_remove_outliers": {"type": "boolean", "default": False}, - "plot_feature_importances": {"type": "integer", "default": 0}, - "svm_params": { - "type": "object", - "properties": { - "shuffle": {"type": "boolean", "default": False}, - "nu": {"type": "number", "default": 0.1}, - }, - }, - "shuffle_after_split": {"type": "boolean", "default": False}, - "buffer_train_data_candles": {"type": "integer", "default": 0}, - }, - "required": [ - "include_timeframes", - "include_corr_pairlist", - ], - }, - "data_split_parameters": { - "type": "object", - "properties": { - "test_size": {"type": "number"}, - "random_state": {"type": "integer"}, - "shuffle": {"type": "boolean", "default": False}, - }, - }, - "model_training_parameters": {"type": "object"}, - "rl_config": { - "type": "object", - "properties": { - "drop_ohlc_from_features": {"type": "boolean", "default": False}, - "train_cycles": {"type": "integer"}, - "max_trade_duration_candles": {"type": "integer"}, - "add_state_info": {"type": "boolean", "default": False}, - "max_training_drawdown_pct": {"type": "number", "default": 0.02}, - "cpu_count": {"type": "integer", "default": 1}, - "model_type": {"type": "string", "default": "PPO"}, - "policy_type": {"type": "string", "default": "MlpPolicy"}, - "net_arch": {"type": "array", "default": [128, 128]}, - "randomize_starting_position": {"type": "boolean", "default": False}, - "progress_bar": {"type": "boolean", "default": True}, - "model_reward_parameters": { - "type": "object", - "properties": { - "rr": {"type": "number", "default": 1}, - "profit_aim": {"type": "number", "default": 0.025}, - }, - }, - }, - }, - }, - "required": [ - "enabled", - "train_period_days", - "backtest_period_days", - "identifier", - "feature_parameters", - "data_split_parameters", - ], - }, - }, -} - -SCHEMA_TRADE_REQUIRED = [ - "exchange", - "timeframe", - "max_open_trades", - "stake_currency", - "stake_amount", - "tradable_balance_ratio", - "last_stake_amount_min_ratio", - "dry_run", - "dry_run_wallet", - "exit_pricing", - "entry_pricing", - "stoploss", - "minimal_roi", - "internals", - "dataformat_ohlcv", - "dataformat_trades", -] - -SCHEMA_BACKTEST_REQUIRED = [ - "exchange", - "stake_currency", - "stake_amount", - "dry_run_wallet", - "dataformat_ohlcv", - "dataformat_trades", -] -SCHEMA_BACKTEST_REQUIRED_FINAL = SCHEMA_BACKTEST_REQUIRED + [ - "stoploss", - "minimal_roi", - "max_open_trades", -] - -SCHEMA_MINIMAL_REQUIRED = [ - "exchange", - "dry_run", - "dataformat_ohlcv", - "dataformat_trades", -] -SCHEMA_MINIMAL_WEBSERVER = SCHEMA_MINIMAL_REQUIRED + [ - "api_server", -] CANCEL_REASON = { "TIMEOUT": "cancelled due to timeout",