The Market Robo™
Vendor SDK

Configuration schema

How to describe your robot's settings so the Vendor Portal can validate them before you submit.

Overview & why it matters

The Robot Config Component Schema is the platform rule set for how vendors define configuration options for Expert Advisors. It applies only to robots; Custom Indicators do not have configurable parameters and do not use this schema.

When you submit a robot version on the Vendor Portal, the platform validates your configuration schema against this component schema before allowing submission. If your config fields or default values do not conform — wrong types, invalid keys, defaults out of range, missing required properties, or broken dependsOn — submission is blocked and you will see validation errors. You must fix the schema and/or default config to match the rules described here.

Your MQL5 IRobotConfig implementation (e.g. define_schema(), to_json(), update_from_json()) should produce a structure that aligns with this schema so the dashboard and backend stay in sync with your EA. The schema is versioned (v1); the same version is used in the SDK repository docs and by the Vendor Portal.

Component types

You can use five field types. Each field has required properties: type, key, label, required, default. Keys must match ^[a-z][a-z0-9_]*$ (lowercase, underscores, no spaces) and be unique.

Types:

integer — Whole numbers. Optional: minimum, maximum, step.

decimal — Floating point. Optional: minimum, maximum, step, precision.

boolean — True/false. Default must be true or false.

radio — Single choice. Required: options (array of {"value", "label"}), at least 2. Default must be one of the option values.

multiple — Multiple choice. Required: options. Optional: minSelections, maxSelections. Default must be an array of option values.

Optional for all: description, tooltip, group, order, dependsOn (conditional display: show field only when another field has a given value).

Schema structure

Your robot config schema is a JSON object with a single top-level key fields, an array of field objects. Default values are usually stored separately as default_config: a flat object whose keys are the field keys and whose values satisfy each field’s type and constraints.

{ "fields": [ { "type": "integer", "key": "max_trades", "label": "...", "required": true, "default": 5, ... }, ... ] }

Validation at submission

Before you can submit a robot version, the Vendor Portal validates:

• Root has fields array with at least one field.

• Each field has type, key, label, required, default; keys match the pattern and are unique.

• Type-specific rules: integer/decimal min/max and default in range; radio/multiple have ≥2 options and default in options; multiple default array length between minSelections and maxSelections.

dependsOn references an existing field and uses a valid condition; no circular dependencies.

default_config: every required field key present, no extra keys, all values valid for their field.

If validation fails, the portal returns error codes (e.g. INVALID_KEY_PATTERN, DEFAULT_OUT_OF_RANGE, DEFAULT_NOT_IN_OPTIONS). Fix the reported issues and resubmit.

Config & symbol change (optional)

Config change and symbol change support are not mandatory. Vendors can disable them with set_enable_config_change_requests(false) and set_enable_symbol_change_requests(false). If enabled, the SDK delivers the server’s change requests and builds the response; you implement the config side and optionally react in callbacks.

Config change: Server sends a request (e.g. in the heartbeat response) with field_name and new_value per field. The SDK calls your validate_field() then update_field() to apply each change, builds a result (accepted/rejected per item, plus overall status), and sends that result in the next heartbeat as config_change_results. You must implement update_field() and validate_field() (or schema-based validation) for config changes to work. Optionally override on_config_changed(event_json) to react after changes.

Symbol change: Server sends a request with symbol and active_to_trade. The SDK calls SymbolSelect(), updates its internal list, builds the result, and sends it in the next heartbeat as symbols_change_results. Optionally override on_symbol_changed(event_json) to react (e.g. close positions when a symbol is disabled).

Full request/response flow and implementation details are in the SDK docs: Architecture Overview and API Reference in the sample library repository.

Example: Simple config

A minimal valid schema with one field of each type: integer, decimal, boolean, radio, and multiple. Each field has group and order for UI grouping. The key values (e.g. max_trades, trading_sessions) are what you use in your MQL5 config class and in default_config.

