使用云存储服务来进行终端之间的数据交换(基础篇)
📘

使用云存储服务来进行终端之间的数据交换(基础篇)

第 1/3 篇

用云存储打通多终端数据

MetaTrader 5 内置的 MQL5 云存储(基于 Mail 与 Files 的跨终端同步机制)能让同一账户下的不同终端实例交换数据,不必自己搭服务器。 实际场景中,2017 年 10 月 3 日 Dmitriy Gizlyk 发布的示例帖获得 3121 次查看与 10 条讨论,说明多终端协同的需求在实盘圈并不小众。 核心思路是:一台终端把状态写进公共存储区,另一台终端轮询读取,从而把信号或参数在 VPS 与本地 MT5 之间搬运。外汇与贵金属杠杆高,多终端同步若延迟可能造成重复下单,务必先在模拟盘验证。

◍ 用云存储做终端间数据中转

把云存储当成交互通道,是 MT5 多终端协同里一种被低估的做法。比起终端直连,走云服务的核心好处是提供方可以匿名——用户只碰到云服务器,提供者的机器不必常驻公网,只在推送数据时联网一次,被扫端口和种马的概率都降下来。 第二个实打实的优势是横向扩展:云里能挂任意数量的“虚拟提供者”,用户量涨了,提供者本地算力不用跟着升。以 Google 免费 15GB 空间为例,对行情标记、信号中转这类小体量同步任务已经够用,零成本起步。 外汇与贵金属交易本身高杠杆、高风险,这类架构只解决传输通道问题,不替代任何风控逻辑;真要落地,先在 MT5 用 demo 账户跑通一次再谈实盘。

「OAuth 2.0 怎么管住第三方读取权限」

MT5 想碰 Google Drive 上的信号或日志备份,走的是 OAuth 2.0,不是把账号密码塞进 EA。它让第三方在不知道你密码的前提下,拿到有限访问权。 完整链路是 4 步:先由 Google 给应用发 client_id 和 client_secret;应用用系统浏览器拉起授权页,用户在登录后做“user consent”确认;同意后服务器回一个授权码,应用拿它换 access token;之后每次请求把 token 放进 HTTP 头里。 access token 的权限边界由 scope 定死。比如许可了 Google Drive 的 token,就调不到 Google Contacts,但对 Drive 内的允许操作可反复发 token 调用。 token 有寿命。过期后若还要访问,应用得靠 refresh token 去换新的 access token,否则接口直接返错。外汇与贵金属自动化涉及云端存取时,这套过期机制是高风险的隐性断点,需自行兜底重授权。

开通 Drive API 与拿到客户端密钥

要用 MQL5 直接读写 Google Drive,第一步不是在 MT5 里写代码,而是先在 Google 开发人员控制台里把项目和应用身份建好。登录账户后按 Ctrl+O 打开项目面板,新建一个项目并命名,随后在 API 库里搜 Drive API 点 Enable 激活。 激活后会提示创建凭据,这里别用向导,直接选 client ID;系统会要求先配置同意屏幕,只需填“向用户显示的产品名称”,其余默认。应用类型选 Other,生成 client ID 与 client secret。 这两个字符串可以手抄,但更稳的做法是下载对应的 json 文件到本地磁盘,后面服务端调用就靠它做 OAuth 身份校验。完成这一步,服务端的准备就结束了,可以进 MT5 写程序了。 外汇与贵金属自动化涉及账户授权与云端交互,任何接口失配都可能让策略停摆,建议先在模拟环境跑通再上实盘。

◍ 用 C# 桥梁打通 MT 与 Google Drive

把 MT4/MT5 的 EA 或指标和云存储连起来,最省事的路子是另写个独立程序当中间层:它收终端请求、跑 Google Drive 的读写、再把结果丢回 MT。这样终端不用直接扛外部服务的资源消耗,桥梁本身用 C# 写、挂 Google.Apis.Drive.v3 库,能同时服务 MT4 与 MT5,不绑死平台。 Google Drive 的文件系统和本地不一样:文件名和扩展名只是显示用,存进去后每个文件拿唯一 ID,同名同扩展能存无数份。所以读文件前必须先拉全量列表、按名比对拿 ID。示例类里写死了扩展名 .gdb、应用名 "Google Drive Bridge",认证密钥对象 credential 初始为 null,登录失败即重置。 [CODE] class GoogleDriveClass { static string[] Scopes = { DriveService.Scope.DriveFile }; //用于操作类的数组 static string ApplicationName = "Google Drive Bridge"; //应用程序名称 public static UserCredential credential = null; //认证密钥 public static string extension = ".gdb"; //所保存文件的扩展名 } public bool Authorize() { using (System.IO.FileStream stream = new System.IO.FileStream("client-secret.json", System.IO.FileMode.Open, System.IO.FileAccess.Read)) { try { 桥梁和终端用命名管道通信,MQL5 自带 CFilePipe 类可用。管道里单线程传数据,作者用 ; 分隔字段,一条串把命令、文件名、内容全带上。支持三个命令:Close 断连、Read 读云文件、Write 写云文件。 写云不是直接覆盖,而是 FileCreate 建新文件拿 ID,再 GetFileList 比对删旧同名文件(FileUpdate 逻辑),避免多终端并发时读到残数据。读云则 GetFileID 先捞 ID,再 FileRead 取内容,失败返空串。多线程异步处理多终端连接,异常就重登 Google 并重启线程。 落地动作:VisualStudio 建 Windows Form 项目,NuGet 装 Google.Apis.Drive.v3,把 client-secret.json 放运行目录,编译后从 Form1 启 PipesCreate。外汇/贵金属自动化跨机同步有断连与云权限风险,实盘前先在模拟环境跑通管道读写。

