The Market Robo™
Vendor SDK

SDK API reference

Every class, lifecycle method, callback, and configuration type in the MQL5 SDK — the contract your Expert Advisor or indicator implements.

Base class & constructors

CTheMarketRobo_Base is the unified base class; CTheMarketRobo_Bot_Base is an alias.

Expert Advisor (Robot):

CTheMarketRobo_Base(string robot_version_uuid, IRobotConfig* robot_config)

Custom Indicator:

CTheMarketRobo_Base(string indicator_version_uuid) // One argument only

Call on_deinit() before destroying the instance (e.g. from OnDeinit).

Lifecycle methods

on_init(api_key, magic_number) for Robots;on_init(api_key) for Indicators. Returns INIT_SUCCEEDED or INIT_FAILED.

on_deinit(reason) — terminate session and cleanup. on_timer() — heartbeats and token refresh. on_chart_event(id, lparam, dparam, sparam) — SDK events (config/symbol/termination/token refresh).

Feature configuration

Call before on_init():

set_token_refresh_threshold(int seconds) // Default 60, range 60-3600 set_enable_config_change_requests(bool) // Default true set_enable_symbol_change_requests(bool) // Default true print_sdk_configuration() // Debug

Callbacks

Override in your class. Default implementations are empty (not pure virtual).

on_tick() // Robot: trading logic on_calculate(rates_total, prev_calculated, time, open, ...) // Indicator: return rates_total on_config_changed(string event_json) // Robot: config update from server on_symbol_changed(string event_json) // Robot: symbol list update on_termination_requested(string event_json) // Optional: default Alert + ExpertRemove/EventKillTimer

Getters: get_robot_version_uuid(), get_token_refresh_threshold(), is_indicator_mode(), is_robot_mode().

Config & symbol change — handling requests

The server can send config change and symbol change requests in the heartbeat (or start) response. The SDK delivers them to your robot, applies changes using your code (config) or SymbolSelect() (symbols), and sends the result back in the next heartbeat. Support is optional: use set_enable_config_change_requests(false) / set_enable_symbol_change_requests(false) to ignore.

Config change — request format (from server)

{ "id": "req-abc-123", "request": [ { "field_name": "lot_size", "new_value": 0.05 }, { "field_name": "max_trades", "new_value": 10 } ] }

For each item the SDK calls your validate_field(field_name, new_value_str, reason). If valid, it calls update_field(field_name, new_value_str). You must implement both so config changes apply. Values arrive as strings (e.g. "0.05", "10").

Example: update_field and validate_field

virtual bool update_field(string field_name, string new_value) override { if(field_name == "lot_size") { m_lot_size = StringToDouble(new_value); return true; } if(field_name == "max_trades") { m_max_trades = (int)StringToInteger(new_value); return true; } return false; } virtual bool validate_field(string field_name, string new_value, string &reason) override { if(field_name == "lot_size") { double v = StringToDouble(new_value); if(v < 0.01 || v > 10.0) { reason = "Lot size must be between 0.01 and 10"; return false; } return true; } if(field_name == "max_trades") { long v = StringToInteger(new_value); if(v < 1 || v > 50) { reason = "Max trades must be between 1 and 50"; return false; } return true; } reason = "Unknown field"; return false; }

Config change — response (SDK sends in next heartbeat)

"config_change_results": { "request_id": "req-abc-123", "status": "all_accepted", "results": [ { "field_name": "lot_size", "requested_value": "0.05", "accepted": true, "applied_value": "0.05" }, { "field_name": "max_trades", "requested_value": "10", "accepted": true, "applied_value": "10" } ] } // If rejected: "accepted": false, "error_code": "OUT_OF_RANGE", "error_message": "..."

Example: on_config_changed — react after changes

Called after the SDK has applied one or more config changes. Your config object already has the new values. Use this to recalculate, log, or alert.

virtual void on_config_changed(string event_json) override { CJAVal event; if(event.parse(event_json)) { // Per-field event (if SDK sends it): field, old_value, new_value if(event.has_key("field")) { string field = event["field"].get_string(); string newVal = event["new_value"].get_string(); Print("Config updated: ", field, " = ", newVal); } // Or request_id for batch if(event.has_key("request_id")) Print("Request ID: ", event["request_id"].get_string()); } CMyConfig* cfg = (CMyConfig*)m_robot_config; double lot = cfg.get_lot_size(); int max = cfg.get_max_trades(); // React: e.g. recalculate position size, log, Alert("Settings updated") }

Symbol change — request format (from server)

{ "id": "sym-req-456", "request": [ { "symbol": "EURUSD", "active_to_trade": true }, { "symbol": "GBPUSD", "active_to_trade": false } ] }

The SDK calls SymbolSelect(symbol_name, active_to_trade) for each item and updates its internal list. It then sends symbols_change_results in the next heartbeat. For each applied change it calls your on_symbol_changed with event JSON.

Example: on_symbol_changed — close positions when symbol disabled

virtual void on_symbol_changed(string event_json) override { CJAVal event; if(!event.parse(event_json)) return; string symbol = event["symbol"].get_string(); bool active = event["active_to_trade"].get_bool(); if(!active) { Print("Symbol ", symbol, " disabled — closing positions"); for(int i = PositionsTotal() - 1; i >= 0; i--) { if(PositionGetSymbol(i) == symbol) { ulong ticket = PositionGetInteger(POSITION_TICKET); if(!trade.PositionClose(ticket)) Print("Failed to close ", ticket); } } } }

Summary: SDK receives request → validates (config) / applies SymbolSelect (symbol) → your update_field applies config values → SDK builds result → next heartbeat sends result. Optionally override on_config_changed / on_symbol_changed to react.

IRobotConfig

Override: define_schema(), apply_defaults(), to_json(), update_from_json(CJAVal), update_field(name, value), get_field_as_string(name). Use m_schema.add_field() with CConfigField.

Provided: validate_field, get_field_names, get_schema, get_schema_json, get_field_definition.

CConfigField & schema

Factory methods: create_integer, create_decimal, create_boolean, create_radio, create_multiple. Fluent setters: with_description, with_range, with_precision, with_option, with_group, etc.

m_schema.add_field( CConfigField::create_integer("max_trades", "Max Trades", true, 5) .with_range(1, 20) .with_group("Risk", 1) );

Events & constants

Event IDs: SDK_EVENT_CONFIG_CHANGED, SDK_EVENT_SYMBOL_CHANGED, SDK_EVENT_TERMINATION_START/END, SDK_EVENT_TERMINATION_REQUESTED, SDK_EVENT_TOKEN_REFRESH.

Constants: SDK_API_BASE_URL, SDK_DEFAULT_TOKEN_REFRESH_THRESHOLD (60), SDK_DEFAULT_HEARTBEAT_INTERVAL (60), SDK_MAX_HEARTBEAT_INTERVAL (300). See and endpoint flows for request/response details.

Error handling

Init: "Invalid robot_version_uuid" (36 chars), "API Key is required", "Failed to start SDK session". Robots: auth failure triggers ExpertRemove(). Indicators: SDK stops timer and alerts user (no self-removal). Use token refresh threshold and monitor logs.