迁移至 MQL5 Algo Forge(第 3 部分):在您自己的项目中使用外部仓库

0
309

概述

在我们向 MQL5 Algo Forge 过渡的第二部分中,我们专注于解决一个重要挑战 —— 使用多个仓库。通过结合使用 Adwizard 库项目和 Simple Candles EA 交易,我们遇到并成功解决了主要与文件包含路径和分支合并相关的问题。我们还尝试在整个工作流程中使用 MetaEditor 工具(在可能的情况下),从创建单独的修复分支到通过拉取请求合并它。但是,当 MetaEditor 功能不够用时,我们切换到 MQL5 Algo Forge Web 界面、Visual Studio Code 中的外部 Git 客户端或 Git 控制台命令。这清楚地表明,即使在个人开发中,您也可以应用 Git 最佳实践来维护项目中的秩序和清晰的变更历史。

但这只是一个方面:将存储作为一个“封闭”的生态系统,开发人员拥有所有使用的仓库。合乎逻辑的下一步,也是迁移到 Git 的主要原因之一,是能够充分利用其他社区成员的公共仓库。这就是分布式开发的真正潜力所在:能够轻松连接和更新第三方代码,为其改进做出贡献,并从现成的、经过良好测试的组件组装复杂的项目。 

在本文中,我们最后转向这个有前景但更复杂的任务:如何在 MQL5 Algo Forge 中实际连接和使用来自第三方仓库的库。不是“未来的某一天”,而是现在,无需等待 MetaEditor 仓库工具的进一步开发。 


规划路径

在本文中,我们将继续使用我们的 Simple Candles 项目仓库,它将作为实验的绝佳测试场。现有的交易策略已经包括一个自定义波动率计算,其功能类似于标准的平均真实范围(ATR)指标。然而,我们将探索如何通过纳入社区中专门的、即用型的解决方案来改进代码,而不是仅仅依赖自己的实现。

为此,我们将转向公开可用的 SmartATR 仓库,假设它包含该指标的更高级和优化版本。我们的长期实际目标是修改 EA,使其可以在继续使用内部计算或切换到外部 SmartATR 库算法之间进行选择。然而,在本文中,我们不会专注于构建一个功能齐全的 EA,而是研究使用外部仓库的关键方面。

为了实现这一目标,我们需要做到以下几点。将 SmartATR 库代码下载到我们的本地计算机,并将其设置为包含在我们的项目中。我们将介绍如何将外部仓库添加到您的工作环境中,以便以后在发布新版本时可以轻松更新。之后,我们将对 Simple Candles 项目和(事实证明是必要的)SmartATR 库代码本身进行修改。理想情况下,我们可以避免最后一步,但由于我们的案例需要它,我们将以此为例,说明如何对其他人的仓库进行更改。最后,我们将通过测试 SmartATR 库是否可以作为我们项目的一部分成功包含和编译来验证集成。

这种方法将使我们能够仔细地完成集成外部代码的整个过程。这种经历将是普遍的:一旦我们成功添加了一个库,我们将能够使用相同的方法将 MQL5 Algo Forge 中的任何其他公共仓库包含到我们的项目中。


获取外部代码

乍一看,这不应该是一个问题。任何 Git 仓库都可以使用标准控制台命令克隆到本地计算机:

git clone ...

但是,我们同意遵循一个特定的顺序:首先尝试通过 MetaEditor 界面工作,然后是 MQL5 Algo Forge web 界面,只有当这些方法失败时,才求助于 Visual Studio Code 或 Git 控制台命令等外部工具。

所以第一个问题是:我们如何在 MetaEditor 中查看其他人的仓库以选择它进行克隆?部分答案可以在帮助文档中找到,但很少有用户知道在哪里可以立即找到答案。我们自己也是后来才偶然发现这个页面。在此之前,我们注意到 MetaEditor 中的 Shared Projects 文件夹只显示了我们自己的仓库。为了进一步调查,我们在 MetaEditor 的导航器中尝试了此文件夹的上下文菜单选项。 

新建项目选项在这里并不正确,因为它只会创建一个我们拥有的新仓库。刷新也不会添加任何外部仓库。“显示所有文件”选项的行为很奇怪:运行它之后,我们的仓库中出现了尚未在本地克隆的重复名称。幸运的是,按“刷新”可以删除这些重复的名称。我们最后的希望是“显示所有公共项目”选项,但它也没有产生任何明显的变化。

