MIT License

技术解读

以下内容由 GitRead 中文社区 编辑团队基于项目 README 与官方资料整理, 结合中文开发者的常见使用场景补充技术选型建议。具体以项目官方文档为准。

MetaTrader API (terminal bridge) 技术分析

项目背景与痛点

vdemydiuk/mtapi 是一个用于与 MetaTrader 终端进行交互的 API 实现。MetaTrader 平台是金融交易者常用的工具,其 API 的复杂性和限制性让开发者难以直接对交易平台进行自动化操作。mtapi 项目则提供了一个桥梁,解决了开发者与交易平台间交互的痛点。它简化了与 MT 终端的通信流程,让用户能够更高效地使用自动化脚本控制交易行为。

核心技术揭秘

mtapi 的核心在于其能够通过消息队列机制实现对 MetaTrader 终端的异步操作。通过 TCP/IP 协议与后台进程通信,它能够发送交易命令和接收市场数据。项目的设计思想在于将复杂的交易平台抽象成一组结构化的 API 接口,简化了对 MetaTrader 终端的访问。

在技术栈方面,mtapi 使用了 C++ 编写后端,提高了执行效率,适用多线程环境处理大量并发任务。以下是其关键的数据流架构:

graph TD A[用户请求] --> B("请求队列") B --> C("处理进程") C --> D{"请求类型?"} D -->|"交易命令"| E[发送交易命令] D -->|"获取市场数据"| F[查询市场数据] E --> G[返回命令结果] F --> G[返回命令结果] G --> H[结果处理]

此架构图展示了用户的请求如何被接收入队,再经由进程处理,根据请求类型发送不同的命令或查询数据,并等待返回结果,最后将结果反馈给用户。

功能亮点与差异

相较于竞争对手,mtapi 的关键优势在于其提供了更灵活且高效的 API 接口。特别是在交易命令执行和数据获取上,它能够通过并行处理提高响应速度。此外,该项目还具备良好的扩展性,对于高级用户来说更容易进行定制开发和二次开发。这样的设计不仅增强了功能性,还极大地拓展了项目的应用范围。

应用场景与落地建议

在生产环境使用 mtapi 时,需要重点注意其消息队列机制的稳定性和可靠性。建议在高并发场景下进行压力测试,确保系统平稳运行。此外,由于金融市场的敏感性,还需确保数据传输的安全性和隐私保护措施。

mtapi 适用于以下场景:

  • 具备自动化交易需求的高频交易员。
  • 需要对市场数据流进行实时处理的金融数据分析公司。
  • 开发多个自动化交易策略并进行优化测试的开发者。

综合评价

优点:

  • 高效的数据处理和交易执行速度。
  • 灵活且可扩展的 API 接口。
  • 稳定的消息队列机制和多线程支持。

缺点:

  • 需要一定的 C++ 和金融交易平台开发基础。
  • 文档部分细节较少,新手上手有一定学习成本。

整体来说,vdemydiuk/mtapi 是一款优秀的 MetaTrader 平台交互工具,尤其是在需要高效率处理交易指令和市场数据的环境下。尽管门槛略高,但其技术优势和灵活性使其成为金融技术开发者们的理想选择。

简要分析

热度分
1442
价值分
526
活跃状态
活跃

语言占比

C
C#
C++
MQL4
MQL5
Visual Basic .NET

README

Introduction

MtApi provides a .NET API for working with famous trading platfrom MetaTrader(MetaQuotes).
It is not API for connection to MT servers directly. MtApi is just a bridge between MT terminal and .NET applications designed by developers.
MtApi executes MQL commands and functions by MtApi’s expert linked to chart of MetaTrader.
Most of the API’s functions duplicates MQL interface.
The project was designed using WebSocket framework with the intention of using flexibility to setup connections.

Build environment

The project is supported by Visual Studio 2022 and based on .NetCore (.Net 8). It requires HeatWave for VS2022 - set of tools for creating WiX installation packages (https://marketplace.visualstudio.com/items?itemName=FireGiant.FireGiantHeatWaveDev17). Just install the VS extensions.

Use MetaEditor to working with MQL files.

How to Build Solution

To build the solution for MT4, you need to choose the configuration to build for x86 and start with building the MtApiInstaller. This will build all projects related to MT4:

  • MtApi
  • MtClient
  • MtService
  • MTConnector

For building the solution for MT5, you need to choose the configuration to build for x64 (or x86 for the 32-bit MT5)) and start build MtApi5Installer. This will build all projects related to MT5:

  • MtApi5
  • MtClient
  • MtService
  • MT5Connector

