English Русский Español Deutsch 日本語 Français
preview
迁移至 MQL5 Algo Forge(第 1 部分):创建主存储库

迁移至 MQL5 Algo Forge(第 1 部分):创建主存储库

MetaTrader 5示例 |
27 7
Yuriy Bykov
Yuriy Bykov

目录



概述

在处理大中型项目时,不可避免地需要跟踪代码中的更改,按含义对其进行分组,并能够回滚到以前的版本。通常,这是由 Git 或 Subversion(SVN)等版本控制系统处理的。

大多数开发环境都提供内置工具,用于处理某些版本控制系统的存储库。MetaEditor 也不例外,它支持基于 SVN 的自己的存储库 MQL Storage。正如文档所述:

MQL5 Storage 是 MQL4/MQL5 源代码的个人在线存储库。它集成到 MetaEditor 中: 您可以直接在编辑器中保存和接收存储中的数据。

存储提供版本控制系统。意即您始终可以了解何时以及如何对文件进行了修改,并可取消所有更改并返回到以前的版本。

借助 MQL5 Storage,您的源代码始终会保持安全。数据存储在受保护的服务器上,并且只有您有权访问它。如果您的硬盘发生故障,所有以前保存的代码都可以很容易地恢复。

通过存储,您可以轻松共享和同步图表模板和配置文件、用于测试 MQL5 程序的参数集以及不同平台之间的交易工具集。

MQL5 Storage 允许团队使用共享项目远程开发 MQL5 应用程序。

然而,Git 版本控制系统已经变得更加流行了 —— 在我们看来,这是理所当然的。也许出于这个原因,早在 2024 年中期,MetaQuotes 就透露了其计划,计划采用 Git 作为 MetaEditor 的内置版本控制系统,同时推出 MQL5 Algo Forge ,这是 GitHub 的内部替代品。

在撰写本文时,新的存储库已经可以使用,但 MetaEditor 集成尚未完成。因此,MetaEditor 仍然是主要的开发环境,而开发人员仍然局限于基于 SVN 的 MQL Storage。

在我们的各种项目工作中,我们积极使用现有的版本控制系统。然而,在撰写 “开发多币种 EA 交易” 系列文章时,对分支中的并行代码开发及其后续合并缺乏支持变得尤为明显。虽然 SVN 本身支持分支,但 MetaEditor 不提供分支接口。虽然可以使用外部 SVN 客户端 ,但这需要重构熟悉的工作流程。

因此,MQL5 Algo Forge 的发布受到了热烈欢迎。我们希望 MetaEditor 最终能够支持分支。但七个月后,这些期望仍未实现。因此,让我们探讨如何使用当前可用的工具改进开发过程。

为了更好地理解,至少需要版本控制系统的基本知识。如果有必要,我们建议查看 MQL5 网站或其他地方的资料,例如开始使用 Git


当前可用的工具

在 MetaQuotes 发布有关推出 MQL5 Algo Forge 的消息后不久,在其中创建了一个名为 mql5 的存储库,其中包含我们当前 MQL 存储中的所有文件。但是,它们都是在用户 super.admin 下的单个提交中添加的,这意味着没有保留提交历史记录。这是意料之中的。在不同的版本控制系统之间迁移完整的历史几乎是不可能的。

后来,MetaEditor 中的一些界面元素开始显示新的存储库名称。例如,版本历史对话框的标题更改为 “MQL5 Algo Forge”:

但本质并没有改变:所有修改仍然进入 MQL Storage,而不是 Algo Forge。因此,七个月前复制到 Algo Forge 的文件自那以后就没有更新过。

然而,改变的是,我们现在可以使用多个存储库。以前,只有一个存储库。我们必须在 MQL5 数据文件夹中的单独文件夹中创建不同的项目,该文件夹始终是存储库根目录。这意味着,当我们为新项目创建一个新的终端实例并激活存储时,我们会从存储中下载所有项目,甚至是不相关的项目。随着它们的数量不断增加,这变得越来越不方便。

简单地从数据文件夹中删除不相关的项目是不可行的,因为每次提交都需要手动排除那些被删除的项目以将其发送到存储中。