不幸的是,这意味着目前我们不能仅仅依靠 MetaEditor 来克隆外部仓库。让我们来看看实现我们目标的几种替代方法。


方法一:直接克隆

让我们从一个实验开始。如果我们在 Shared Projects 中创建一个具有任意名称(例如, TestRepo )的空文件夹,它将在 MetaEditor 中可见。从那里,我们甚至可以从其上下文菜单中执行克隆命令。然而,根据日志判断,MetaEditor 随后尝试从我们的个人存储中克隆一个同名仓库( TestRepo )—— 当然,这个仓库并不存在:

这证实该方法不适用于克隆其他人的仓库。让我们尝试使用“git clone ...”控制台命令将 SmartATR 仓库直接克隆到共享项目中,看看会发生什么。

克隆后,Shared Projects 中会出现一个新的 SmartATR 文件夹,并显示在 MetaEditor 的导航器中。更重要的是,我们不仅可以查看这个仓库,还可以将其作为仓库使用:执行拉取并直接从 MetaEditor 查看更改历史记录(日志)。

因此,MetaEditor 目前缺少一个上下文菜单选项,例如“从...克隆”,它允许用户从存储中指定仓库的 URL,或者打开一个对话框来搜索和选择 MQL5 Algo Forge 中的所有公共仓库(类似于 Web 界面中的探索部分)。另一个可能的改进是不仅显示共享项目下的个人仓库,还显示用户在 Web 界面中加星标的公共仓库( 点赞的仓库 ),并能够切换其可见性。但是,我们不要过度推测 MetaEditor 最终可能会引入哪些更改。

现在,回到我们成功克隆的 SmartATR 仓库,我们可以说近期目标已经实现。该项目的源代码现在可以在本地获得,这意味着我们可以在自己的项目中使用它。然而,有一个警告。我们只能在 SmartATR 代码不需要修改的情况下直接使用,这意味着我们可以“开箱即用”,只在新版本发布时进行更新。让我们看看我们能否做到这一点。


检查功能

在 SmartATR 项目中,我们收到了一个文件,其中包含 MetaTrader 5 指标的源代码,该指标(根据描述)使用更高级的方法计算平均真实范围 (ATR)。让我们试着编译它……我们立即遇到了一个错误。 

无论错误有多严重,重要的是:如果不进行更改,我们就无法使用该项目。在这个阶段,我们必须决定是只应用本地使用的修复程序,还是共享它们并为原始仓库做出贡献。其他开发人员在尝试使用此项目的代码时也可能遇到同样的问题。因此,第二种选择更可取,因为它符合开源开发的理念。

然而,就目前而言,让我们假设我们目前不会发布修复程序。首先,我们需要解决错误;只有这样,我们才能发表有意义的东西。在这种情况下,如果我们只计划对 SmartATR 项目进行本地更改,我们可以简单地创建一个新的本地分支。 

让我们尝试这样做。原始 SmartATR 仓库仅包含一个 main 分支,因此我们将通过 MetaEditor 中项目文件夹的上下文菜单创建一个新的 develop 分支。该分支出现在 MetaEditor 中显示的分支列表中。按下推送后,日志确认操作成功。此时,我们可能希望在原始仓库中创建新的分支。但检查 MQL5 Algo Forge web 界面却发现并非如此:什么都没有改变。

接下来,让我们尝试编辑代码并从 MetaEditor 提交更改。我们在导致错误的每一行之前添加注释,指出需要修复的地方,并提交这些更改。MetaEditor 日志表明提交和推送均成功。

然而,再次通过检查 MQL5 Algo Forge web 界面中的原始仓库,我们发现没有任何变化。这至少是不寻常的。让我们在 Visual Studio Code 中检查项目,并尝试了解发生了什么。我们打开包含 SmartATR 项目克隆的文件夹并看到以下内容:

最新的提交存在,但 VS Code 建议我们发布 develop 分支。这意味着该分支尚不存在于远程仓库中,我们的提交也不存在。我们尝试发布分支但出现错误:

查看日志找出原因:

我们的用户帐户没有原始仓库的写入权限。这是有道理的。否则,由于任何人的不受控制的编辑,项目很容易陷入混乱。这意味着我们只能在本地副本中进行修改。但是,这些更改无法与远程同步,只能存在于我们的本地克隆中。这远非理想。除了协作选项外,外部仓库还扮演着非常重要的角色 —— 它们充当存储项目备份。放弃这个安全网是不明智的。

还值得注意的是,当专门在 MetaEditor 中工作时,没有迹象表明出现了问题。根据 MetaEditor 日志,一切看起来都很好:没有错误,所有更改都“成功”推送到一个不存在的仓库。希望这个问题能够在未来的版本中得到纠正。


方法二:克隆一个派生

现在让我们尝试不同的路线。在这里,我们也需要超越 MetaEditor 的当前功能 —— 这次我们还将使用 MQL5 Algo Forge web 界面。对于发现命令行 Git 操作具有挑战性的开发人员来说,这提供了一种折衷方案。在 MQL5 Algo Forge 的 web 界面中,我们可以派生所需的原始仓库。 

派生(Fork)是版本控制系统和协作开发平台(包括 MQL5 Algo Forge)中的一个基本概念。指在平台内创建原始仓库的完整、独立副本的过程。

当用户派生其他人的仓库时,平台会在该用户的帐户下创建一个精确的副本。此副本在派生时继承了源项目的所有更改历史记录、分支和文件,但从那一刻起,它就成为一个自主仓库。新主人可以自由修改它而不会影响原有的东西。

因此,派生使任何用户都可以在现有项目的基础上进行构建并按照自己的路径进行开发,从而有效地为代码创建一个新的进化分支。这一概念使得在开源生态系统中创建衍生项目和替代实现成为可能。

派生也是对用户没有直接写权限的项目做出贡献的主要方式。标准工作流程如下:创建一个派生,在其中实现并测试所需的更改,然后通过拉取请求通知原始仓库的维护者有关提议的改进,我们已经在第 2 部分中介绍过。这是去中心化协作开发模式的基础。

尽管分支彼此独立,但它们仍与源仓库保持着技术联系。这样就可以跟踪原始版本中的更改并将其同步到您的派生 中,将上游项目中的新提交合并到您自己的提交中。

区分派生和简单克隆非常重要。克隆是指在特定计算机上创建存储库的本地副本,而派生是在平台本身上的完整副本,在另一个用户的所有权下建立新的远程仓库。

因此,一旦我们派生一个仓库,它就成为我们自己的仓库。它还会在 MetaEditor 中的 Shared Projects 列表中显示,并可通过 MetaEditor 直接克隆。


使用派生测试工作

感谢 Fernando Carreiro 的鼎力相助,我们得以在实践中测试这一机制。我们派生了他的存储库 FMIC ,同时将原始存储库添加到 MQL5 Algo Forge web 界面中的“关注”和“点赞”列表中。

正如预期的那样,该分支出现在 MetaEditor 中 Shared Projects 下显示的仓库列表中:

这使我们能够成功地将新创建的 FMIC 仓库的派生克隆到本地计算机。

接下来,我们要求 Fernando 提交一些更改,以便我们可以测试更新如何反映在我们的派生中。他添加了一个描述 Heikin Ashi 发布的示例 README.md 文件并将其提交到仓库。

随后,在 web 界面上我们确实看到了有关新变化的通知:

然而,这些通知尚未影响我们存储在 MQL5 Algo Forge 上的派生或我们计算机上的本地克隆。让我们尝试将 Fernando 的更改拉入我们的仓库。首先,我们检查本地克隆中确实缺少最新的更改:

我们本地历史记录中的最后一次提交日期为 2025 年 8 月 27 日,而 Fernando 的更改则更晚进行。

现在,如果我们在 web 界面中访问我们的派生,我们会看到一条消息,表明我们的 main 分支比原始存储库落后了三个提交:

我们还看到一个同步按钮,它应该将我们的 main 文件夹与上游分支同步。然后,我们检查提交历史记录,发现有三个新的提交,日期为 2025 年 9 月 5 日,之前没有:

换句话说,原始仓库中的所有提交都首先成功传播到我们在 MQL5 Algo Forge 上的派生中,然后传播到该派生的本地克隆中。

对于那些希望更详细地探索此机制的人,我们建议查阅以下 GitHub 文档部分: 