All binaries are placed in the project root folder, in the build directory: ../build/.
The installers (*.msi) will be found under: **…/build/installers/**. All the DLL library binaries (***.dll**) in: **…/bin/`.

MQL files have been pre-compiled to *.ex4 and can be found in the repository here:

  • ..\mql4\
  • ..\mql5\

Changing the source code of the MQL Expert Advisor (EA), requires recompilation with MetaEditor.

Before you can recompile the EA, you need to add/place the following MQL library files, in the MetaEditor ../Include/ folder.

  • hash.mqh
  • json.mqh

The MetaEditor include folder is usually located here:

C:\Users\<username>\AppData\Roaming\MetaQuotes\Terminal\<terminal-hash>\MQL5\Include\.

Project Structure

  • MtService: (C++, .dll)
    The common engine communication project of the API. It contains the implementations of server sides based on WebSocket (from Boost library).

  • MtClient: (C#, .dll)
    The client side communication project of the API (based on WebSocket).

  • MTConnector, MT5Connector: (C++, .dll)
    The libraries that are working as proxy between MQL and C# layers. They provides the API interfaces for working with MQL experts.

  • MtApi, MtApi5: (C#, .dll)
    The client side libraries that are using in user’s projects.

  • (MQL4/MQL5, .ex4/.ex5)
    MT4 and MT5 Expert Advisors linked to terminal’s charts. They executes API’s functions and provides trading events.

  • MtApiInstaller, MtApi5Installer (WIX, .msi)
    The project’s installers.

  • Boost libraries (*.lib)
    Precompiled x64 and x86 libraries for using with C++ projects, placed in [root]\thirdparty.

Installation

Use the installers to setup all libraries automatically.

  • For MT4, use: MtApiInstaller.msi
  • For MT5, use: MtApi5Installer_x64.msi

To quickly navigate to the trading platform data folder, click: File >> "Open data folder" in your MetaTrader Terminal.

Additional packets

VCRedist packet must be installed for correct working MtApi connectors (MTConnector or MT5Connector). Use Microsoft website to download required installers: https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170

Using

MtApi provides two types of connection to MetaTrader terminal: local and remote (via TCP).
The port of connection is defined by MtApi expert.

Console sample for MT5:

using System;
using System.Threading;
using System.Threading.Tasks;
using MtApi5;

namespace MtApi5Console
{
    class Program
    {
        static readonly EventWaitHandle _connnectionWaiter = new AutoResetEvent(false);
        static readonly MtApi5Client _mtapi = new MtApi5Client();

        static void _mtapi_ConnectionStateChanged(object sender, Mt5ConnectionEventArgs e)
        {
            switch (e.Status)
            {
                case Mt5ConnectionState.Connecting:
                    Console.WriteLine("Connnecting...");
                    break;
                case Mt5ConnectionState.Connected:
                    Console.WriteLine("Connnected.");
                    _connnectionWaiter.Set();
                    break;
                case Mt5ConnectionState.Disconnected:
                    Console.WriteLine("Disconnected.");
                    _connnectionWaiter.Set();
                    break;
                case Mt5ConnectionState.Failed:
                    Console.WriteLine("Connection failed.");
                    _connnectionWaiter.Set();
                    break;
            }
        }

        static void _mtapi_QuoteAdded(object sender, Mt5QuoteEventArgs e)
        {
            Console.WriteLine("Quote added with symbol {0}", e.Quote.Instrument);
        }

        static void _mtapi_QuoteRemoved(object sender, Mt5QuoteEventArgs e)
        {
            Console.WriteLine("Quote removed with symbol {0}", e.Quote.Instrument);
        }

        static void _mtapi_QuoteUpdate(object sender, Mt5QuoteEventArgs e)
        {
            Console.WriteLine("Quote updated: {0} - {1} : {2}", e.Quote.Instrument, e.Quote.Bid, e.Quote.Ask);
        }

        static void Main(string[] args)
        {
            Console.WriteLine("Application started.");

            _mtapi.ConnectionStateChanged += _mtapi_ConnectionStateChanged;
            _mtapi.QuoteAdded += _mtapi_QuoteAdded;
            _mtapi.QuoteRemoved += _mtapi_QuoteRemoved;
            _mtapi.QuoteUpdate += _mtapi_QuoteUpdate;

            _mtapi.BeginConnect(8228);
            _connnectionWaiter.WaitOne();

            if (_mtapi.ConnectionState == Mt5ConnectionState.Connected)
            {
                Run();
            }

            Console.WriteLine("Application finished. Press any key...");
            Console.ReadKey();
        }

        private static void Run()
        {
            ConsoleKeyInfo cki;
            do
            {
                cki = Console.ReadKey();
                switch (cki.KeyChar.ToString())
                {
                    case "b":
                        Buy();
                        break;
                    case "s":
                        Sell();
                        break;
                }
            } while (cki.Key != ConsoleKey.Escape);

            _mtapi.BeginDisconnect();
            _connnectionWaiter.WaitOne();
        }

        private static async void Buy()
        {
            const string symbol = "EURUSD";
            const double volume = 0.1;
            MqlTradeResult tradeResult = null;
            var retVal = await Execute(() => _mtapi.Buy(out tradeResult, volume, symbol));
            Console.WriteLine($"Buy: symbol EURUSD retVal = {retVal}, result = {tradeResult}");
        }

        private static async void Sell()
        {
            const string symbol = "EURUSD";
            const double volume = 0.1;
            MqlTradeResult tradeResult = null;
            var retVal = await Execute(() => _mtapi.Sell(out tradeResult, volume, symbol));
            Console.WriteLine($"Sell: symbol EURUSD retVal = {retVal}, result = {tradeResult}");
        }

        private static async Task<TResult> Execute<TResult>(Func<TResult> func)
        {
            return await Task.Factory.StartNew(() =>
            {
                var result = default(TResult);
                try
                {
                    result = func();
                }
                catch (ExecutionException ex)
                {
                    Console.WriteLine($"Exception: {ex.ErrorCode} - {ex.Message}");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Exception: {ex.Message}");
                }

                return result;
            });
        }
    }
}

Telegram Channel

https://t.me/joinchat/GfnfUxvelQCLvvIvLO16-w

评论

暂无评论