有了一个合适的 Git 存储库,我们现在有几个选项来构建存储和管理不同的项目:

  • 每个项目都存在于自己的存储库中。
  • 每个项目都存在于单个存储库的一个单独分支中。
  • 混合模型:一些项目位于单独的存储库中,而另一些项目作为分支共存于一个存储库中。

每种方法都有优点和缺点。例如,如果多个项目共享同一个库,将库保存在单独的存储库中会很不方便。相反,最好在专用分支中维护它,根据需要将更改合并到项目分支中。另一方面,对于自包含的项目,最好使用单独的存储库,因为这可以避免存储来自其他项目的无关代码。


开始迁移

在做出改变时,明智的做法是保留已经存在的东西。使用自动创建的 mql5 存储库可能不是最好的主意,因为 MetaQuotes 可能会在 super.admin 下执行其他操作。因此,首先,我们将创建一个新的存储库来存储我们当前的所有项目。为此,我们将采用将不同项目存储在不同分支中的模型。为了实现这种分离,我们定义了以下约定:

  • main(主)分支将保持为空,或者只包含所有项目使用的最小公共代码集。
  • 单独的 archive(归档)分支将存储迁移时可用的所有代码。从这里,我们可以将代码复制到单个项目分支中。
  • 其他分支机构将与单个项目相关,并将相应地命名。
  • 一个项目可能有多个活动分支,具体取决于所选的分支策略(例如,“成功的 Git 分支模型” 中描述的方法)。

假设我们有一个 MetaTrader5 文件夹,其中安装了终端并连接了 MQL Storage。也就是说,终端的 MetaTrader5/MQL5 数据文件夹除了包含标准文件外,还包含我们项目的代码。


创建一个名为 MetaTrader5.forge 的新文件夹并将两个可执行文件复制到那里:

以便携模式从此文件夹启动 MetaTrade r终端。在我们的系统中,它在双击后以这种模式启动。否则,在从命令行运行 /portable 键或创建快捷方式时,可能需要显式指定该键,并将其添加到应用程序启动命令中。目前无需开设交易模拟账户或登录 MQL5.community。

在新文件夹中创建初始文件夹结构,其中包括一个空的 MQL5 数据文件夹。它还不包含我们的文件。

按 F4 从终端启动 MetaEditor。

如果右键单击文件夹名称,上下文菜单将提供激活 MQL5 Algo Forge 存储的选项(尽管实际上,这将激活 MQL Storage)。请不要激活它,因为我们打算迁移到新的存储库类型。

然后关闭 MetaTrader 和 MetaEditor,因为我们暂时不需要它们,需要直接在终端文件夹中执行一些操作。


存储库管理工具

下一步是选择一个工具来处理未来的存储库。稍后,这个角色可能会被 MetaEditor 本身接管,但现在我们必须使用其他东西。您可以使用任何工具来处理 Git 存储库,例如,Visual Studio Code (VSCode) 与 Git 结合使用。可以从 gitforwindows.org 下载 Windows 版本的 Git。

因此,请安装 Git 和 VSCode(或确保它们已经安装)。在 VSCode 中,安装 MQL Tools 扩展以处理 MQL5 文件:

安装扩展后,在设置中的 “Metaeditor5 Dir” 参数中指定 MetaEditor 可执行文件的路径。由于不需要使用位于终端实例工作文件夹之外的 MQL5 源文件,您可以按照建议在 VSCode 中提供与当前打开的文件夹相关的路径:

在扩展设置中,我们强烈建议启用“便携式 MT5”选项。

为了语法突出显示,您需要安装 Visual Studio Code 的 C/C++ 扩展。

不幸的是,虽然 MQL5 与 C++ 非常相似,但它包含标准 C++ 中未使用的某些语言结构。因此,该扩展可能偶尔会显示与 MQL5 上下文无关的语法错误。

现在,在 VSCode 中打开 MetaTrader5.forge/MQL5 数据文件夹:

尝试打开任意 EA 交易文件:

语法高亮显示工作正常,编辑器窗口的右上角现在显示了通过 MetaEditor 进行 MQL5 语法检查和编译的其他按钮。但是,所有 #include 指令都会生成错误消息。发生这种情况是因为 MQL5 不是 C++,并且标准库包含文件的位置不同。要解决此问题,请按照建议的解决方案:在 VSCode 的 C/C++ 扩展设置中,添加 MetaTrader5.forge/MQL5/Include 的 路径。