MQL5 / C++
class GoogleDriveClass
    {
        class="kw">static class="type">class="kw">string[] Scopes = { DriveService.Scope.DriveFile }; class=class="str">"cmt">//用于操作类的数组
        class="kw">static class="type">class="kw">string ApplicationName = "Google Drive Bridge"; class=class="str">"cmt">//应用程序名称
        class="kw">public class="kw">static UserCredential credential = null; class=class="str">"cmt">//认证密钥
        class="kw">public class="kw">static class="type">class="kw">string extension = ".gdb"; class=class="str">"cmt">//所保存文件的扩展名
    }
        class="kw">public class="type">bool Authorize()
        {
            using (System.IO.FileStream stream =
                new System.IO.FileStream("client-secret.json", System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                try
                {

「把网盘文件清单拉进 C# 桥接层」

在 MT5 外部用 C# 做桥接时,授权失败不应让整个 EA 崩掉。上面这段把 Google 凭证路径拼到当前工作目录下的 drive-bridge.json,用 FileDataStore 缓存令牌;若 AuthorizeAsync 抛异常,catch 里直接把 credential 置空并返回 false,调用方据此跳过云端逻辑即可。 取文件列表时先判断 credential 是否为空,空就重跑一次授权,仍为空则直接 return null,避免空引用。DriveService 用 using 包裹,HttpClientInitializer 接凭证、ApplicationName 接应用名,离开作用域自动释放连接。 真正发请求只设两个参数:PageSize = 1000 控制单次最多拉 1000 个文件,Fields 限定只回传 id、name、size 三个字段。外汇与贵金属交易涉及高杠杆,这类桥接只负责文件同步,不参与下单,实盘前请在模拟环境验证令牌刷新是否稳定。

MQL5 / C++
class="type">class="kw">string credPath = System.Environment.CurrentDirectory.ToString();
credPath = System.IO.Path.Combine(credPath, "drive-bridge.json");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
    GoogleClientSecrets.Load(stream).Secrets,
    GoogleDriveClass.Scopes,
    "example.bridge@gmail.com",
    CancellationToken.None,
    new FileDataStore(credPath, true)).Result;
            }
            class="kw">catch (Exception)
            {
                credential = null;
            }
        }
        class="kw">return (credential != null);
    }
using File = Google.Apis.Drive.v3.Data.File;
class="kw">public IList<File> GetFileList()
    {
        IList<File> result = null;
        if (credential == null)
            this.Authorize();
        if (credential == null)
        {
            class="kw">return result;
        }
        class=class="str">"cmt">// 创建 Drive API 服务.
        using (Google.Apis.Drive.v3.DriveService service = new Google.Apis.Drive.v3.DriveService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = ApplicationName,
        }))
        {
            try
            {
                class=class="str">"cmt">// 定义请求的参数.
                FilesResource.ListRequest listRequest = service.Files.List();
                listRequest.PageSize = class="num">1000;
                listRequest.Fields = "nextPageToken, files(id, name, size)";
                class=class="str">"cmt">// 列出文件.
                result = listRequest.Execute().Files;
            }
            class="kw">catch (Exception)
            {

常见问题

可以用云存储做终端间数据中转,把配置文件传到网盘,另一台终端启动时自动拉取覆盖本地,避免手动拷贝漏版本。
用 OAuth 2.0 授权时只勾选只读 scope,不授予写入或删除权限,第三方就只能拉清单和读文件,动不了你的盘。
小布可以接管云存储桥梁,定时把各终端生成的诊断文件收进同一网盘目录,你打开就能看全部机器的汇总,不用自己倒腾。
密钥别塞进代码仓库或明文配置,放本地仅当前用户可读的路径,桥梁程序启动时载入,外发版本前删掉。
在 C# 里调用网盘 API 的 files.list 接口拿回条目,绑到本地列表控件,点选就能下载对应文件到终端目录。