如何将 MetaTrader 5 与 PostgreSQL 连接·综合运用
(3/3)·从原生 WebRequest 到 REST API 抽象层,打通 MQL5 与远程 Postgres 的数据读写闭环
「把远端账户快照落进本地变量」
当 HTTP 返回码为 200 时,说明远端账户接口已正常响应,这时候要把 JSON 反序列化成可操作的字段。下面这段代码演示了如何用 CJAVal 把返回结果拆成 double、long、string、bool 四类本地变量。 double 段覆盖了余额、信用、利润、净值、已用保证金、空闲保证金、保证金水平、爆仓 call/so 阈值——这些是盯盘时最容易被忽略但决定风控边界的数字。 long 与 string 段拿到登录号、杠杆、交易模式、公司名、币种、服务器等静态身份;bool 段则直接暴露 EA 与手动交易是否被 broker 放行。 外汇与贵金属自带高杠杆高风险,拿到 a_margin_level 与 a_margin_so_so 后,应自行核对平台强平线,勿盲信接口返回值。
if(res == class="num">200)class=class="str">"cmt">// HTTP result code class="num">200 (OK) { CJAVal data; data.Deserialize(result); class=class="str">"cmt">//--- doubles class="type">class="kw">double a_balance = data[class="num">0]["a_balance"].ToDbl(); class="type">class="kw">double a_credit = data[class="num">0]["a_credit"].ToDbl(); class="type">class="kw">double a_profit = data[class="num">0]["a_profit"].ToDbl(); class="type">class="kw">double a_equity = data[class="num">0]["a_equity"].ToDbl(); class="type">class="kw">double a_margin = data[class="num">0]["a_margin"].ToDbl(); class="type">class="kw">double a_margin_free = data[class="num">0]["a_margin_free"].ToDbl(); class="type">class="kw">double a_margin_level = data[class="num">0]["a_margin_level"].ToDbl(); class="type">class="kw">double a_margin_so_call = data[class="num">0]["a_margin_so_call"].ToDbl(); class="type">class="kw">double a_margin_so_so = data[class="num">0]["a_margin_so_so"].ToDbl(); class=class="str">"cmt">//--- longs class="type">long a_login = data[class="num">0]["a_login"].ToInt(); class="type">long a_leverage = data[class="num">0]["a_leverage"].ToInt(); class="type">long a_trade_mode = data[class="num">0]["a_trade_mode"].ToInt(); class="type">long a_margin_so_mode = data[class="num">0]["a_margin_so_mode"].ToInt(); class="type">long a_id = data[class="num">0]["a_id"].ToInt(); class=class="str">"cmt">//--- database generated ID class=class="str">"cmt">//--- strings class="type">class="kw">string a_company = data[class="num">0]["a_company"].ToStr(); class="type">class="kw">string a_currency = data[class="num">0]["a_currency"].ToStr(); class="type">class="kw">string a_name = data[class="num">0]["a_name"].ToStr(); class="type">class="kw">string a_server = data[class="num">0]["a_server"].ToStr(); class=class="str">"cmt">//--- booleans class="type">bool a_ea_allowed = data[class="num">0]["a_ea_allowed"].ToBool(); class="type">bool a_trade_allowed = data[class="num">0]["a_trade_allowed"].ToBool();
if(res == class="num">200)class=class="str">"cmt">// HTTP result code class="num">200 (OK) { CJAVal data; data.Deserialize(result); class=class="str">"cmt">//--- doubles class="type">class="kw">double a_balance = data[class="num">0]["a_balance"].ToDbl(); class="type">class="kw">double a_credit = data[class="num">0]["a_credit"].ToDbl(); class="type">class="kw">double a_profit = data[class="num">0]["a_profit"].ToDbl(); class="type">class="kw">double a_equity = data[class="num">0]["a_equity"].ToDbl(); class="type">class="kw">double a_margin = data[class="num">0]["a_margin"].ToDbl(); class="type">class="kw">double a_margin_free = data[class="num">0]["a_margin_free"].ToDbl(); class="type">class="kw">double a_margin_level = data[class="num">0]["a_margin_level"].ToDbl(); class="type">class="kw">double a_margin_so_call = data[class="num">0]["a_margin_so_call"].ToDbl(); class="type">class="kw">double a_margin_so_so = data[class="num">0]["a_margin_so_so"].ToDbl(); class=class="str">"cmt">//--- longs class="type">long a_login = data[class="num">0]["a_login"].ToInt(); class="type">long a_leverage = data[class="num">0]["a_leverage"].ToInt(); class="type">long a_trade_mode = data[class="num">0]["a_trade_mode"].ToInt(); class="type">long a_margin_so_mode = data[class="num">0]["a_margin_so_mode"].ToInt(); class="type">long a_id = data[class="num">0]["a_id"].ToInt(); class=class="str">"cmt">//--- database generated ID class=class="str">"cmt">//--- strings class="type">class="kw">string a_company = data[class="num">0]["a_company"].ToStr(); class="type">class="kw">string a_currency = data[class="num">0]["a_currency"].ToStr(); class="type">class="kw">string a_name = data[class="num">0]["a_name"].ToStr(); class="type">class="kw">string a_server = data[class="num">0]["a_server"].ToStr(); class=class="str">"cmt">//--- booleans class="type">bool a_ea_allowed = data[class="num">0]["a_ea_allowed"].ToBool(); class="type">bool a_trade_allowed = data[class="num">0]["a_trade_allowed"].ToBool();
◍ 把账户状态字段一口气打出来
这段脚本的核心动作,是把当前 MT5 账户的关键字段通过 printf 直接输出到专家日志,方便你在不打开终端账户窗口的情况下快速核对。 被注释掉的 Server headers 行说明原始请求里还能拿到 HTTP 头,但本段只聚焦账户结构本身,没有去解析响应头。 double 类字段覆盖了 Balance、Credit、Profit、Equity、Margin、Margin Free、Margin Level、Margin Call Level、Margin Stop Out Level,共 9 项数值,分别对应账户权益与强平阈值链。 long 类包括 Login、Leverage、Trade Mode、Margin Stop Out Mode、Database ID,字符串类有 Company、Currency、Platform Name、Server,布尔类用 %d 输出 Expert Advisor Allowed 与 Trade Allowed。 若请求返回非 200,else 分支会用 PrintFormat 把 URL 和错误码打到日志,你可以据此判断是 broker 接口拒绝还是网络层问题。外汇与贵金属杠杆波动大,输出 Margin Level 后建议手动比对终端显示值,高风险品种下数值偏差可能直接触发强平。
class=class="str">"cmt">//printf("Server headers: %s", headers); class=class="str">"cmt">//--- doubles printf("Balance: %d", a_balance); printf("Credit: %d", a_credit); printf("Profit: %d", a_profit); printf("Equity: %d", a_equity); printf("Margin: %d", a_margin); printf("Margin Free: %d", a_margin_free); printf("Margin Level: %d", a_margin_level); printf("Margin Call Level: %d", a_margin_so_call); printf("Margin Stop Out Level: %d", a_margin_so_so); class=class="str">"cmt">//--- longs printf("Login: %d", a_login); printf("Leverage: %d", a_leverage); printf("Trade Mode: %d", a_trade_mode); printf("Margin Stop Out Mode: %d", a_margin_so_mode); printf("Database ID: %d", a_id); class=class="str">"cmt">//--- strings printf("Company: %s", a_company); printf("Currency: %s", a_currency); printf("Platform Name: %s", a_name); printf("Server: %s", a_server); class=class="str">"cmt">//--- booleans printf("Expert Advisor Allowed: %d", a_ea_allowed); printf("Trade Allowed: %d", a_trade_allowed); Print("Done!"); } else PrintFormat("Request to &class="macro">#x27;%s&class="macro">#x27; failed with error code %d", url, res); } }
收束
前面两节把 MQL5 通过 REST API 对接 Postgres 的链路和 WSL 开发环境都搭清楚了,核心结论是用轻量 REST 替代专用驱动或 dll,省下的不只是授权费,还有 Windows 下编译排错的精力。 附件里两个 zip 共约 18 KB(5.99 KB 基础文件 + 12.38 KB 演示应用),解压后直接在 WSL 跑起本地 Postgres 就能复现 demo 的请求回路。 外汇与贵金属品种叠加这类外部存储分析,天然伴随连接中断、云端账单失控的高风险,上线前先在单机容器里压一遍并发再说。