一旦完成,错误消息就会消失,并且 EA 交易会成功编译:

此时,我们将暂时把 VSCode 放在一边,因为主角现在登场了:MQL5 Algo Forge。


创建主存储库

前往 https://forge.mql5.io/ 并注册新账户或使用您现有的 MQL5.community 凭证登录:

从右上角的菜单中选择“新建存储库”。

为存储库选择一个名称(例如, mql5-main )。在本地克隆存储库时,您可以为根文件夹指定任何名称,因此存储库名称本身并不重要。初始化时,添加 .gitignoreREADME.md 文件。

存储库现已创建好,第一次提交是自动进行的:

为了接下来的步骤,请复制存储库 URL。在我们的例子中,它是:https://forge.mql5.io/antekov/mql5-main.git。我们现在可以从浏览器返回到 VSCode、MetaEditor 和 MetaTrader 5 终端。


克隆存储库

为了在本地克隆存储库,我们需要在终端目录中有一个空的 MQL5 文件夹。目前,它已经装满了文件,因此我们必须按以下步骤操作:

  • 关闭 VSCode、MetaEditor 和 MetaTrader 5。
  • 重命名现有的 MQL5 文件夹(例如,重命名为 MQL6 )。

现在 MetaTrader5.forge 目录中没有 MQL5 文件夹:

在 VSCode 中打开此文件夹,然后按 [Ctrl + `] 启动 VSCode 终端。

复制存储库 URL并执行克隆命令,在 URL 后指定本地存储库的根文件夹名称(它应该与 MQL5 匹配):

git clone https://forge.mql5.io/antekov/mql5-main.git MQL5

如果存储库是私有的,并且这是您第一次克隆它,系统将提示您输入凭据。结果,终端目录中将出现一个新的 MQL5 子文件夹,其中包含 .gitignoreREADME.md

现在将所有文件和文件夹从 MetaTrader5.forge/MQL6 移动到 MetaTrader5.forge/MQL5 ,然后删除旧的 MetaTrader5.forge/MQL6 文件夹。

在 VSCode 中打开 MetaTrader5.forge/MQL5 文件夹。在左侧的“源代码控制”面板上,您将看到存储库文件夹中有大量新文件(在我们的例子中为 581 个):

但这些文件中的大多数不应该位于我们的存储库中,因为它们属于标准的 MetaTrader 5 安装。在新版本中,这些标准库和示例项目的内容和结构可能会发生变化。我们不能修改它们,否则在下次更新 MetaTrader 终端时或切换到新的工作文件夹时可能会发生冲突。因此,没有理由将它们包含在我们的存储库中。


配置忽略的文件

这正是 .gitignore 文件发挥作用的地方。在这里,我们可以指定 Git 应该忽略哪些文件和目录。这样,我们只会看到自己文件中的修改,而不是数百个无关的更改。由于我们尚未将任何自定义文件添加到存储库中,因此应忽略当前列出的所有文件。

因此,打开 .gitignore 并将其默认内容替换为如下内容:

# ---> MQL5
# VSCode Preferences
.vscode/*

# Executables
*.ex5

# MQL5 Standard Files
/Experts/Advisors/
/Experts/Examples/
/Experts/Free Robots/
/Experts/Market/
/Files/
/Images/
/Include/Arrays/
/Include/Canvas/
/Include/ChartObjects/
/Include/Charts/
/Include/Controls/
/Include/Expert/
/Include/Files/
/Include/Generic/
/Include/Graphics/
/Include/Indicators/
/Include/Math/
/Include/OpenCL/
/Include/Strings/
/Include/Tools/
/Include/Trade/
/Include/WinAPI/
/Include/MovingAverages.mqh
/Include/Object.mqh
/Include/StdLibErr.mqh
/Include/VirtualKeys.mqh
/Indicators/Examples/
/Indicators/Free Indicators/
/Libraries/
/Logs/
/Profiles/
/Scripts/Examples/
/Scripts/UnitTests/
/Services/
/Shared Projects/
/experts.dat
/mql5.*

这样,您可以指示版本控制系统排除 VSCode 设置文件、已编译的 EA 交易和指标文件(存储库通常仅存储源代码)以及位于列出文件夹中的标准 MetaTrader 5 文件。只会跟踪您自己的源代码。


提交更改

保存 .gitignore 后,VSCode 仅显示一个修改的文件 - .gitignore 本身。MQL5 文件夹中的所有其他文件(现在是我们的 mql5-main 存储库的根文件夹)虽然物理上存在,但现在都被忽略了:

通过添加以下消息在本地存储库中执行提交:“将标准文件添加到 .gitignore”,然后点击“提交”。

此时,更改仅存在于本地存储库中。要将其推送到远程存储库,请运行“推送”命令。这可以通过不同的方式完成,例如,通过单击 VSCode 中的“同步更改”,从 CHANGES 旁边的溢出菜单 (...) 中选择“推送”,或手动运行 “git push” 命令。

但是,在向上游推送最后一次提交之前,请检查 GRAPH 中的提交历史记录。您应该看到两次提交:“初始提交”和“将标准文件添加到 .gitignore”。分支名称以彩色显示在右侧,提交旁边。第一个提交标记为 origin/main ,第二个提交标记为 main 。实际上,它们是同一个 main 分支。这里, origin 是远程仓库的别名,因此 origin/ 前缀表示本次提交是上游仓库 main 分支中的最后一次提交。第二次提交没有此前缀,因此它存在,并且是本地存储库中的最后一次提交。

按 “同步更改”:

现在,更改已成功推送到远程存储库,并且紫色的 “origin” 标签已移动到第二次提交。您可以通过查看 Web 界面中的存储库来确认这一点:

在这个阶段,我们为我们的工作准备了一个几乎空的存储库。它的唯一分支名为 main ,包含我们添加的两个文件。版本控制系统会忽略此终端实例的数据文件夹中存在的任何其他文件。


创建归档分支

如前所述,第一步是将所有现有文件放入一个分支中,以便它们受到版本控制,并可以推送到远程存储库。这确保了我们以后可以在需要时在任何其他计算机上检索它们。

与版本控制系统中的任何其他操作一样,可以以不同的方式创建分支。从 VSCode 打开存储库菜单 (...)。然后选择“签出至...”

接下来,在操作列表中,选择“创建新分支...”。

在 web 界面中,从远程存储库转到分支选项卡,然后单击新的分支创建按钮(下面用绿色矩形突出显示):

这两种方法有一个区别。第一个在本地计算机上创建一个新分支,在您推送更改之前,远程存储库对该分支一无所知。第二种方法在远程存储库中创建一个新分支,因此在您使用拉取命令获取更改之前,本地存储库不会知道此分支的存在。无论哪种方式,您只需通过运行拉取或推送命令进行同步。

第三种方式是使用命令行。要在本地存储库中创建名为 “archive” 的新分支,您可以从存储库文件夹运行以下命令:

git checkout -b archive

如果您在 VSCode 集成终端中执行此操作,您将看到以下内容:

该终端通知您存储库已切换到新创建的 “archive” 分支。在提交列表中,分支名称 main 更改为 archive 。变更日志将提示您将新分支推送到远程存储库。但是,我们将首先将文件添加到此分支中。

我们有一个带有 MetaTrader 终端的初始文件夹,其中包含装有我们所有文件的 MQL5 文件夹。该存储库是在另一个终端文件夹中创建的。现在,将旧的原始 MetaTrader5/MQL5 文件夹中的所有文件复制到新的存储库文件夹:

版本控制系统立即检测到存储库文件夹中的新文件,并为它们提供了某些操作。您需要将所有新文件添加到索引中(以启用版本控制)。这可以通过 VSCode 界面在变更列表标题中选择 “+”(暂存所有变更)来完成,也可以通过运行命令

git add。

现在,更改列表中的每个文件都标记为 A,这意味着它已被索引,而不是 U。接下来,将更改提交并推送到远程存储库:

我们可以看到,main 分支中的最后一次提交现在是第二次提交,而 archive 分支中已经进行了第三次提交。让我们验证新分支是否已推送到远程存储库:

最新提交在远程存储库中可见,并属于新的 archive 分支。单击它可以查看此提交中包含的具体更改。

至此,所有文件都已成功添加到 archive 分支。现在,让我们切换回本地存储库中的 main 分支。


准备创建项目分支

要切换到主分支,请在控制台中执行以下命令

git checkout main

本地存储库应恢复到复制所有文件之前的状态。然而,切换后检查 MQL5 文件夹的内容,您可能会注意到我们的许多 EA 交易文件夹仍然保留。

这些文件夹仍然包含已编译的 .ex5 文件。发生这种情况的原因是,在将它们排除在版本控制之外后,Git 在从存档分支切换回主分支时不会删除这些文件。只有暂存并提交到存储库的源文件已从文件夹中删除。

这不是很方便,所以我们需要删除编译后的文件和删除后留下的任何空目录。手动执行此操作将非常耗时,特别是因为我们将来可能需要重复此操作。因此,编写一个简单的脚本来自动处理此任务更为实用。

在脚本开发过程中,很明显,仅删除文件不足以在切换分支后将根文件夹恢复到原始状态。删除 .ex5 文件后,还需要删除已变空的目录。某些文件夹可能故意留空,不应删除。这些将被添加到排除列表中。此列表将包括之前在 .gitignore 中列出的所有文件夹以及包含版本控制元数据的 .git 文件夹。 

以下是此类脚本的一个示例:

import os


def delete_ex5_files_and_empty_dirs(path, excluded=['.git', '.vscode']):
    # Exceptions
    excluded = {os.path.join(path, dir) for dir in excluded}

    # Check all folders and files in the directory tree
    for root, dirs, files in os.walk(path, topdown=False):
        is_excluded = False
        for ex in excluded:
            if root.startswith(ex):
                is_excluded = True
                break
        if is_excluded:
            continue

        # Delete all files with extension .ex5
        for file in files:
            if file.endswith('.ex5'):
                file_path = os.path.join(root, file)
                os.remove(file_path)
                print(f'File removed: {file_path}')

        # Delete all folders that have become empty after deleting files
        for dir in dirs:
            dir_path = os.path.join(root, dir)

            # IF the directory is empty after deleting files
            if dir_path not in excluded and not os.listdir(dir_path):
                try:
                    os.rmdir(dir_path)
                    print(f'Empty folder removed: {dir_path}')
                except OSError:
                    pass  # If error occurred, ignore


excluded = [
    '.git',
    '.vscode',
    'Experts\\Advisors',
    'Experts\\Examples',
    'Experts\\Free Robots',
    'Experts\\Market'
    'Files',
    'Images',
    'Include\\Arrays',
    'Include\\Canvas',
    'Include\\ChartObjects',
    'Include\\Charts',
    'Include\\Controls',
    'Include\\Expert',
    'Include\\Files',
    'Include\\Generic',
    'Include\\Graphics',
    'Include\\Indicators',
    'Include\\Math',
    'Include\\OpenCL',
    'Include\\Strings',
    'Include\\Tools',
    'Include\\Trade',
    'Include\\WinAPI',
    'Indicators\\Examples',
    'Indicators\\Free Indicators',
    'Libraries',
    'Logs',
    'Presets',
    'Profiles',
    'Scripts\\Examples',
    'Scripts\\UnitTests',
    'Services',
    'Shared Projects',
]

if __name__ == '__main__':
    current_dir = os.getcwd()  # Current working directory
    delete_ex5_files_and_empty_dirs(current_dir, excluded)

将此脚本保存为存储库根目录中的 clean.py ,并将其添加到主分支中的版本控制中。从现在开始,从 archive 切换回 main 后,只需运行此脚本即可自动清理编译的文件和空文件夹。


结论

在这里,我们结束了对新存储库系统的初步实验。我们所有的文件都已成功转移到其中。我们已经为为新项目创建新的项目分支奠定了基础。由于代码安全地存储在归档分支中,我们可以根据需要逐步将项目迁移到单独的分支中。

下一步有趣的事情是尝试为我们的文章系列 “开发多币种 EA 交易” 的源代码创建一个公共存储库。目前还不清楚如何在该系列的不同部分构建代码,但我们将在不久的将来解决这个问题。

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


存档内容

#
 名称
版本  描述 
  MQL5   存储库根文件夹(终端数据文件夹)
1 .gitignore 1.00
Git 版本控制系统忽略的文件列表文件夹和文件
2 clean.py
1.00 切换到存储库主分支时删除已编译文件和空目录的脚本

本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/17646

附加的文件 |
MQL5.zip (1.66 KB)
最近评论 | 前往讨论 (7)
Maxim Kuznetsov
Maxim Kuznetsov | 7 4月 2025 在 15:52
Yuriy Bykov 项目 的代码。

说实话,我们确实没有考虑过这种情况。我不知道现在在论坛上封禁用户是否会限制对当前 MQL 存储库的访问,以及这是否也会限制对新存储库的访问。如果是这样,这个风险因素当然值得考虑。

很难检查这一点--因此风险评估只是理论上的;-)但确实存在这样的风险

MQLStorage 需要登录到社区。登录的技术可能性掌握在管理员手中。从理论上讲,如果您严重违反规则(或有人会认为严重违反规则),就会被严厉禁止。临时禁令只是 "权利的失败",只是禁止网站的组件和个别服务。

但也有虚拟,服务器,数据中心,网络,赢得了禁止PO-IP 。在那里,MQLStorage 很可能是不可用的。您可以不通过个人努力,甚至只是通过动态 IP :-) 获得它。

为了尽量减少这种风险 - 保持完整备份和独立的存储库镜像。这是另一种乐趣...

Rashid Umarov
Rashid Umarov | 9 9月 2025 在 09:00
Maxim Kuznetsov 项目 说再见 :-)

首先,https://forge.mql5.io/ 有两种授权选项。您可以创建一个完全独立于 MQL5.com 的账户

其次,禁止在论坛上发帖仅意味着禁止发帖,对其他服务没有影响。

第三,禁言与此有关吗? 参与机器人的开发,而不是论坛。




Stanislav Korotky
Stanislav Korotky | 9 9月 2025 在 14:09
Rashid Umarov #:

首先,https://forge.mql5.io/ 有两种授权选项。您可以创建一个完全独立于 MQL5.com 的账户

但如果不依赖 mql5.com,如何访问 ME 项目?似乎必须登录那里的社区。

Rashid Umarov
Rashid Umarov | 9 9月 2025 在 14:13
Stanislav Korotky #:

如果不依赖 mql5.com,如何从 ME 访问项目?似乎有必要登录那里的社区。

对了,无论如何都要在 MQL5.com 创建账户。

Yuriy Bykov
Yuriy Bykov | 9 9月 2025 在 14:27
Stanislav Korotky #:

如果不依赖 mql5.com,如何从 ME 访问项目?似乎有必要登录那里的社区。

你还不必登录社区。如果您从 Algo Forge 或 GitHub 等任何版本库克隆一个版本库到 MQL5 数据文件夹内的文件夹,它将作为一个包含文件的文件夹可见。这对于编辑、启动和调试来说已经足够,但对版本库的所有操作都必须使用第三方工具来执行。在 ME 还不能使用 Algo Forge 时,我曾使用过一段时间。但总的来说,使用 mql5.com 账户更方便。

交易策略 交易策略
各种交易策略的分类都是任意的,下面这种分类强调从交易的基本概念上分类。
流动性攫取交易策略 流动性攫取交易策略
流动性攫取交易策略是智能资金概念(SMC)的核心组成部分,旨在识别并利用市场中机构投资者的操作行为。该策略聚焦于高流动性区域(如支撑位或阻力位),在这些区域,大额订单可引发价格波动,随后市场恢复原有趋势。本文将详细阐释流动性攫取的概念,并概述如何在MQL5中开发流动性攫取交易策略的智能交易系统(EA)。
新手在交易中的10个基本错误 新手在交易中的10个基本错误
新手在交易中会犯的10个基本错误: 在市场刚开始时交易, 获利时不适当地仓促, 在损失的时候追加投资, 从最好的仓位开始平仓, 翻本心理, 最优越的仓位, 用永远买进的规则进行交易, 在第一天就平掉获利的仓位,当发出建一个相反的仓位警示时平仓, 犹豫。
开发一款波段交易入场监控智能交易系统(EA) 开发一款波段交易入场监控智能交易系统(EA)
随着年末临近,长期交易者往往会回顾市场历史数据,分析市场行为与趋势,以期预测未来可能的走势。本文将探讨如何使用MQL5开发一款长期交易入场监控智能交易系统(EA)。该系统的开发旨在解决因手动交易和缺乏自动化监控系统而导致的长期交易机会错失问题。我们将以交易量最为活跃的货币对之一为例,有效制定策略并开发我们的解决方案。