{ "fields": [ { "type": "integer", "key": "max_trades", "label": "Maximum Concurrent Trades", "required": true, "default": 5, "minimum": 1, "maximum": 20, "step": 1, "description": "Maximum number of trades to open simultaneously", "group": "Risk Management", "order": 1 }, { "type": "decimal", "key": "stop_loss_percent", "label": "Stop Loss Percentage", "required": true, "default": 2.0, "minimum": 0.5, "maximum": 10.0, "step": 0.5, "precision": 1, "group": "Risk Management", "order": 2 }, { "type": "boolean", "key": "use_trailing_stop", "label": "Use Trailing Stop Loss", "required": true, "default": false, "group": "Features", "order": 1 }, { "type": "radio", "key": "trading_mode", "label": "Trading Mode", "required": true, "default": "moderate", "options": [ {"value": "conservative", "label": "Conservative"}, {"value": "moderate", "label": "Moderate"}, {"value": "aggressive", "label": "Aggressive"} ], "group": "Strategy", "order": 1 }, { "type": "multiple", "key": "trading_sessions", "label": "Active Trading Sessions", "required": true, "default": ["london", "newyork"], "options": [ {"value": "tokyo", "label": "Tokyo"}, {"value": "london", "label": "London"}, {"value": "newyork", "label": "New York"}, {"value": "sydney", "label": "Sydney"} ], "minSelections": 1, "maxSelections": 4, "group": "Trading Hours", "order": 1 } ] }

Example: Complex config

A larger schema with many fields, multiple groups (Strategy, Risk Management, Advanced Features, Trading Hours, Entry Conditions, Notifications), and conditional fields via dependsOn. For example, scalping_timeframe_minutes is shown only when trading_strategy equals "scalping"; risk_per_trade_percent when use_dynamic_lot_sizing is true. The full JSON (19 fields) is in the SDK repository.

{ "fields": [ { "type": "radio", "key": "trading_strategy", "label": "Trading Strategy", "required": true, "default": "scalping", "options": [ {"value": "scalping", "label": "Scalping"}, {"value": "day_trading", "label": "Day Trading"}, {"value": "swing_trading", "label": "Swing Trading"}, {"value": "position_trading", "label": "Position Trading"} ], "group": "Strategy", "order": 1 }, { "type": "integer", "key": "scalping_timeframe_minutes", "label": "Scalping Timeframe (minutes)", "required": true, "default": 5, "minimum": 1, "maximum": 15, "dependsOn": { "field": "trading_strategy", "condition": "equals", "value": "scalping" }, "group": "Strategy", "order": 2 }, { "type": "integer", "key": "max_trades", "label": "Maximum Concurrent Trades", "required": true, "default": 5, "minimum": 1, "maximum": 50, "group": "Risk Management", "order": 1 }, { "type": "decimal", "key": "lot_size", "label": "Lot Size", "required": true, "default": 0.01, "minimum": 0.01, "maximum": 10.0, "precision": 2, "group": "Risk Management", "order": 2 }, { "type": "boolean", "key": "use_dynamic_lot_sizing", "label": "Use Dynamic Lot Sizing", "required": true, "default": false, "group": "Risk Management", "order": 3 }, { "type": "decimal", "key": "risk_per_trade_percent", "label": "Risk Per Trade (%)", "required": true, "default": 1.0, "minimum": 0.1, "maximum": 5.0, "dependsOn": { "field": "use_dynamic_lot_sizing", "condition": "equals", "value": true }, "group": "Risk Management", "order": 4 } // ... more fields: stop_loss_pips, take_profit_pips, use_trailing_stop, // trailing_stop_distance (dependsOn), use_breakeven, breakeven_trigger_pips, // trading_sessions (multiple), avoid_news_events, news_buffer_minutes (dependsOn), // max_spread_pips, min_candle_body_pips, order_execution_mode, max_slippage_pips (dependsOn), // enable_email_alerts, alert_events (multiple, dependsOn). Full JSON in SDK repo. ] }

Example: Default values

The default_config object must have one entry per field key, with values that match the field type and constraints. For the simple schema above, a valid default config is:

{ "max_trades": 5, "stop_loss_percent": 2.0, "use_trailing_stop": false, "trading_mode": "moderate", "trading_sessions": ["london", "newyork"] }

All required field keys are present; values match types (integer, number, boolean, string, array of strings). For radio the value must be one of the option values; for multiple the array must only contain option values and respect minSelections/maxSelections. The Vendor Portal validates default_config against your schema before allowing submission.

More detail on how schema and default config relate, including type-by-type rules and validation, is in the SDK repo: docs/schemas/robot_config_component_schema/examples/with-default-values.md.