diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 56d02e5bf..3e4ef2faa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,6 +80,11 @@ jobs: # Allow failure for coveralls coveralls || true + - name: Run json schema extract + # This should be kept before the repository check to ensure that the schema is up-to-date + run: | + python build_helpers/extract_config_json_schema.py + - name: Check for repository changes run: | if [ -n "$(git status --porcelain)" ]; then diff --git a/build_helpers/extract_config_json_schema.py b/build_helpers/extract_config_json_schema.py new file mode 100644 index 000000000..44ecc0f91 --- /dev/null +++ b/build_helpers/extract_config_json_schema.py @@ -0,0 +1,17 @@ +"""Script to extract the configuration json schema from config_schema.py file.""" + +from pathlib import Path + +import rapidjson + +from freqtrade.configuration.config_schema import CONF_SCHEMA + + +def extract_config_json_schema(): + schema_filename = Path(__file__).parent / "schema.json" + with schema_filename.open("w") as f: + rapidjson.dump(CONF_SCHEMA, f, indent=2) + + +if __name__ == "__main__": + extract_config_json_schema() diff --git a/build_helpers/schema.json b/build_helpers/schema.json new file mode 100644 index 000000000..c0933d9f8 --- /dev/null +++ b/build_helpers/schema.json @@ -0,0 +1,1601 @@ +{ + "type": "object", + "properties": { + "max_open_trades": { + "description": "Maximum number of open trades. -1 for unlimited.", + "type": [ + "integer", + "number" + ], + "minimum": -1 + }, + "new_pairs_days": { + "description": "Download data of new pairs for given number of days", + "type": "integer", + "default": 30 + }, + "timeframe": { + "description": "The timeframe to use (e.g `1m`, `5m`, `15m`, `30m`, `1h` ...). \nUsually specified in the strategy and missing in the configuration.", + "type": "string" + }, + "stake_currency": { + "description": "Currency used for staking.", + "type": "string" + }, + "stake_amount": { + "description": "Amount to stake per trade.", + "type": [ + "number", + "string" + ], + "minimum": 0.0001, + "pattern": "unlimited" + }, + "tradable_balance_ratio": { + "description": "Ratio of balance that is tradable.", + "type": "number", + "minimum": 0.0, + "maximum": 1, + "default": 0.99 + }, + "available_capital": { + "description": "Total capital available for trading.", + "type": "number", + "minimum": 0 + }, + "amend_last_stake_amount": { + "description": "Whether to amend the last stake amount.", + "type": "boolean", + "default": false + }, + "last_stake_amount_min_ratio": { + "description": "Minimum ratio for the last stake amount.", + "type": "number", + "minimum": 0.0, + "maximum": 1.0, + "default": 0.5 + }, + "fiat_display_currency": { + "description": "Fiat currency for display purposes.", + "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", + "UAH", + "SEK", + "SGD", + "THB", + "TRY", + "TWD", + "ZAR", + "USD", + "BTC", + "ETH", + "XRP", + "LTC", + "BCH", + "BNB", + "" + ] + }, + "dry_run": { + "description": "Enable or disable dry run mode.", + "type": "boolean" + }, + "dry_run_wallet": { + "description": "Initial wallet balance for dry run mode.", + "type": "number", + "default": 1000 + }, + "cancel_open_orders_on_exit": { + "description": "Cancel open orders when exiting.", + "type": "boolean", + "default": false + }, + "process_only_new_candles": { + "description": "Process only new candles.", + "type": "boolean" + }, + "minimal_roi": { + "description": "Minimum return on investment. \nUsually specified in the strategy and missing in the configuration.", + "type": "object", + "patternProperties": { + "^[0-9.]+$": { + "type": "number" + } + } + }, + "amount_reserve_percent": { + "description": "Percentage of amount to reserve.", + "type": "number", + "minimum": 0.0, + "maximum": 0.5 + }, + "stoploss": { + "description": "Value (as ratio) to use as Stoploss value. \nUsually specified in the strategy and missing in the configuration.", + "type": "number", + "maximum": 0, + "exclusiveMaximum": true + }, + "trailing_stop": { + "description": "Enable or disable trailing stop. \nUsually specified in the strategy and missing in the configuration.", + "type": "boolean" + }, + "trailing_stop_positive": { + "description": "Positive offset for trailing stop. \nUsually specified in the strategy and missing in the configuration.", + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "trailing_stop_positive_offset": { + "description": "Offset for trailing stop to activate. \nUsually specified in the strategy and missing in the configuration.", + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "trailing_only_offset_is_reached": { + "description": "Use trailing stop only when offset is reached. \nUsually specified in the strategy and missing in the configuration.", + "type": "boolean" + }, + "use_exit_signal": { + "description": "Use exit signal for trades. \nUsually specified in the strategy and missing in the configuration.", + "type": "boolean" + }, + "exit_profit_only": { + "description": "Exit only when in profit. Exit signals are ignored as long as profit is < exit_profit_offset. \nUsually specified in the strategy and missing in the configuration.", + "type": "boolean" + }, + "exit_profit_offset": { + "description": "Offset for profit exit. \nUsually specified in the strategy and missing in the configuration.", + "type": "number" + }, + "fee": { + "description": "Trading fee percentage. Can help to simulate slippage in backtesting", + "type": "number", + "minimum": 0, + "maximum": 0.1 + }, + "ignore_roi_if_entry_signal": { + "description": "Ignore ROI if entry signal is present. \nUsually specified in the strategy and missing in the configuration.", + "type": "boolean" + }, + "ignore_buying_expired_candle_after": { + "description": "Ignore buying after candle expiration time. \nUsually specified in the strategy and missing in the configuration.", + "type": "number" + }, + "trading_mode": { + "description": "Mode of trading (e.g., spot, margin).", + "type": "string", + "enum": [ + "spot", + "margin", + "futures" + ] + }, + "margin_mode": { + "description": "Margin mode for trading.", + "type": "string", + "enum": [ + "cross", + "isolated", + "" + ] + }, + "reduce_df_footprint": { + "description": "Reduce DataFrame footprint by casting columns to float32/int32.", + "type": "boolean", + "default": false + }, + "minimum_trade_amount": { + "description": "Minimum amount for a trade - only used for lookahead-analysis", + "type": "number", + "default": 10 + }, + "targeted_trade_amount": { + "description": "Targeted trade amount for lookahead analysis.", + "type": "number", + "default": 20 + }, + "lookahead_analysis_exportfilename": { + "description": "csv Filename for lookahead analysis export.", + "type": "string" + }, + "startup_candle": { + "description": "Startup candle configuration.", + "type": "array", + "uniqueItems": true, + "default": [ + 199, + 399, + 499, + 999, + 1999 + ] + }, + "liquidation_buffer": { + "description": "Buffer ratio for liquidation.", + "type": "number", + "minimum": 0.0, + "maximum": 0.99 + }, + "backtest_breakdown": { + "description": "Breakdown configuration for backtesting.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "day", + "week", + "month" + ] + } + }, + "bot_name": { + "description": "Name of the trading bot. Passed via API to a client.", + "type": "string" + }, + "unfilledtimeout": { + "description": "Timeout configuration for unfilled orders. \nUsually specified in the strategy and missing in the configuration.", + "type": "object", + "properties": { + "entry": { + "description": "Timeout for entry orders in unit.", + "type": "number", + "minimum": 1 + }, + "exit": { + "description": "Timeout for exit orders in unit.", + "type": "number", + "minimum": 1 + }, + "exit_timeout_count": { + "description": "Number of times to retry exit orders before giving up.", + "type": "number", + "minimum": 0, + "default": 0 + }, + "unit": { + "description": "Unit of time for the timeout (e.g., seconds, minutes).", + "type": "string", + "enum": [ + "minutes", + "seconds" + ], + "default": "minutes" + } + } + }, + "entry_pricing": { + "description": "Configuration for entry pricing.", + "type": "object", + "properties": { + "price_last_balance": { + "description": "Balance ratio for the last price.", + "type": "number", + "minimum": 0, + "maximum": 1, + "exclusiveMaximum": false + }, + "price_side": { + "description": "Side of the price to use (e.g., bid, ask, same).", + "type": "string", + "enum": [ + "ask", + "bid", + "same", + "other" + ], + "default": "same" + }, + "use_order_book": { + "description": "Whether to use the order book for pricing.", + "type": "boolean" + }, + "order_book_top": { + "description": "Top N levels of the order book to consider.", + "type": "integer", + "minimum": 1, + "maximum": 50 + }, + "check_depth_of_market": { + "description": "Configuration for checking the depth of the market.", + "type": "object", + "properties": { + "enabled": { + "description": "Enable or disable depth of market check.", + "type": "boolean" + }, + "bids_to_ask_delta": { + "description": "Delta between bids and asks to consider.", + "type": "number", + "minimum": 0 + } + } + } + }, + "required": [ + "price_side" + ] + }, + "exit_pricing": { + "description": "Configuration for exit pricing.", + "type": "object", + "properties": { + "price_side": { + "description": "Side of the price to use (e.g., bid, ask, same).", + "type": "string", + "enum": [ + "ask", + "bid", + "same", + "other" + ], + "default": "same" + }, + "price_last_balance": { + "description": "Balance ratio for the last price.", + "type": "number", + "minimum": 0, + "maximum": 1, + "exclusiveMaximum": false + }, + "use_order_book": { + "description": "Whether to use the order book for pricing.", + "type": "boolean" + }, + "order_book_top": { + "description": "Top N levels of the order book to consider.", + "type": "integer", + "minimum": 1, + "maximum": 50 + } + }, + "required": [ + "price_side" + ] + }, + "custom_price_max_distance_ratio": { + "description": "Maximum distance ratio between current and custom entry or exit price.", + "type": "number", + "minimum": 0.0, + "maximum": 1, + "default": 0.02 + }, + "order_types": { + "description": "Configuration of order types. \nUsually specified in the strategy and missing in the configuration.", + "type": "object", + "properties": { + "entry": { + "description": "Order type for entry (e.g., limit, market).", + "type": "string", + "enum": [ + "limit", + "market" + ] + }, + "exit": { + "description": "Order type for exit (e.g., limit, market).", + "type": "string", + "enum": [ + "limit", + "market" + ] + }, + "force_exit": { + "description": "Order type for forced exit (e.g., limit, market).", + "type": "string", + "enum": [ + "limit", + "market" + ] + }, + "force_entry": { + "description": "Order type for forced entry (e.g., limit, market).", + "type": "string", + "enum": [ + "limit", + "market" + ] + }, + "emergency_exit": { + "description": "Order type for emergency exit (e.g., limit, market).", + "type": "string", + "enum": [ + "limit", + "market" + ], + "default": "market" + }, + "stoploss": { + "description": "Order type for stop loss (e.g., limit, market).", + "type": "string", + "enum": [ + "limit", + "market" + ] + }, + "stoploss_on_exchange": { + "description": "Whether to place stop loss on the exchange.", + "type": "boolean" + }, + "stoploss_price_type": { + "description": "Price type for stop loss (e.g., last, mark, index).", + "type": "string", + "enum": [ + "last", + "mark", + "index" + ] + }, + "stoploss_on_exchange_interval": { + "description": "Interval for stop loss on exchange in seconds.", + "type": "number" + }, + "stoploss_on_exchange_limit_ratio": { + "description": "Limit ratio for stop loss on exchange.", + "type": "number", + "minimum": 0.0, + "maximum": 1.0 + } + }, + "required": [ + "entry", + "exit", + "stoploss", + "stoploss_on_exchange" + ] + }, + "order_time_in_force": { + "description": "Time in force configuration for orders. \nUsually specified in the strategy and missing in the configuration.", + "type": "object", + "properties": { + "entry": { + "description": "Time in force for entry orders.", + "type": "string", + "enum": [ + "GTC", + "FOK", + "IOC", + "PO", + "gtc", + "fok", + "ioc", + "po" + ] + }, + "exit": { + "description": "Time in force for exit orders.", + "type": "string", + "enum": [ + "GTC", + "FOK", + "IOC", + "PO", + "gtc", + "fok", + "ioc", + "po" + ] + } + }, + "required": [ + "entry", + "exit" + ] + }, + "coingecko": { + "description": "Configuration for CoinGecko API.", + "type": "object", + "properties": { + "is_demo": { + "description": "Whether to use CoinGecko in demo mode.", + "type": "boolean", + "default": true + }, + "api_key": { + "description": "API key for accessing CoinGecko.", + "type": "string" + } + }, + "required": [ + "is_demo", + "api_key" + ] + }, + "exchange": { + "description": "Exchange configuration.", + "$ref": "#/definitions/exchange" + }, + "edge": { + "description": "Edge configuration.", + "$ref": "#/definitions/edge" + }, + "freqai": { + "description": "FreqAI configuration.", + "$ref": "#/definitions/freqai" + }, + "external_message_consumer": { + "description": "Configuration for external message consumer.", + "$ref": "#/definitions/external_message_consumer" + }, + "experimental": { + "description": "Experimental configuration.", + "type": "object", + "properties": { + "block_bad_exchanges": { + "type": "boolean" + } + } + }, + "pairlists": { + "description": "Configuration for pairlists.", + "type": "array", + "items": { + "type": "object", + "properties": { + "method": { + "description": "Method used for generating the pairlist.", + "type": "string", + "enum": [ + "StaticPairList", + "VolumePairList", + "ProducerPairList", + "RemotePairList", + "MarketCapPairList", + "AgeFilter", + "FullTradesFilter", + "OffsetFilter", + "PerformanceFilter", + "PrecisionFilter", + "PriceFilter", + "RangeStabilityFilter", + "ShuffleFilter", + "SpreadFilter", + "VolatilityFilter" + ] + } + }, + "required": [ + "method" + ] + } + }, + "protections": { + "description": "Configuration for various protections.", + "type": "array", + "items": { + "type": "object", + "properties": { + "method": { + "description": "Method used for the protection.", + "type": "string", + "enum": [ + "CooldownPeriod", + "LowProfitPairs", + "MaxDrawdown", + "StoplossGuard" + ] + }, + "stop_duration": { + "description": "Duration to lock the pair after a protection is triggered, in minutes.", + "type": "number", + "minimum": 0.0 + }, + "stop_duration_candles": { + "description": "Duration to lock the pair after a protection is triggered, in number of candles.", + "type": "number", + "minimum": 0 + }, + "trade_limit": { + "description": "Minimum number of trades required during lookback period.", + "type": "number", + "minimum": 1 + }, + "lookback_period": { + "description": "Period to look back for protection checks, in minutes.", + "type": "number", + "minimum": 1 + }, + "lookback_period_candles": { + "description": "Period to look back for protection checks, in number of candles.", + "type": "number", + "minimum": 1 + } + }, + "required": [ + "method" + ] + } + }, + "telegram": { + "description": "Telegram settings.", + "type": "object", + "properties": { + "enabled": { + "description": "Enable Telegram notifications.", + "type": "boolean" + }, + "token": { + "description": "Telegram bot token.", + "type": "string" + }, + "chat_id": { + "description": "Telegram chat ID", + "type": "string" + }, + "allow_custom_messages": { + "description": "Allow sending custom messages from the Strategy.", + "type": "boolean", + "default": true + }, + "balance_dust_level": { + "description": "Minimum balance level to consider as dust.", + "type": "number", + "minimum": 0.0 + }, + "notification_settings": { + "description": "Settings for different types of notifications.", + "type": "object", + "default": {}, + "properties": { + "status": { + "description": "Telegram setting for status updates.", + "type": "string", + "enum": [ + "on", + "off", + "silent" + ] + }, + "warning": { + "description": "Telegram setting for warnings.", + "type": "string", + "enum": [ + "on", + "off", + "silent" + ] + }, + "startup": { + "description": "Telegram setting for startup messages.", + "type": "string", + "enum": [ + "on", + "off", + "silent" + ] + }, + "entry": { + "description": "Telegram setting for entry signals.", + "type": "string", + "enum": [ + "on", + "off", + "silent" + ] + }, + "entry_fill": { + "description": "Telegram setting for entry fill signals.", + "type": "string", + "enum": [ + "on", + "off", + "silent" + ], + "default": "off" + }, + "entry_cancel": { + "description": "Telegram setting for entry cancel signals.", + "type": "string", + "enum": [ + "on", + "off", + "silent" + ] + }, + "exit": { + "description": "Telegram setting for exit signals.", + "type": [ + "string", + "object" + ], + "additionalProperties": { + "type": "string", + "enum": [ + "on", + "off", + "silent" + ] + } + }, + "exit_fill": { + "description": "Telegram setting for exit fill signals.", + "type": "string", + "enum": [ + "on", + "off", + "silent" + ], + "default": "on" + }, + "exit_cancel": { + "description": "Telegram setting for exit cancel signals.", + "type": "string", + "enum": [ + "on", + "off", + "silent" + ] + }, + "protection_trigger": { + "description": "Telegram setting for protection triggers.", + "type": "string", + "enum": [ + "on", + "off", + "silent" + ], + "default": "on" + }, + "protection_trigger_global": { + "description": "Telegram setting for global protection triggers.", + "type": "string", + "enum": [ + "on", + "off", + "silent" + ], + "default": "on" + } + } + }, + "reload": { + "description": "Add Reload button to certain messages.", + "type": "boolean" + } + }, + "required": [ + "enabled", + "token", + "chat_id" + ] + }, + "webhook": { + "description": "Webhook settings.", + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "url": { + "type": "string" + }, + "format": { + "type": "string", + "enum": [ + "form", + "json", + "raw" + ], + "default": "form" + }, + "retries": { + "type": "integer", + "minimum": 0 + }, + "retry_delay": { + "type": "number", + "minimum": 0 + }, + "status": { + "type": "object" + }, + "warning": { + "type": "object" + }, + "exception": { + "type": "object" + }, + "startup": { + "type": "object" + }, + "entry": { + "type": "object" + }, + "entry_fill": { + "type": "object" + }, + "entry_cancel": { + "type": "object" + }, + "exit": { + "type": "object" + }, + "exit_fill": { + "type": "object" + }, + "exit_cancel": { + "type": "object" + }, + "protection_trigger": { + "type": "object" + }, + "protection_trigger_global": { + "type": "object" + }, + "strategy_msg": { + "type": "object" + }, + "whitelist": { + "type": "object" + }, + "analyzed_df": { + "type": "object" + }, + "new_candle": { + "type": "object" + } + } + }, + "discord": { + "description": "Discord settings.", + "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": { + "description": "API server settings.", + "type": "object", + "properties": { + "enabled": { + "description": "Whether the API server is enabled.", + "type": "boolean" + }, + "listen_ip_address": { + "description": "IP address the API server listens on.", + "format": "ipv4" + }, + "listen_port": { + "description": "Port the API server listens on.", + "type": "integer", + "minimum": 1024, + "maximum": 65535 + }, + "username": { + "description": "Username for API server authentication.", + "type": "string" + }, + "password": { + "description": "Password for API server authentication.", + "type": "string" + }, + "ws_token": { + "description": "WebSocket token for API server.", + "type": [ + "string", + "array" + ], + "items": { + "type": "string" + } + }, + "jwt_secret_key": { + "description": "Secret key for JWT authentication.", + "type": "string" + }, + "CORS_origins": { + "description": "List of allowed CORS origins.", + "type": "array", + "items": { + "type": "string" + } + }, + "x": { + "description": "Logging verbosity level.", + "type": "string", + "enum": [ + "error", + "info" + ] + } + }, + "required": [ + "enabled", + "listen_ip_address", + "listen_port", + "username", + "password" + ] + }, + "db_url": { + "description": "Database connection URL.", + "type": "string" + }, + "export": { + "description": "Type of data to export.", + "type": "string", + "enum": [ + "none", + "trades", + "signals" + ], + "default": "trades" + }, + "disableparamexport": { + "description": "Disable parameter export.", + "type": "boolean" + }, + "initial_state": { + "description": "Initial state of the system.", + "type": "string", + "enum": [ + "running", + "stopped" + ] + }, + "force_entry_enable": { + "description": "Force enable entry.", + "type": "boolean" + }, + "disable_dataframe_checks": { + "description": "Disable checks on dataframes.", + "type": "boolean" + }, + "internals": { + "description": "Internal settings.", + "type": "object", + "default": {}, + "properties": { + "process_throttle_secs": { + "description": "Throttle time in seconds for processing.", + "type": "integer" + }, + "interval": { + "description": "Interval time in seconds.", + "type": "integer" + }, + "sd_notify": { + "description": "Enable systemd notify.", + "type": "boolean" + } + } + }, + "dataformat_ohlcv": { + "description": "Data format for OHLCV data.", + "type": "string", + "enum": [ + "json", + "jsongz", + "hdf5", + "feather", + "parquet" + ], + "default": "feather" + }, + "dataformat_trades": { + "description": "Data format for trade data.", + "type": "string", + "enum": [ + "json", + "jsongz", + "hdf5", + "feather", + "parquet" + ], + "default": "feather" + }, + "position_adjustment_enable": { + "description": "Enable position adjustment. \nUsually specified in the strategy and missing in the configuration.", + "type": "boolean" + }, + "max_entry_position_adjustment": { + "description": "Maximum entry position adjustment allowed. \nUsually specified in the strategy and missing in the configuration.", + "type": [ + "integer", + "number" + ], + "minimum": -1 + }, + "orderflow": { + "description": "Settings related to order flow.", + "type": "object", + "properties": { + "cache_size": { + "description": "Size of the cache for order flow data.", + "type": "number", + "minimum": 1, + "default": 1500 + }, + "max_candles": { + "description": "Maximum number of candles to consider.", + "type": "number", + "minimum": 1, + "default": 1500 + }, + "scale": { + "description": "Scale factor for order flow data.", + "type": "number", + "minimum": 0.0 + }, + "stacked_imbalance_range": { + "description": "Range for stacked imbalance.", + "type": "number", + "minimum": 0 + }, + "imbalance_volume": { + "description": "Volume threshold for imbalance.", + "type": "number", + "minimum": 0 + }, + "imbalance_ratio": { + "description": "Ratio threshold for imbalance.", + "type": "number", + "minimum": 0.0 + } + }, + "required": [ + "max_candles", + "scale", + "stacked_imbalance_range", + "imbalance_volume", + "imbalance_ratio" + ] + } + }, + "definitions": { + "exchange": { + "description": "Exchange configuration settings.", + "type": "object", + "properties": { + "name": { + "description": "Name of the exchange.", + "type": "string" + }, + "enable_ws": { + "description": "Enable WebSocket connections to the exchange.", + "type": "boolean", + "default": true + }, + "key": { + "description": "API key for the exchange.", + "type": "string", + "default": "" + }, + "secret": { + "description": "API secret for the exchange.", + "type": "string", + "default": "" + }, + "password": { + "description": "Password for the exchange, if required.", + "type": "string", + "default": "" + }, + "uid": { + "description": "User ID for the exchange, if required.", + "type": "string" + }, + "pair_whitelist": { + "description": "List of whitelisted trading pairs.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "pair_blacklist": { + "description": "List of blacklisted trading pairs.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "unknown_fee_rate": { + "description": "Fee rate for unknown markets.", + "type": "number" + }, + "outdated_offset": { + "description": "Offset for outdated data in minutes.", + "type": "integer", + "minimum": 1 + }, + "markets_refresh_interval": { + "description": "Interval for refreshing market data in minutes.", + "type": "integer", + "default": 60 + }, + "ccxt_config": { + "description": "CCXT configuration settings.", + "type": "object" + }, + "ccxt_async_config": { + "description": "CCXT asynchronous configuration settings.", + "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": { + "description": "Configuration for external message consumer.", + "type": "object", + "properties": { + "enabled": { + "description": "Whether the external message consumer is enabled.", + "type": "boolean", + "default": false + }, + "producers": { + "description": "List of producers for the external message consumer.", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "description": "Name of the producer.", + "type": "string" + }, + "host": { + "description": "Host of the producer.", + "type": "string" + }, + "port": { + "description": "Port of the producer.", + "type": "integer", + "default": 8080, + "minimum": 0, + "maximum": 65535 + }, + "secure": { + "description": "Whether to use SSL to connect to the producer.", + "type": "boolean", + "default": false + }, + "ws_token": { + "description": "WebSocket token for the producer.", + "type": "string" + } + }, + "required": [ + "name", + "host", + "ws_token" + ] + } + }, + "wait_timeout": { + "description": "Wait timeout in seconds.", + "type": "integer", + "minimum": 0 + }, + "sleep_time": { + "description": "Sleep time in seconds before retrying to connect.", + "type": "integer", + "minimum": 0 + }, + "ping_timeout": { + "description": "Ping timeout in seconds.", + "type": "integer", + "minimum": 0 + }, + "remove_entry_exit_signals": { + "description": "Remove signal columns from the dataframe (set them to 0)", + "type": "boolean", + "default": false + }, + "initial_candle_limit": { + "description": "Initial candle limit.", + "type": "integer", + "minimum": 0, + "maximum": 1500, + "default": 1500 + }, + "message_size_limit": { + "description": "Message size limit in megabytes.", + "type": "integer", + "minimum": 1, + "maximum": 20, + "default": 8 + } + }, + "required": [ + "producers" + ] + }, + "freqai": { + "type": "object", + "properties": { + "enabled": { + "description": "Whether freqAI is enabled.", + "type": "boolean", + "default": false + }, + "keras": { + "description": "Use Keras for model training.", + "type": "boolean", + "default": false + }, + "write_metrics_to_disk": { + "description": "Write metrics to disk?", + "type": "boolean", + "default": false + }, + "purge_old_models": { + "description": "Number of models to keep on disk.", + "type": [ + "boolean", + "number" + ], + "default": 2 + }, + "conv_width": { + "description": "The width of a neural network input tensor.", + "type": "integer", + "default": 1 + }, + "train_period_days": { + "description": "Number of days to use for the training data (width of the sliding window)", + "type": "integer", + "default": 0 + }, + "backtest_period_days": { + "description": "Number of days to inference from the trained model before sliding the `train_period_days` window ", + "type": "number", + "default": 7 + }, + "identifier": { + "description": "A unique ID for the current model. Must be changed when modifying features.", + "type": "string", + "default": "example" + }, + "feature_parameters": { + "description": "The parameters used to engineer the feature set", + "type": "object", + "properties": { + "include_corr_pairlist": { + "description": "List of correlated pairs to include in the features.", + "type": "array" + }, + "include_timeframes": { + "description": "A list of timeframes that all indicators in `feature_engineering_expand_*()` will be created for.", + "type": "array" + }, + "label_period_candles": { + "description": "Number of candles into the future to use for labeling the period.This can be used in `set_freqai_targets()`.", + "type": "integer" + }, + "include_shifted_candles": { + "description": "Add features from previous candles to subsequent candles with the intent of adding historical information.", + "type": "integer", + "default": 0 + }, + "DI_threshold": { + "description": "Activates the use of the Dissimilarity Index for outlier detection when set to > 0.", + "type": "number", + "default": 0 + }, + "weight_factor": { + "description": "Weight training data points according to their recency.", + "type": "number", + "default": 0 + }, + "principal_component_analysis": { + "description": "Automatically reduce the dimensionality of the data set using Principal Component Analysis", + "type": "boolean", + "default": false + }, + "use_SVM_to_remove_outliers": { + "description": "Use SVM to remove outliers from the features.", + "type": "boolean", + "default": false + }, + "plot_feature_importances": { + "description": "Create feature importance plots for each model.", + "type": "integer", + "default": 0 + }, + "svm_params": { + "description": "All parameters available in Sklearn's `SGDOneClassSVM()`.", + "type": "object", + "properties": { + "shuffle": { + "description": "Whether to shuffle data before applying SVM.", + "type": "boolean", + "default": false + }, + "nu": { + "type": "number", + "default": 0.1 + } + } + }, + "shuffle_after_split": { + "description": "Split the data into train and test sets, and then shuffle both sets individually.", + "type": "boolean", + "default": false + }, + "buffer_train_data_candles": { + "description": "Cut `buffer_train_data_candles` off the beginning and end of the training data *after* the indicators were populated.", + "type": "integer", + "default": 0 + } + }, + "required": [ + "include_timeframes", + "include_corr_pairlist" + ] + }, + "data_split_parameters": { + "descriptions": "Additional parameters for scikit-learn's test_train_split() function.", + "type": "object", + "properties": { + "test_size": { + "type": "number" + }, + "random_state": { + "type": "integer" + }, + "shuffle": { + "type": "boolean", + "default": false + } + } + }, + "model_training_parameters": { + "description": "Flexible dictionary that includes all parameters available by the selected model library. ", + "type": "object" + }, + "rl_config": { + "type": "object", + "properties": { + "drop_ohlc_from_features": { + "description": "Do not include the normalized ohlc data in the feature set.", + "type": "boolean", + "default": false + }, + "train_cycles": { + "description": "Number of training cycles to perform.", + "type": "integer" + }, + "max_trade_duration_candles": { + "description": "Guides the agent training to keep trades below desired length.", + "type": "integer" + }, + "add_state_info": { + "description": "Include state information in the feature set for training and inference.", + "type": "boolean", + "default": false + }, + "max_training_drawdown_pct": { + "description": "Maximum allowed drawdown percentage during training.", + "type": "number", + "default": 0.02 + }, + "cpu_count": { + "description": "Number of threads/CPU's to use for training.", + "type": "integer", + "default": 1 + }, + "model_type": { + "description": "Model string from stable_baselines3 or SBcontrib.", + "type": "string", + "default": "PPO" + }, + "policy_type": { + "description": "One of the available policy types from stable_baselines3.", + "type": "string", + "default": "MlpPolicy" + }, + "net_arch": { + "description": "Architecture of the neural network.", + "type": "array", + "default": [ + 128, + 128 + ] + }, + "randomize_starting_position": { + "description": "Randomize the starting point of each episode to avoid overfitting.", + "type": "boolean", + "default": false + }, + "progress_bar": { + "description": "Display a progress bar with the current progress.", + "type": "boolean", + "default": true + }, + "model_reward_parameters": { + "description": "Parameters for configuring the reward model.", + "type": "object", + "properties": { + "rr": { + "type": "number", + "default": 1, + "description": "Reward ratio parameter." + }, + "profit_aim": { + "type": "number", + "default": 0.025, + "description": "Profit aim parameter." + } + } + } + } + } + }, + "required": [ + "enabled", + "train_period_days", + "backtest_period_days", + "identifier", + "feature_parameters", + "data_split_parameters" + ] + } + } +} \ No newline at end of file diff --git a/freqtrade/configuration/config_schema.py b/freqtrade/configuration/config_schema.py index aec0cb94a..7beed69e6 100644 --- a/freqtrade/configuration/config_schema.py +++ b/freqtrade/configuration/config_schema.py @@ -26,115 +26,296 @@ from freqtrade.enums import RPCMessageType __MESSAGE_TYPE_DICT: Dict[str, Dict[str, str]] = {x: {"type": "object"} for x in RPCMessageType} +__IN_STRATEGY = "\nUsually specified in the strategy and missing in the configuration." + 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"}, + "max_open_trades": { + "description": "Maximum number of open trades. -1 for unlimited.", + "type": ["integer", "number"], + "minimum": -1, + }, + "new_pairs_days": { + "description": "Download data of new pairs for given number of days", + "type": "integer", + "default": 30, + }, + "timeframe": { + "description": ( + f"The timeframe to use (e.g `1m`, `5m`, `15m`, `30m`, `1h` ...). {__IN_STRATEGY}" + ), + "type": "string", + }, + "stake_currency": { + "description": "Currency used for staking.", + "type": "string", + }, "stake_amount": { + "description": "Amount to stake per trade.", "type": ["number", "string"], "minimum": 0.0001, "pattern": UNLIMITED_STAKE_AMOUNT, }, - "tradable_balance_ratio": {"type": "number", "minimum": 0.0, "maximum": 1, "default": 0.99}, + "tradable_balance_ratio": { + "description": "Ratio of balance that is tradable.", + "type": "number", + "minimum": 0.0, + "maximum": 1, + "default": 0.99, + }, "available_capital": { + "description": "Total capital available for trading.", "type": "number", "minimum": 0, }, - "amend_last_stake_amount": {"type": "boolean", "default": False}, + "amend_last_stake_amount": { + "description": "Whether to amend the last stake amount.", + "type": "boolean", + "default": False, + }, "last_stake_amount_min_ratio": { + "description": "Minimum ratio for the last stake amount.", "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"}, + "fiat_display_currency": { + "description": "Fiat currency for display purposes.", + "type": "string", + "enum": SUPPORTED_FIAT, + }, + "dry_run": { + "description": "Enable or disable dry run mode.", + "type": "boolean", + }, + "dry_run_wallet": { + "description": "Initial wallet balance for dry run mode.", + "type": "number", + "default": DRY_RUN_WALLET, + }, + "cancel_open_orders_on_exit": { + "description": "Cancel open orders when exiting.", + "type": "boolean", + "default": False, + }, + "process_only_new_candles": { + "description": "Process only new candles.", + "type": "boolean", + }, "minimal_roi": { + "description": f"Minimum return on investment. {__IN_STRATEGY}", "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"}, + "amount_reserve_percent": { + "description": "Percentage of amount to reserve.", + "type": "number", + "minimum": 0.0, + "maximum": 0.5, + }, + "stoploss": { + "description": f"Value (as ratio) to use as Stoploss value. {__IN_STRATEGY}", + "type": "number", + "maximum": 0, + "exclusiveMaximum": True, + }, + "trailing_stop": { + "description": f"Enable or disable trailing stop. {__IN_STRATEGY}", + "type": "boolean", + }, + "trailing_stop_positive": { + "description": f"Positive offset for trailing stop. {__IN_STRATEGY}", + "type": "number", + "minimum": 0, + "maximum": 1, + }, + "trailing_stop_positive_offset": { + "description": f"Offset for trailing stop to activate. {__IN_STRATEGY}", + "type": "number", + "minimum": 0, + "maximum": 1, + }, + "trailing_only_offset_is_reached": { + "description": f"Use trailing stop only when offset is reached. {__IN_STRATEGY}", + "type": "boolean", + }, + "use_exit_signal": { + "description": f"Use exit signal for trades. {__IN_STRATEGY}", + "type": "boolean", + }, + "exit_profit_only": { + "description": ( + "Exit only when in profit. Exit signals are ignored as " + f"long as profit is < exit_profit_offset. {__IN_STRATEGY}" + ), + "type": "boolean", + }, + "exit_profit_offset": { + "description": f"Offset for profit exit. {__IN_STRATEGY}", + "type": "number", + }, + "fee": { + "description": "Trading fee percentage. Can help to simulate slippage in backtesting", + "type": "number", + "minimum": 0, + "maximum": 0.1, + }, + "ignore_roi_if_entry_signal": { + "description": f"Ignore ROI if entry signal is present. {__IN_STRATEGY}", + "type": "boolean", + }, + "ignore_buying_expired_candle_after": { + "description": f"Ignore buying after candle expiration time. {__IN_STRATEGY}", + "type": "number", + }, + "trading_mode": { + "description": "Mode of trading (e.g., spot, margin).", + "type": "string", + "enum": TRADING_MODES, + }, + "margin_mode": { + "description": "Margin mode for trading.", + "type": "string", + "enum": MARGIN_MODES, + }, + "reduce_df_footprint": { + "description": "Reduce DataFrame footprint by casting columns to float32/int32.", + "type": "boolean", + "default": False, + }, + "minimum_trade_amount": { + "description": "Minimum amount for a trade - only used for lookahead-analysis", + "type": "number", + "default": 10, + }, + "targeted_trade_amount": { + "description": "Targeted trade amount for lookahead analysis.", + "type": "number", + "default": 20, + }, + "lookahead_analysis_exportfilename": { + "description": "csv Filename for lookahead analysis export.", + "type": "string", + }, "startup_candle": { + "description": "Startup candle configuration.", "type": "array", "uniqueItems": True, "default": [199, 399, 499, 999, 1999], }, - "liquidation_buffer": {"type": "number", "minimum": 0.0, "maximum": 0.99}, + "liquidation_buffer": { + "description": "Buffer ratio for liquidation.", + "type": "number", + "minimum": 0.0, + "maximum": 0.99, + }, "backtest_breakdown": { + "description": "Breakdown configuration for backtesting.", "type": "array", "items": {"type": "string", "enum": BACKTEST_BREAKDOWNS}, }, - "bot_name": {"type": "string"}, + "bot_name": { + "description": "Name of the trading bot. Passed via API to a client.", + "type": "string", + }, "unfilledtimeout": { + "description": f"Timeout configuration for unfilled orders. {__IN_STRATEGY}", "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": { + "description": "Timeout for entry orders in unit.", + "type": "number", + "minimum": 1, + }, + "exit": { + "description": "Timeout for exit orders in unit.", + "type": "number", + "minimum": 1, + }, + "exit_timeout_count": { + "description": "Number of times to retry exit orders before giving up.", + "type": "number", + "minimum": 0, + "default": 0, + }, + "unit": { + "description": "Unit of time for the timeout (e.g., seconds, minutes).", + "type": "string", + "enum": TIMEOUT_UNITS, + "default": "minutes", + }, }, }, "entry_pricing": { + "description": "Configuration for entry pricing.", "type": "object", "properties": { "price_last_balance": { + "description": "Balance ratio for the last price.", "type": "number", "minimum": 0, "maximum": 1, "exclusiveMaximum": False, }, - "price_side": {"type": "string", "enum": PRICING_SIDES, "default": "same"}, - "use_order_book": {"type": "boolean"}, + "price_side": { + "description": "Side of the price to use (e.g., bid, ask, same).", + "type": "string", + "enum": PRICING_SIDES, + "default": "same", + }, + "use_order_book": { + "description": "Whether to use the order book for pricing.", + "type": "boolean", + }, "order_book_top": { + "description": "Top N levels of the order book to consider.", "type": "integer", "minimum": 1, "maximum": 50, }, "check_depth_of_market": { + "description": "Configuration for checking the depth of the market.", "type": "object", "properties": { - "enabled": {"type": "boolean"}, - "bids_to_ask_delta": {"type": "number", "minimum": 0}, + "enabled": { + "description": "Enable or disable depth of market check.", + "type": "boolean", + }, + "bids_to_ask_delta": { + "description": "Delta between bids and asks to consider.", + "type": "number", + "minimum": 0, + }, }, }, }, "required": ["price_side"], }, "exit_pricing": { + "description": "Configuration for exit pricing.", "type": "object", "properties": { - "price_side": {"type": "string", "enum": PRICING_SIDES, "default": "same"}, + "price_side": { + "description": "Side of the price to use (e.g., bid, ask, same).", + "type": "string", + "enum": PRICING_SIDES, + "default": "same", + }, "price_last_balance": { + "description": "Balance ratio for the last price.", "type": "number", "minimum": 0, "maximum": 1, "exclusiveMaximum": False, }, - "use_order_book": {"type": "boolean"}, + "use_order_book": { + "description": "Whether to use the order book for pricing.", + "type": "boolean", + }, "order_book_top": { + "description": "Top N levels of the order book to consider.", "type": "integer", "minimum": 1, "maximum": 50, @@ -142,24 +323,63 @@ CONF_SCHEMA = { }, "required": ["price_side"], }, - "custom_price_max_distance_ratio": {"type": "number", "minimum": 0.0}, + "custom_price_max_distance_ratio": { + "description": "Maximum distance ratio between current and custom entry or exit price.", + "type": "number", + "minimum": 0.0, + "maximum": 1, + "default": 0.02, + }, "order_types": { + "description": f"Configuration of order types. {__IN_STRATEGY}", "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}, + "entry": { + "description": "Order type for entry (e.g., limit, market).", + "type": "string", + "enum": ORDERTYPE_POSSIBILITIES, + }, + "exit": { + "description": "Order type for exit (e.g., limit, market).", + "type": "string", + "enum": ORDERTYPE_POSSIBILITIES, + }, + "force_exit": { + "description": "Order type for forced exit (e.g., limit, market).", + "type": "string", + "enum": ORDERTYPE_POSSIBILITIES, + }, + "force_entry": { + "description": "Order type for forced entry (e.g., limit, market).", + "type": "string", + "enum": ORDERTYPE_POSSIBILITIES, + }, "emergency_exit": { + "description": "Order type for emergency exit (e.g., limit, market).", "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": { + "description": "Order type for stop loss (e.g., limit, market).", + "type": "string", + "enum": ORDERTYPE_POSSIBILITIES, + }, + "stoploss_on_exchange": { + "description": "Whether to place stop loss on the exchange.", + "type": "boolean", + }, + "stoploss_price_type": { + "description": "Price type for stop loss (e.g., last, mark, index).", + "type": "string", + "enum": STOPLOSS_PRICE_TYPES, + }, + "stoploss_on_exchange_interval": { + "description": "Interval for stop loss on exchange in seconds.", + "type": "number", + }, "stoploss_on_exchange_limit_ratio": { + "description": "Limit ratio for stop loss on exchange.", "type": "number", "minimum": 0.0, "maximum": 1.0, @@ -168,80 +388,180 @@ CONF_SCHEMA = { "required": ["entry", "exit", "stoploss", "stoploss_on_exchange"], }, "order_time_in_force": { + "description": f"Time in force configuration for orders. {__IN_STRATEGY}", "type": "object", "properties": { - "entry": {"type": "string", "enum": ORDERTIF_POSSIBILITIES}, - "exit": {"type": "string", "enum": ORDERTIF_POSSIBILITIES}, + "entry": { + "description": "Time in force for entry orders.", + "type": "string", + "enum": ORDERTIF_POSSIBILITIES, + }, + "exit": { + "description": "Time in force for exit orders.", + "type": "string", + "enum": ORDERTIF_POSSIBILITIES, + }, }, "required": REQUIRED_ORDERTIF, }, "coingecko": { + "description": "Configuration for CoinGecko API.", "type": "object", "properties": { - "is_demo": {"type": "boolean", "default": True}, - "api_key": {"type": "string"}, + "is_demo": { + "description": "Whether to use CoinGecko in demo mode.", + "type": "boolean", + "default": True, + }, + "api_key": {"description": "API key for accessing CoinGecko.", "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"}, + "exchange": { + "description": "Exchange configuration.", + "$ref": "#/definitions/exchange", + }, + "edge": { + "description": "Edge configuration.", + "$ref": "#/definitions/edge", + }, + "freqai": { + "description": "FreqAI configuration.", + "$ref": "#/definitions/freqai", + }, + "external_message_consumer": { + "description": "Configuration for external message consumer.", + "$ref": "#/definitions/external_message_consumer", + }, "experimental": { + "description": "Experimental configuration.", "type": "object", "properties": {"block_bad_exchanges": {"type": "boolean"}}, }, "pairlists": { + "description": "Configuration for pairlists.", "type": "array", "items": { "type": "object", "properties": { - "method": {"type": "string", "enum": AVAILABLE_PAIRLISTS}, + "method": { + "description": "Method used for generating the pairlist.", + "type": "string", + "enum": AVAILABLE_PAIRLISTS, + }, }, "required": ["method"], }, }, "protections": { + "description": "Configuration for various 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}, + "method": { + "description": "Method used for the protection.", + "type": "string", + "enum": AVAILABLE_PROTECTIONS, + }, + "stop_duration": { + "description": ( + "Duration to lock the pair after a protection is triggered, " + "in minutes." + ), + "type": "number", + "minimum": 0.0, + }, + "stop_duration_candles": { + "description": ( + "Duration to lock the pair after a protection is triggered, in " + "number of candles." + ), + "type": "number", + "minimum": 0, + }, + "trade_limit": { + "description": "Minimum number of trades required during lookback period.", + "type": "number", + "minimum": 1, + }, + "lookback_period": { + "description": "Period to look back for protection checks, in minutes.", + "type": "number", + "minimum": 1, + }, + "lookback_period_candles": { + "description": ( + "Period to look back for protection checks, in number " "of candles." + ), + "type": "number", + "minimum": 1, + }, }, "required": ["method"], }, }, "telegram": { + "description": "Telegram settings.", "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}, + "enabled": { + "description": "Enable Telegram notifications.", + "type": "boolean", + }, + "token": {"description": "Telegram bot token.", "type": "string"}, + "chat_id": { + "description": "Telegram chat ID", + "type": "string", + }, + "allow_custom_messages": { + "description": "Allow sending custom messages from the Strategy.", + "type": "boolean", + "default": True, + }, + "balance_dust_level": { + "description": "Minimum balance level to consider as dust.", + "type": "number", + "minimum": 0.0, + }, "notification_settings": { + "description": "Settings for different types of notifications.", "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}, + "status": { + "description": "Telegram setting for status updates.", + "type": "string", + "enum": TELEGRAM_SETTING_OPTIONS, + }, + "warning": { + "description": "Telegram setting for warnings.", + "type": "string", + "enum": TELEGRAM_SETTING_OPTIONS, + }, + "startup": { + "description": "Telegram setting for startup messages.", + "type": "string", + "enum": TELEGRAM_SETTING_OPTIONS, + }, + "entry": { + "description": "Telegram setting for entry signals.", + "type": "string", + "enum": TELEGRAM_SETTING_OPTIONS, + }, "entry_fill": { + "description": "Telegram setting for entry fill signals.", "type": "string", "enum": TELEGRAM_SETTING_OPTIONS, "default": "off", }, "entry_cancel": { + "description": "Telegram setting for entry cancel signals.", "type": "string", "enum": TELEGRAM_SETTING_OPTIONS, }, "exit": { + "description": "Telegram setting for exit signals.", "type": ["string", "object"], "additionalProperties": { "type": "string", @@ -249,38 +569,39 @@ CONF_SCHEMA = { }, }, "exit_fill": { + "description": "Telegram setting for exit fill signals.", "type": "string", "enum": TELEGRAM_SETTING_OPTIONS, "default": "on", }, - "exit_cancel": {"type": "string", "enum": TELEGRAM_SETTING_OPTIONS}, + "exit_cancel": { + "description": "Telegram setting for exit cancel signals.", + "type": "string", + "enum": TELEGRAM_SETTING_OPTIONS, + }, "protection_trigger": { + "description": "Telegram setting for protection triggers.", "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": { + "description": "Telegram setting for global protection triggers.", "type": "string", "enum": TELEGRAM_SETTING_OPTIONS, "default": "on", }, }, }, - "reload": {"type": "boolean"}, + "reload": { + "description": "Add Reload button to certain messages.", + "type": "boolean", + }, }, "required": ["enabled", "token", "chat_id"], }, "webhook": { + "description": "Webhook settings.", "type": "object", "properties": { "enabled": {"type": "boolean"}, @@ -289,18 +610,10 @@ CONF_SCHEMA = { "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": { + "description": "Discord settings.", "type": "object", "properties": { "enabled": {"type": "boolean"}, @@ -344,56 +657,153 @@ CONF_SCHEMA = { }, }, "api_server": { + "description": "API server settings.", "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"]}, + "enabled": {"description": "Whether the API server is enabled.", "type": "boolean"}, + "listen_ip_address": { + "description": "IP address the API server listens on.", + "format": "ipv4", + }, + "listen_port": { + "description": "Port the API server listens on.", + "type": "integer", + "minimum": 1024, + "maximum": 65535, + }, + "username": { + "description": "Username for API server authentication.", + "type": "string", + }, + "password": { + "description": "Password for API server authentication.", + "type": "string", + }, + "ws_token": { + "description": "WebSocket token for API server.", + "type": ["string", "array"], + "items": {"type": "string"}, + }, + "jwt_secret_key": { + "description": "Secret key for JWT authentication.", + "type": "string", + }, + "CORS_origins": { + "description": "List of allowed CORS origins.", + "type": "array", + "items": {"type": "string"}, + }, + "x": { + "description": "Logging verbosity level.", + "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"}, + "db_url": { + "description": "Database connection URL.", + "type": "string", + }, + "export": { + "description": "Type of data to export.", + "type": "string", + "enum": EXPORT_OPTIONS, + "default": "trades", + }, + "disableparamexport": { + "description": "Disable parameter export.", + "type": "boolean", + }, + "initial_state": { + "description": "Initial state of the system.", + "type": "string", + "enum": ["running", "stopped"], + }, + "force_entry_enable": { + "description": "Force enable entry.", + "type": "boolean", + }, + "disable_dataframe_checks": { + "description": "Disable checks on dataframes.", + "type": "boolean", + }, "internals": { + "description": "Internal settings.", "type": "object", "default": {}, "properties": { - "process_throttle_secs": {"type": "integer"}, - "interval": {"type": "integer"}, - "sd_notify": {"type": "boolean"}, + "process_throttle_secs": { + "description": "Throttle time in seconds for processing.", + "type": "integer", + }, + "interval": { + "description": "Interval time in seconds.", + "type": "integer", + }, + "sd_notify": { + "description": "Enable systemd notify.", + "type": "boolean", + }, }, }, "dataformat_ohlcv": { + "description": "Data format for OHLCV data.", "type": "string", "enum": AVAILABLE_DATAHANDLERS, "default": "feather", }, "dataformat_trades": { + "description": "Data format for trade data.", "type": "string", "enum": AVAILABLE_DATAHANDLERS, "default": "feather", }, - "position_adjustment_enable": {"type": "boolean"}, - "max_entry_position_adjustment": {"type": ["integer", "number"], "minimum": -1}, + "position_adjustment_enable": { + "description": f"Enable position adjustment. {__IN_STRATEGY}", + "type": "boolean", + }, + "max_entry_position_adjustment": { + "description": f"Maximum entry position adjustment allowed. {__IN_STRATEGY}", + "type": ["integer", "number"], + "minimum": -1, + }, "orderflow": { + "description": "Settings related to order flow.", "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}, + "cache_size": { + "description": "Size of the cache for order flow data.", + "type": "number", + "minimum": 1, + "default": 1500, + }, + "max_candles": { + "description": "Maximum number of candles to consider.", + "type": "number", + "minimum": 1, + "default": 1500, + }, + "scale": { + "description": "Scale factor for order flow data.", + "type": "number", + "minimum": 0.0, + }, + "stacked_imbalance_range": { + "description": "Range for stacked imbalance.", + "type": "number", + "minimum": 0, + }, + "imbalance_volume": { + "description": "Volume threshold for imbalance.", + "type": "number", + "minimum": 0, + }, + "imbalance_ratio": { + "description": "Ratio threshold for imbalance.", + "type": "number", + "minimum": 0.0, + }, }, "required": [ "max_candles", @@ -406,33 +816,62 @@ CONF_SCHEMA = { }, "definitions": { "exchange": { + "description": "Exchange configuration settings.", "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"}, + "name": {"description": "Name of the exchange.", "type": "string"}, + "enable_ws": { + "description": "Enable WebSocket connections to the exchange.", + "type": "boolean", + "default": True, + }, + "key": { + "description": "API key for the exchange.", + "type": "string", + "default": "", + }, + "secret": { + "description": "API secret for the exchange.", + "type": "string", + "default": "", + }, + "password": { + "description": "Password for the exchange, if required.", + "type": "string", + "default": "", + }, + "uid": {"description": "User ID for the exchange, if required.", "type": "string"}, "pair_whitelist": { + "description": "List of whitelisted trading pairs.", "type": "array", - "items": { - "type": "string", - }, + "items": {"type": "string"}, "uniqueItems": True, }, "pair_blacklist": { + "description": "List of blacklisted trading pairs.", "type": "array", - "items": { - "type": "string", - }, + "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"}, + "unknown_fee_rate": { + "description": "Fee rate for unknown markets.", + "type": "number", + }, + "outdated_offset": { + "description": "Offset for outdated data in minutes.", + "type": "integer", + "minimum": 1, + }, + "markets_refresh_interval": { + "description": "Interval for refreshing market data in minutes.", + "type": "integer", + "default": 60, + }, + "ccxt_config": {"description": "CCXT configuration settings.", "type": "object"}, + "ccxt_async_config": { + "description": "CCXT asynchronous configuration settings.", + "type": "object", + }, }, "required": ["name"], }, @@ -455,39 +894,77 @@ CONF_SCHEMA = { "required": ["process_throttle_secs", "allowed_risk"], }, "external_message_consumer": { + "description": "Configuration for external message consumer.", "type": "object", "properties": { - "enabled": {"type": "boolean", "default": False}, + "enabled": { + "description": "Whether the external message consumer is enabled.", + "type": "boolean", + "default": False, + }, "producers": { + "description": "List of producers for the external message consumer.", "type": "array", "items": { "type": "object", "properties": { - "name": {"type": "string"}, - "host": {"type": "string"}, + "name": { + "description": "Name of the producer.", + "type": "string", + }, + "host": { + "description": "Host of the producer.", + "type": "string", + }, "port": { + "description": "Port of the producer.", "type": "integer", "default": 8080, "minimum": 0, "maximum": 65535, }, - "secure": {"type": "boolean", "default": False}, - "ws_token": {"type": "string"}, + "secure": { + "description": "Whether to use SSL to connect to the producer.", + "type": "boolean", + "default": False, + }, + "ws_token": { + "description": "WebSocket token for the producer.", + "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}, + "wait_timeout": { + "description": "Wait timeout in seconds.", + "type": "integer", + "minimum": 0, + }, + "sleep_time": { + "description": "Sleep time in seconds before retrying to connect.", + "type": "integer", + "minimum": 0, + }, + "ping_timeout": { + "description": "Ping timeout in seconds.", + "type": "integer", + "minimum": 0, + }, + "remove_entry_exit_signals": { + "description": "Remove signal columns from the dataframe (set them to 0)", + "type": "boolean", + "default": False, + }, "initial_candle_limit": { + "description": "Initial candle limit.", "type": "integer", "minimum": 0, "maximum": 1500, "default": 1500, }, - "message_size_limit": { # In megabytes + "message_size_limit": { + "description": "Message size limit in megabytes.", "type": "integer", "minimum": 1, "maximum": 20, @@ -499,35 +976,150 @@ CONF_SCHEMA = { "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"}, + "enabled": { + "description": "Whether freqAI is enabled.", + "type": "boolean", + "default": False, + }, + "keras": { + "description": "Use Keras for model training.", + "type": "boolean", + "default": False, + }, + "write_metrics_to_disk": { + "description": "Write metrics to disk?", + "type": "boolean", + "default": False, + }, + "purge_old_models": { + "description": "Number of models to keep on disk.", + "type": ["boolean", "number"], + "default": 2, + }, + "conv_width": { + "description": "The width of a neural network input tensor.", + "type": "integer", + "default": 1, + }, + "train_period_days": { + "description": ( + "Number of days to use for the training data (width of the sliding window)" + ), + "type": "integer", + "default": 0, + }, + "backtest_period_days": { + "description": ( + "Number of days to inference from the trained model before sliding the " + "`train_period_days` window " + ), + "type": "number", + "default": 7, + }, + "identifier": { + "description": ( + "A unique ID for the current model. " + "Must be changed when modifying features." + ), + "type": "string", + "default": "example", + }, "feature_parameters": { + "description": "The parameters used to engineer the feature set", "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}, + "include_corr_pairlist": { + "description": "List of correlated pairs to include in the features.", + "type": "array", + }, + "include_timeframes": { + "description": ( + "A list of timeframes that all indicators in " + "`feature_engineering_expand_*()` will be created for." + ), + "type": "array", + }, + "label_period_candles": { + "description": ( + "Number of candles into the future to use for labeling the period." + "This can be used in `set_freqai_targets()`." + ), + "type": "integer", + }, + "include_shifted_candles": { + "description": ( + "Add features from previous candles to subsequent candles with " + "the intent of adding historical information." + ), + "type": "integer", + "default": 0, + }, + "DI_threshold": { + "description": ( + "Activates the use of the Dissimilarity Index for " + "outlier detection when set to > 0." + ), + "type": "number", + "default": 0, + }, + "weight_factor": { + "description": ( + "Weight training data points according to their recency." + ), + "type": "number", + "default": 0, + }, + "principal_component_analysis": { + "description": ( + "Automatically reduce the dimensionality of the data set using " + "Principal Component Analysis" + ), + "type": "boolean", + "default": False, + }, + "use_SVM_to_remove_outliers": { + "description": "Use SVM to remove outliers from the features.", + "type": "boolean", + "default": False, + }, + "plot_feature_importances": { + "description": "Create feature importance plots for each model.", + "type": "integer", + "default": 0, + }, "svm_params": { + "description": ( + "All parameters available in Sklearn's `SGDOneClassSVM()`." + ), "type": "object", "properties": { - "shuffle": {"type": "boolean", "default": False}, - "nu": {"type": "number", "default": 0.1}, + "shuffle": { + "description": "Whether to shuffle data before applying SVM.", + "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}, + "shuffle_after_split": { + "description": ( + "Split the data into train and test sets, and then shuffle " + "both sets individually." + ), + "type": "boolean", + "default": False, + }, + "buffer_train_data_candles": { + "description": ( + "Cut `buffer_train_data_candles` off the beginning and end of the " + "training data *after* the indicators were populated." + ), + "type": "integer", + "default": 0, + }, }, "required": [ "include_timeframes", @@ -535,6 +1127,9 @@ CONF_SCHEMA = { ], }, "data_split_parameters": { + "descriptions": ( + "Additional parameters for scikit-learn's test_train_split() function." + ), "type": "object", "properties": { "test_size": {"type": "number"}, @@ -542,26 +1137,94 @@ CONF_SCHEMA = { "shuffle": {"type": "boolean", "default": False}, }, }, - "model_training_parameters": {"type": "object"}, + "model_training_parameters": { + "description": ( + "Flexible dictionary that includes all parameters available by " + "the selected model library. " + ), + "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}, + "drop_ohlc_from_features": { + "description": ( + "Do not include the normalized ohlc data in the feature set." + ), + "type": "boolean", + "default": False, + }, + "train_cycles": { + "description": "Number of training cycles to perform.", + "type": "integer", + }, + "max_trade_duration_candles": { + "description": ( + "Guides the agent training to keep trades below desired length." + ), + "type": "integer", + }, + "add_state_info": { + "description": ( + "Include state information in the feature set for " + "training and inference." + ), + "type": "boolean", + "default": False, + }, + "max_training_drawdown_pct": { + "description": "Maximum allowed drawdown percentage during training.", + "type": "number", + "default": 0.02, + }, + "cpu_count": { + "description": "Number of threads/CPU's to use for training.", + "type": "integer", + "default": 1, + }, + "model_type": { + "description": "Model string from stable_baselines3 or SBcontrib.", + "type": "string", + "default": "PPO", + }, + "policy_type": { + "description": ( + "One of the available policy types from stable_baselines3." + ), + "type": "string", + "default": "MlpPolicy", + }, + "net_arch": { + "description": "Architecture of the neural network.", + "type": "array", + "default": [128, 128], + }, + "randomize_starting_position": { + "description": ( + "Randomize the starting point of each episode to avoid overfitting." + ), + "type": "boolean", + "default": False, + }, + "progress_bar": { + "description": "Display a progress bar with the current progress.", + "type": "boolean", + "default": True, + }, "model_reward_parameters": { + "description": "Parameters for configuring the reward model.", "type": "object", "properties": { - "rr": {"type": "number", "default": 1}, - "profit_aim": {"type": "number", "default": 0.025}, + "rr": { + "type": "number", + "default": 1, + "description": "Reward ratio parameter.", + }, + "profit_aim": { + "type": "number", + "default": 0.025, + "description": "Profit aim parameter.", + }, }, }, },