虽然该文档不是专门为 MQL5 Algo Forge 编写的,但大部分 web 界面的行为都类似,并且控制台 Git 命令无论托管平台如何都普遍适用。当然,前提是该平台基于 Git。

例如,按照 上游(upstream)配置指南,我们可以设置同步,以便每个拉取/推送操作也会根据原始仓库更新我们的派生克隆:

但是,当仅通过 MetaEditor 和 MQL5 Algo Forge web 界面工作时,这个额外的配置步骤并不是必需的。


派生 SmartATR

现在让我们回到我们最初计划使用的仓库。我们将重复相同的步骤 - 通过 MQL5 Algo Forge web 界面创建分支并在本地克隆 - 用于 SmartATR 仓库。

我们首先在探索部分中搜索原始仓库,输入其名称:

由于仓库中已经有其他用户创建的多个分支,因此搜索结果也会显示这些分支。为了派生真正的原始版本,我们进一步向下滚动结果并打开 steverosenstock/SmartATR 的页面。

我们点击派生按钮:

点击后,我们将被重定向到派生创建设置页面。在这里,我们可以重命名派生的仓库(因为它将出现在我们的仓库列表中),指定应包含原始仓库的哪些分支,并根据需要编辑存储库描述:

默认情况下,派生是作为原始存储库的精确副本创建的。这对我们来说非常完美,所以我们只需单击“派生仓库”即可。

成功创建了派生:

接下来,我们将这个仓库克隆到我们的本地计算机。在此之前,我们从本地计算机中删除之前克隆的原始 SmartATR 文件夹。如果 MetaEditor 已经打开,我们需要通过从 Shared Projects 上下文菜单中选择刷新来刷新文件夹列表。之后,出现SmartATR文件夹,从其上下文菜单中选择“Git 克隆”: 

SmartATR 项目克隆成功:

我们现在准备开始做出修改了。


做出修改

由于我们的目标是引入修复程序来解决或至少消除特定错误,因此我们首先创建一个新分支,其名称清楚地反映了这一目的;例如,fixes/news-impact:

然后,我们通过选择“Git 分支 → fixes-news-impact”在项目的上下文菜单中切换到该分支。

请注意,尽管我们最初在分支名称中包含了斜杠(“/”),但实际上创建分支时该字符会自动替换为连字符(“-”)。这是 MetaEditor 施加的限制,它只允许分支名称中使用拉丁字母和连字符。从技术上讲,Git 本身允许使用斜杠,并且通过 web 界面我们可以自由创建包含斜杠的分支。 

让我们测试一下这个限制的重要性。我们将直接在 MQL5 Algo Forge web 界面中创建另一个分支,这次在其名称中明确包含斜杠:fixes/cast-warning。从分支页面,我们选择新分支,以 main 分支为基础:

分支创建成功:

然而,当尝试在 MetaEditor 中运行拉取时,我们收到一条错误消息:

即便如此,名称中带有斜杠的新分支确实出现在 MetaEditor 内的分支列表中,并且切换到该分支不会出现其他问题:

注意到这个特性后,我们切换回 fixes-news-impact 分支并引入临时修复程序以消除编译错误的原因:

一旦指标编译无误,我们就通过上下文菜单选项“Git 提交”提交更改: 

在提交对话框中,我们检查修改的文件列表。在这种情况下检查很简单,因为我们只更改了一个文件。强烈建议添加描述性注释来解释修复的性质。确认一切正确后,我们按 OK。

我们的更改现已提交并推送到 MQL5 Algo Forge 中的 SmartATR 仓库的分支。在此阶段,指标的更正版本已经可以在本地使用,并且安全副本也存储在仓库中。或者,我们可以通过在仓库的 web 界面中按“新拉取请求”向原始项目作者提交拉取请求:

然而,现在还为时过早,因为我们的修改只是禁用部分功能而不是改进代码。目前,我们还没有创建拉取请求。

SmartATR 指标已准备好集成到我们的 Simple Candles 项目中。


整合指标

按照最佳实践,我们基于 develop 分支在 Simple Candles 项目仓库中创建一个新分支 - article-19436-forge3 。为了改变我们的方法,我们使用 MQL5 Algo Forge web 界面创建此分支。

为了使分支在本地出现,我们在 MetaEditor 中运行“Git 拉取”,然后切换到新分支 article-19436-forge3

由于我们的目的是在交易策略中应用该指标,因此我们将其直接添加到 SimpleCandlesStrategy.mqh 中的策略类实现中。具体来说,我们引入一个类字段来存储指标句柄:

//+------------------------------------------------------------------+ //| Trading strategy using unidirectional candlesticks       | //+------------------------------------------------------------------+ class CSimpleCandlesStrategy : public CVirtualStrategy { protected:    //...    int               m_iATRHandle;        // SmartATR indicator handle    //... }; 

接下来,我们在类构造函数中调用 iCustom() ,传递所需的交易品种、时间框架、指标文件路径及其参数:

//+------------------------------------------------------------------+ //| Constructor                                                      | //+------------------------------------------------------------------+ CSimpleCandlesStrategy::CSimpleCandlesStrategy(string p_params) { // Read the parameters from the initialization string    // ...    if(IsValid()) {       // Load the SmartATR indicator       m_iATRHandle = iCustom(                         m_symbol, m_timeframe,                         "Shared Projects/SmartATR/SmartATR.ex5",                         // Indicator parameters                         m_periodATR,   // Initial ATR period (used for first calculation, adaptively changes)                         false,         // Enable adaptive period (dynamic lookback)                         7,             // Minimum ATR period (adaptive mode)                         28,            // Maximum ATR period (adaptive mode)                         false,         // Weight True Range by volume                         false,         // Weight True Range by economic news events (MT5 Calendar)                         2.0,           // Multiplier: alert if ATR exceeds this factor of average                         false          // Enable pop-up & sound alerts on high volatility                      );       // ...    } } 

请注意为指标指定的路径。它以 Shared Projects 开始,然后是项目文件夹名称 SmartATR ,接着是指标文件名 SmartATR.ex5 。包含 .ex5 扩展名是可选的,但保留它有助于避免混淆。

Shared Projects 文件夹中工作时,应考虑一个重要的细微差别。这既指您自己的项目,也指派生的项目。所有已编译的可执行文件都不会直接放置在仓库文件夹中。这是因为 Shared Projects 文件夹位于终端数据根文件夹中:MQL5/Shared Projects。一方面,这是好的,因为版本控制系统不会尝试建议索引可执行文件。另一方面,一开始可能会有点令人困惑:我们在哪里可以找到已编译的 EA 交易和指标文件?

它们实际上是在各自的标准文件夹中创建的,例如 EA 的 MQL5/Experts 或指标的 MQL5/Indicators 。在其中,会自动创建一个 Shared Projects 子目录。因此,编译的文件就直接在这些子文件夹中创建。这意味着从 MQL5/Shared Projects/SmartATR.mq5 编译文件将在 MQL5/Indicators/Shared Projects/SmartATR/SmartATR.ex5 生成可执行文件。

因此, iCustom() 调用必须引用相对于 MQL5/Indicators 的指标路径。

最后,我们编译 EA 文件 SimpleCandles.mq5 并在策略测试器中运行它。日志显示以下内容:

因此,SmartATR 指标已成功加载、初始化并可供使用。目前,我们仅展示其集成。我们稍后可能会在策略逻辑中添加实际使用。我们提交这些更改并将其推送到 MQL5 Algo Forge 仓库。


结论

本文演示了如何采用 MQL5 Algo Forge 为开发人员提供更加灵活的工作流程。以前,我们只研究了自包含仓库,但在这里我们已成功将来自第三方仓库的外部库集成到我们的项目中。

关键时刻是基于派生的正确工作流程 —— 创建外部仓库的个人副本,允许完全修改,同时与上游项目保持同步。SmartATR 与 Simple Candles 的成功集成支持这种方法 —— 从定位和派生仓库,到在实时交易策略中修改和应用其代码。

重要的是,这个过程完全是通过当前的 MetaEditor 功能实现的,无需等待未来的更新。通过使用 MQL5 Algo Forge web 界面以及(如有必要)标准 Git 控制台命令进行补充,可以轻松克服 MetaEditor 的局限性(例如缺乏对第三方仓库的直接访问和分支命名受限)。简而言之,该系统已经可以实际使用,其余的界面缺陷只是不便之处,而不是阻碍因素。

然而,我们不要就此止步。我们将继续使用仓库来分离项目并分享我们在此过程中获得的经验。

感谢您的关注!期待很快与您见面!

下一篇文章 >>