English Русский Español Deutsch 日本語 Português 한국어 Français Italiano Türkçe
preview
学习为什么、以及如何设计算法交易系统

学习为什么、以及如何设计算法交易系统

MetaTrader 5交易 | 7 四月 2022, 08:57
2 485 0
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

概述

我们可以毫无疑问地说,编程或编码的重要性在我们世界的各个领域每天都在提升。 故此,我们可以观察编程或编码为我们的生活变得更轻松如何做出贡献,而且可以根据您想要的、和您之前确定的内容保证准确的输出。

一旦进入交易世界 — 这个伟大的领域和职业 — 我们可以说,编程或编码令我们的交易变得简单,所创建程序会更加系统化;一旦我们依据自己的期望和想要的东西完成了一个精准和优秀的程序,它就可让我们实现更方便和自动化。 因此,编码的世界可以给我们带来很多益处,但在我看来,编码交易最重要之处是帮助您遵守纪律,就像我们所有人都知道的那样,作为交易员,我们的交易决策需要一直遵守纪律。 纪律是关乎我们交易和投资结果的一个重要特征,因此遵守纪律在交易中并非选项。 正如我常说的,纪律是您在交易和一生中能否成功的关键。 为了用一种简单的方式明辨纪律,这意味着无论周围的环境如何,都要在正确的时间做您必须做的事情。 因此,当我们找到一个工具来帮助实现这一点时,我们必须要全神贯注,并了解它到底是什么。 正确的编码工具。

众所周知,在交易过程中,阻碍我们自律的最常见事情就是情绪,我们必须避免这些情绪,或者当避免这些情绪对交易决策产生影响时采取消极方式。 我想让大家想象一下,如果你们有一个系统,它能在不受人为干预的情况下,以预定的参数为你们工作。 那么,在此情况下,情绪对我们交易决策的负面影响就能被避免。 好消息是,我们有一个工具可以帮助我们做到这一点。 此处,我将为 MetaTrader 平台撰写关于 MQL(MetaQuotes 语言)的文章。 这个伟大的编程语言或工具将帮助我们设计自己的交易系统,我们指定的参数将保证具体的行动、或具体的交易决策。

如果您想更多地了解这个概念,我们来举一个例子。 如果我们有两位投资者(A 和 B),他们的交易策略相同,在上升趋势中买入并持有,在逆转趋势时卖出;但他们每个人的行为不同 — 投资者 A 遵守约束,但投资者 B 不会。 请看以下示意图:


2- Investor_B


因此,根据之前的数据,很明显,纪律对于良好的结果至关重要,但缺乏纪律会导致糟糕的结果。

通过本文,我将与大家分享一款简单的移动平均线交叉交易系统,学习如何通过分享 MQL5 编码的一些基础知识来设计自己的交易系统,并通过示例来练习并深入理解这些基础知识。 目的是给您一个关于利用这个华丽工具能够做哪些事情的概述。

本文的主要目的是通过学习 MQL5 的一些基础知识,引导初学者学习如何在 MQL5 中设计算法交易系统,从而获得一个简单交易系统的概念,在解释了 MQL5 的一些基础知识后,在本文会中逐步实现编码。 我们会通过脚本针对它们编码,然后代码执行后会显示结果。 为了增进您的理解,我建议您自己实现并编写在此阅读的内容,因为这将帮助您深入理解上述代码的概念。 需要注意的是,本文中创建的全部代码、程序和交易策略都是为教育目的而设计的,而无其它目的。 请注意,我们将使用 MQL5 编写代码。


我们在设计我们的算法交易时需要什么

在这一部分中,我会提及我们打算要用的工具,以及我们打算了解的工具:

  • MetaTrader 5平台,又名 MetaTrader 5 终端。 通过终端执行命令和测试我们的代码。 MetaTrader 是最受欢迎的交易平台。



3- MT5 平台

演示账户 您可在您的经纪商那里开一个演示账户,在相同的市场环境下,无风险的用虚拟货币来测试您的交易策略。 请务必使用演示帐户而不是您的实盘帐户实验编码,因为您所创建和执行的程序需要在您的帐户上执行交易。

MetaQuotes 语言编辑器,我们将在其中编写代码或程序。 下面的屏幕截图将显示安装了 MetaTrader 后如何打开它。 有三种方法可以打开它。

  • 单击工具菜单,然后单击 MMetaQuotes 语言编辑器:

4- MetaEditor 打开  

                   

或者单击 MetaQuotes 编辑器图标:

   5- MetaEditor 打开

或者在打开终端后按键盘上的 F4 键。

下面的屏幕截图展示了它的样子,于此我们编写程序和设计交易系统的大部分工作。

   6- MetaEditor 窗口

 

现在我们需要用这个编辑器来编写我们的第一个代码,所以按照下面的步骤来了解如何做到这一点。

单击“新建”,您将找到多种类型的程序可供选择:

7- MetaEditor 窗口



8- MetaEditor - 新建



在本文中,我们需要提及的是:智能交易系统、自定义指标和脚本。

  • 智能交易系统:EA 是终端中的一个程序,根据您设置的参数开发,并用于自动化分析和交易过程。
  • 自定义指标:是一段已编码的程序;它主要用于附属初步计算的图形显示。
  • 脚本:是一个用于执行任何单一操作的程序,它可以实现分析和交易功能,并且与智能交易系统不同,它是根据请求执行的,而非基于即时报价执行。

启程的 Hello World! 程序

在这一部分中,我们将学习如何利用 MQL5 编写第一个程序和第一段代码。 所有编程或编码的初学者都从编写 “Hello World” 代码开始他们的旅程。 因此,我们将首先编写一个程序,在终端屏幕上打印 “Hello World”。 我们开始吧…

如上图所示打开 MetaEditor 编辑器,然后单击新建,然后从选项(脚本)中选择,然后单击下一步。


9- MetaEditor - 新建文件 - 脚本


单击 “下一步” 后,将出现以下窗口。 填写您所需脚本的数据:

  • Name 是脚本的名称
  • Author 是脚本的创作者吗
  • Link 是您的链接
  • Parameter 是您需要为脚本设置的参数,但此处我们不会为该脚本设置任何参数,因此跳过它。
然后单击完成。

10- MetaEditor - 脚本信息


单击“完成”后,将打开以下窗口。 在这个窗口中,会生成我们的程序代码。正如我所提及的那样,我们需要设计一个在终端上显示 “Hello World!” 的程序。 因此,我们将开始在两个花括号之间编写代码。


 11 - 代码位置

在此我们会用:

  • Alert: 它打印我确定的内容,或者在程序中显示一条预先确定的消息,而在我们的示例中是 “Hello World!”
  • ( “ ”): 在引号里写入我想要的东西和预先确定的信息 “Hello World!” 或任何内容。
  • ; - 分隔句子。

我们的代码如下相同:

//+----------------------------------------------------------+
//|                                         Hello World!.mq5 |
//|                          Copyright 2022, MetaQuotes Ltd. |
//|                                     https://www.mql5.com |
//+----------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+----------------------------------------------------------+
//| Script program start function                            |
//+----------------------------------------------------------+
void OnStart()
  {
   Alert("Hello World!");
  }
//+----------------------------------------------------------+

代码编写完毕后,单击编译,然后确保没有错误和警告。 编译代码后,“错误”选项卡里必须没有错误,从而确保程序的运行与我在下图中示意的相同。 然后按 F4 键进入终端,测试我们的代码。

12- Hello World 代码

在此之后,在终端的导航窗口中的脚本之下,您能找到之前选定的程序名(Hello World!),将其拖放到图表上或双击。 之后,您将看到一条警告消息出现,其中包含您在代码中确定的内容。 它应该与下面的屏幕截图相同。

13- Hello World 警报



交易策略理念(两条简单的移动平均线交叉

在这一部分中,我将提出一个仅出于教育意图的交易策略思路。 它旨在帮助您学习 MQL5 的基础知识,以及如何利用 MQL5 编程。

免责声明
提供的任何信息均“按原样”,目的仅作为信息,并非出于交易目的或建议。 过去的绩效表现并不能保证未来之结果。如果您在任何交易账户上选用这些材料,请您风险自担。

此处,策略思路是尝试利用两条简单的移动平均线指标的信号来确认趋势:

  • 简单移动平均线是一个滞后的技术指标,它计算指定时期的平均收盘价,它是滞后的,因为它的信号于价格行动信号之后才生成。
  • 策略如下:
    • 如果较短周期的简单移动平均线(其周期为 20)向上穿越较长周期的简单移动平均线(其周期为 50),则信号为买入。
    • 如果较短周期的简单移动平均线(其周期为 20)向下穿越较长周期的简单移动平均线(其周期为 50),则信号为卖出。

此处,我们需要设计一个程序来执行这一切。

15- 交易思路1


14- 交易思路


算法交易系统蓝图

在这一部分中,我将谈及一个非常重要的步骤,如果您想轻松顺利地编写系统代码,就必须进行这个步骤。 这一步是为您的策略和交易思路创建一幅蓝图,设计完成的系统会准确遵照您的希望按步骤顺序操作;例如,您可以通过一幅示意图来完成,它会给您一个清晰的蓝图。 这是我们(两条简单的移动平均线交叉)系统蓝图的一个示例,它以清晰的方式令我们看到需要哪些编码,以及我们期望从这个系统中得到什么。

    16- Simple 2MA-Blueprint-–-MQL5


      现在,我们首先来了解 MQL5 的一些基础知识,然后是我们的设计需要用到的内容。


      它们是变量和类型,以及我们如何使用

      在本部分中,我们将辨别并理解:

      • 什么是变量?
      • 变量的类型。
      • 我们如何使用它们?

      一般来说,在程序中,数据值可以是常量或变量。 如果数值是可变的,则程序和用户可以对其进行更改。 变量是一个内存位置。 它有一个与该位置关联的名称。 因此,内存位置用于保存数据。 MQL5 的程序可以包含数十个或数百个变量。 每个变量都有一个非常重要的特性,即能在程序中存取其数值。 这种可能性的局限性与变量的作用域有关,变量作用域是变量值在程序中可用的区域。 每个变量都有其作用域。

      因此,根据作用域,MQL5 中有两种类型的变量,局部变量和全局变量。 局部变量是在函数内部声明的变量。 局部变量的作用域,局限在声明变量的函数实体内部。 局部变量可以由常量,或与其类型对应的表达式初始化。 声明的全局变量能够超出所有函数。 全局变量的作用域是整个程序。 全局变量只能由与其类型(而不是表达式)对应的常量初始化。 在指定的函数执行之前,全局变量只会初始化一次。

      无论变量的作用域如何,现在我们来查看以下类型的变量:

      • int 是数字类型;有不同类型的整数型来存储不同长度的数值。
      • double. 构建一个能够处理交易中所用数字的程序需要一种能够管理浮点数的数据类型。所以 MetaTrader 提供了以下数据类型来处理这些数据:float 和 double。 它们之间的差异是内存中分配的字节数,float 有 4 字节,double 有 8 字节,从而产生以下最小值和最大值:
        • float - 最小 1.175494351e-38, 最大 3.402823466e+38
        • double - 最小 2.2250738585072014e-308, 最大 1.7976931348623158e+308
          为了声明这些类型的数据,需用 float 和 double 关键字。
      • string 是一种非常重要的数据类型,在 MQL5 编码中也广泛使用。 字符串允许存储和操作任何字母数字字符序列。
      • bool - 布尔型是一种逻辑类型,可以假定为 true 或 false

      我们举一个使用变量的例子:

      //+------------------------------------------------------------------+
      //|                                                    Variables.mq5 |
      //|                                  Copyright 2022, MetaQuotes Ltd. |
      //|                                             https://www.mql5.com |
      //+------------------------------------------------------------------+
      #property copyright "Copyright 2022, MetaQuotes Ltd."
      #property link      "https://www.mql5.com"
      #property version   "1.00"
      //+------------------------------------------------------------------+
      //| Script program start function                                    |
      //+------------------------------------------------------------------+
      void OnStart()
        {
          int myInteger = 5;
          double myDouble = 10.56;
          string myString = "My name is Mohamed";
          bool myBoolean = true;
          
          Alert(myInteger);
          Alert(myDouble);
          Alert(myString);
          Alert(myBoolean); 
        }
      //+------------------------------------------------------------------+
      

      在编译了前面的代码之后,如果您在编写时像我上面那样,那么您不会有任何错误或警告,且您肯定能看到下面屏幕截图所示的警报窗口。

      18- 变量

      另一个使用变量的例子。

        在此,我们需要存储或记忆变量及其数值,A 及其值为 10,B = 10,C = 10 + 5,var1 = 2.5,var2 = 4,result = 2.5/4,message1 = Hello Mohamed,以及 message2 = A 的值,即: 10。 因此,当我们执行此代码时,警报消息将包含 4 个元素:
        • message1 的等效值
        • C 的等效值
        • result 的等效值
        • message2 的等效值
        //+------------------------------------------------------------------+
        //|                                                  Variables 2.mq5 |
        //|                                  Copyright 2022, MetaQuotes Ltd. |
        //|                                             https://www.mql5.com |
        //+------------------------------------------------------------------+
        #property copyright "Copyright 2022, MetaQuotes Ltd."
        #property link      "https://www.mql5.com"
        #property version   "1.00"
        //+------------------------------------------------------------------+
        //| Script program start function                                    |
        //+------------------------------------------------------------------+
        void OnStart()
          {
           int A = 10;
           int B = 5;
           int C;
         
           double var1 = 2.5;
           double var2 = 4;
           double result = var1 / var2;
           
           string greeting = "Hello";
           string space = " ";
           string name = "Mohamed";
           string message1;
           string message2;
           
           C = A + B;
           message1 = greeting + space + name;  
           message2 = "Value of A is: " + string(A);
           
           Alert(message1);
           Alert(C);
           Alert(result);
           Alert(message2);
          }
        //+------------------------------------------------------------------+
        


         19- 变量 2

        布尔运算

        布尔值:简单地说,进行逻辑运算,返回 true 或 false。

        • == 意思是等于
        • != 意思是不等于
        • < 意思是小于
        • <= 意思是小于或等于
        • > 意思是大于
        • >= 意思是大于或等于
        //+------------------------------------------------------------------+
        //|                                           Boolean Operations.mq5 |
        //|                                  Copyright 2022, MetaQuotes Ltd. |
        //|                                             https://www.mql5.com |
        //+------------------------------------------------------------------+
        #property copyright "Copyright 2022, MetaQuotes Ltd."
        #property link      "https://www.mql5.com"
        #property version   "1.00"
        //+------------------------------------------------------------------+
        //| Script program start function                                    |
        //+------------------------------------------------------------------+
        void OnStart()
          {
           bool result = 4 < 5;
           Alert (result);     //true
          }
        //+------------------------------------------------------------------+
        

        在此,若 4<5 时,它必须在警报返回消息 true。

         20- 布尔运算

        While 循环

        while 操作符由一个检验表达式,和一个必须满足的操作符组成。 如果表达式为 true,则执行该操作符,直到表达式变为 false。 在下面的示例中,我们可以了解,首先在开始时发出警报,以便知晓循环的开始和结束,然后程序将检查计数器的值,如果小于 3,则显示其值。 然后,它将在之前的结果中加一,直到变为 false,在本例中 = 或 > 3,然后在循环完成时发出最后一个警报。 因此,我们将在警报消息中看到来自此代码的以下消息:脚本开始,1,2,循环已完成。
        //+------------------------------------------------------------------+
        //|                                                   While Loop.mq5 |
        //|                                  Copyright 2022, MetaQuotes Ltd. |
        //|                                             https://www.mql5.com |
        //+------------------------------------------------------------------+
        #property copyright "Copyright 2022, MetaQuotes Ltd."
        #property link      "https://www.mql5.com"
        #property version   "1.00"
        //+------------------------------------------------------------------+
        //| Script program start function                                    |
        //+------------------------------------------------------------------+
        void OnStart()
          {
           //While (Loop)
           Alert("Start of script");
           
           int counter = 1;
           
           while(counter < 3) //true?
            {
              Alert(counter);
              counter = counter + 1;
            }
            
            Alert("Loop has finished");
          }
        


         21- While 循环


        For 循环

        for 操作符由三个表达式和一个可执行操作符组成:

                 for(expression1; expression2; expression3)
                 operator;

        Expression1 描述循环初始化。 Expression2 检查循环终止的条件。 如果为 true,则执行循环体。 循环重复,直到 expression2 变为 false。 如果为 false,则终止循环,并将控制权交给下一个操作符。 Expression3 在每次迭代后执行计算。

        如此,根据下面的循环示例,我们可以预期代码的执行将产生五条 Hello 消息(I=0,I=2,…..,I=4),然后它将 = 5,循环将因此被终止。

        //+------------------------------------------------------------------+
        //|                                                     For Loop.mq5 |
        //|                                  Copyright 2022, MetaQuotes Ltd. |
        //|                                             https://www.mql5.com |
        //+------------------------------------------------------------------+
        #property copyright "Copyright 2022, MetaQuotes Ltd."
        #property link      "https://www.mql5.com"
        #property version   "1.00"
        //+------------------------------------------------------------------+
        //| Script program start function                                    |
        //+------------------------------------------------------------------+
        void OnStart()
          {
           for(int i=0; i<5 ; i++)
           {
           Alert("Hello");
           }
          }
        //+------------------------------------------------------------------+
        


        22- For 循环

        IF, Else 语句

        IF - ELSE 运算符是在必须做出选择时使用。 形式上,语法如下:


        if (expression)
        operator1
        else
        operator2


        如果 expression 为 true,则执行 operator1,然后将控制权交给 operator2 后面的操作符(不执行 operator2)。 如果 expression 为 false,则执行 operator2(不执行 operator1)。

        示例:根据下面的示例,我们会首先收到一个含有出价的警报,然后我们确定如果出价 > 1.146600,那么我们就会收到“价格高于 1.146600 -> 买入”的警报。 如果没有,我们会收到“价格低于 1.146600 -> 卖出”的警告。 下面是代码及其执行结果。

        //+------------------------------------------------------------------+
        //|                                            If-else statement.mq5 |
        //|                                  Copyright 2022, MetaQuotes Ltd. |
        //|                                             https://www.mql5.com |
        //+------------------------------------------------------------------+
        #property copyright "Copyright 2022, MetaQuotes Ltd."
        #property link      "https://www.mql5.com"
        #property version   "1.00"
        //+------------------------------------------------------------------+
        //| Script program start function                                    |
        //+------------------------------------------------------------------+
        void OnStart()
          {
           double level = 1.146600;
           double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
           Alert("Bid Price = " + string(Bid));
        
          if(Bid > level)
          {
          Alert ("The price is above " + string(level) + " -> BUY");
          }
        // What if the condition is false and we need to take an action also here we can use else function instead of writing another if code
           else
           {
           Alert ("The price is below " + string(level) + " -> SELL");
           } 
            
          }
        //+------------------------------------------------------------------+
        


         23- If-Else 语句


        交易员输入

        在这一部分中,我们将学习如何确定程序的输入或首选参数,用其替代修改代码。

        属性(#property):每个 MQL5 程序都允许指定名为 #property 的附加特定参数,从而帮助客户端正确维护程序,而无需显式启动它们

        script_show_inputs: 在运行脚本之前显示包含属性的窗口,并禁用此确认窗口

        输入变量:  input 存储定义的外部变量。  input 前面的修饰符指明数据类型。

        //+------------------------------------------------------------------+
        //|                                                Trader Inputs.mq5 |
        //|                                  Copyright 2022, MetaQuotes Ltd. |
        //|                                             https://www.mql5.com |
        //+------------------------------------------------------------------+
        #property copyright "Copyright 2022, MetaQuotes Ltd."
        #property link      "https://www.mql5.com"
        #property version   "1.00"
        #property script_show_inputs
        //+------------------------------------------------------------------+
        //| Script program start function                                    |
        //+------------------------------------------------------------------+
        input int TakeProfit = 10;
        input int StopLoss = 10;
        
        void OnStart()
          {
           double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
           double TakeProfitLevel = Bid + TakeProfit * 0.00001; // 0.00001 (5 digits broker, so multiplied by 10)
           double StopLossLevel = Bid - StopLoss * 0.00001;
           
           Alert("Price now = " + string(Bid));
           Alert ("TakeProfitLevel = ", TakeProfitLevel);
           Alert ("StopLossLevel = ", StopLossLevel);
          }
        //+------------------------------------------------------------------+
        

        24- 交易员输入 1


        24- 交易员输入 2


         24- 交易员输入 3


        24- 交易员输入 4


        开单

        在这一部分中,我将讲解如何编写开单的代码:

        //+------------------------------------------------------------------+
        //|                                                         TEST.mq5 |
        //|                                  Copyright 2022, MetaQuotes Ltd. |
        //|                                             https://www.mql5.com |
        //+------------------------------------------------------------------+
        #property copyright "Copyright 2022, MetaQuotes Ltd."
        #property link      "https://www.mql5.com"
        #property version   "1.00"
        #property script_show_inputs
        #include <Trade\Trade.mqh>
        CTrade trade;
        //+------------------------------------------------------------------+
        //| Script program start function                                    |
        //+------------------------------------------------------------------+
        input int TakeProfit = 150;
        input int StopLoss = 100;
        
        void OnStart()
          {
           double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
           double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
           double Balance = AccountInfoDouble(ACCOUNT_BALANCE);
           double Equity = AccountInfoDouble(ACCOUNT_EQUITY); 
           double TakeProfitLevel = (Ask+TakeProfit*0.00001);
           double StopLossLevel = (Ask-StopLoss*0.00001);
           
           
           if(Equity >= Balance)
           trade.Buy(0.01,NULL,Ask,StopLossLevel,TakeProfitLevel,NULL);
           
           for (int i=PositionsTotal()-1; i>=0; i--)
           {
             ulong ticket = PositionGetTicket(i);
             ENUM_POSITION_TYPE position = ENUM_POSITION_TYPE(PositionGetInteger(POSITION_TYPE));
        
              
             Alert (" Order Ticket # ", ticket);
             Alert("TakeProfit = ", TakeProfitLevel);
             Alert("StopLoss = ", StopLossLevel);
           }
          }
        //+------------------------------------------------------------------+
          脚本执行后,结果如下:

          25- 开单


          错误处理技术

          当程序运行时,任何人都可以发现它崩溃了,并且出现了问题。 因此,我们必须在代码中加入这种技术,从而检查每个执行的命令或代码,并在出现问题时发出警告。 换句话说,这是一种保护交易员及其资金免受任何不当情况影响的保护技术。 

          //+------------------------------------------------------------------+
          //|                                                         TEST.mq5 |
          //|                                  Copyright 2022, MetaQuotes Ltd. |
          //|                                             https://www.mql5.com |
          //+------------------------------------------------------------------+
          #property copyright "Copyright 2022, MetaQuotes Ltd."
          #property link      "https://www.mql5.com"
          #property version   "1.00"
          #property script_show_inputs
          #include <Trade\Trade.mqh>
          CTrade trade;
          //+------------------------------------------------------------------+
          //| Script program start function                                    |
          //+------------------------------------------------------------------+
          input int TakeProfit = 150;
          input int StopLoss = 100;
          
          void OnStart()
            {
             double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
             double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
             double Balance = AccountInfoDouble(ACCOUNT_BALANCE);
             double Equity = AccountInfoDouble(ACCOUNT_EQUITY); 
             double TakeProfitLevel = (Ask+TakeProfit*0.00001);
             double StopLossLevel = (Ask-StopLoss*0.00001);
             
             
             if(Equity >= Balance)
             trade.Buy(0.01,NULL,Ask,StopLossLevel,TakeProfitLevel,NULL);
             
                for (int i=PositionsTotal()-1; i>=0; i--)
                {
                   ulong ticket = PositionGetTicket(i);
                   ENUM_POSITION_TYPE position = ENUM_POSITION_TYPE(PositionGetInteger(POSITION_TYPE));
                  
                 if (ticket <= 0)
                  {
                   Alert("Error!");  //in Case of error and the order did not open, appears "Error!"
             
                  }
                else
                  {
                   Alert("Your ticket # is: " + string(ticket));
                   Alert("TakeProfit = ", TakeProfitLevel);
                   Alert("StopLoss = ", StopLossLevel);
                  }
                }
            }
          //+------------------------------------------------------------------+
          

          26- 错误编程技术 1


          27- 错误编程技术 2


          平单

          在本部分中,我们将创建开单和平单的代码,来了解如何平单。
          //+------------------------------------------------------------------+
          //|                                                         TEST.mq5 |
          //|                                  Copyright 2022, MetaQuotes Ltd. |
          //|                                             https://www.mql5.com |
          //+------------------------------------------------------------------+
          #property copyright "Copyright 2022, MetaQuotes Ltd."
          #property link      "https://www.mql5.com"
          #property version   "1.00"
          #property script_show_inputs
          #include <Trade\Trade.mqh>
          CTrade trade;
          //+------------------------------------------------------------------+
          //| Script program start function                                    |
          //+------------------------------------------------------------------+
          input int TakeProfit = 150;
          input int StopLoss = 100;
          
          void OnStart()
            {
             double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
             double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
             double Balance = AccountInfoDouble(ACCOUNT_BALANCE);
             double Equity = AccountInfoDouble(ACCOUNT_EQUITY); 
             double TakeProfitLevel = (Ask+TakeProfit*0.00001);
             double StopLossLevel = (Ask-StopLoss*0.00001);
             
             
             
             trade.Buy(0.01,NULL,Ask,StopLossLevel,TakeProfitLevel,NULL);
             
             for (int i=PositionsTotal()-1; i>=0; i--)
             {
               ulong ticket = PositionGetTicket(i);
               ENUM_POSITION_TYPE position = ENUM_POSITION_TYPE(PositionGetInteger(POSITION_TYPE));
          
                
               Alert (" Order Ticket # ", ticket);
               Alert("TakeProfit = ", TakeProfitLevel);
               Alert("StopLoss = ", StopLossLevel);
               
               Sleep(2000);
               
               trade.PositionClose(ticket,-1);
               Alert("Order Closed...");
             }
          
            }
          //+------------------------------------------------------------------+


           28- 平单

          通过 OrderModify 调整订单

          在这一部分中,我们将学习如何创建有助于修改订单的代码。 它将修改之前的开单或挂单的特征。

          //+------------------------------------------------------------------+
          //|                                                         TEST.mq5 |
          //|                                  Copyright 2022, MetaQuotes Ltd. |
          //|                                             https://www.mql5.com |
          //+------------------------------------------------------------------+
          #property copyright "Copyright 2022, MetaQuotes Ltd."
          #property link      "https://www.mql5.com"
          #property version   "1.00"
          #property script_show_inputs
          #include <Trade\Trade.mqh>
          CTrade trade;
          //+------------------------------------------------------------------+
          //| Script program start function                                    |
          //+------------------------------------------------------------------+
          input int TakeProfit = 150;
          input int StopLoss = 100;
          
          void OnStart()
            {
             double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
             double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
             double Balance = AccountInfoDouble(ACCOUNT_BALANCE);
             double Equity = AccountInfoDouble(ACCOUNT_EQUITY); 
             double TakeProfitLevel = (Ask+TakeProfit*0.00001);
             double StopLossLevel = (Ask-StopLoss*0.00001);
             double TakeProfitLevel2 = (TakeProfitLevel+0.00100);
             double StopLossLevel2 = (StopLossLevel-0.00050);   
             
             
             trade.Buy(0.01,NULL,Ask,StopLossLevel,TakeProfitLevel,NULL);
             
             for (int i=PositionsTotal()-1; i>=0; i--)
             {
               ulong ticket = PositionGetTicket(i);
               ENUM_POSITION_TYPE position = ENUM_POSITION_TYPE(PositionGetInteger(POSITION_TYPE));
          
                
               Alert (" Order Ticket # ", ticket);
               Alert("TakeProfit = ", TakeProfitLevel);
               Alert("StopLoss = ", StopLossLevel);
               
               Sleep(5000);
               
               trade.PositionModify(ticket,StopLossLevel2,TakeProfitLevel2);
               Alert("Order Modified...");
               Alert("Modified TakeProfit = ", TakeProfitLevel2);
               Alert("Modified StopLoss = ", StopLossLevel2);
             }
          
            }
          //+------------------------------------------------------------------+
          

          29- 修改订单



          两条简单移动平均线交叉系统

          在这一部分中,我们将把所有内容糅合到一起,编写两条简单移动平均线交叉。 按照上述所有蓝图完成所需的一切工作。

          在此,我们单击 MetaEditor中 的新建启动新项目,并选择智能交易系统。

          为了记住一切,以下是我们详细的交易系统蓝图:

          16- Simple 2MA-Blueprint-–-MQL5


          我们现在需要做的是编码实现这个策略:
          • 如果较短周期的简单移动平均线(其周期为 20)上穿较长周期的简单移动平均线 (其周期为 50),则信号为买入。
          • 如果较短周期的简单移动平均线(其周期为 20)下穿较长周期的简单移动平均线(其周期为 50),则信号为卖出。
          下面是这个程序的代码,以及如何执行它。
          //+------------------------------------------------------------------+
          //|                                                SMA crossover.mq5 |
          //|                                  Copyright 2022, MetaQuotes Ltd. |
          //|                                             https://www.mql5.com |
          //+------------------------------------------------------------------+
          #property copyright "Copyright 2022, MetaQuotes Ltd."
          #property link      "https://www.mql5.com"
          #property version   "1.00"
          //+------------------------------------------------------------------+
          //| Expert tick function                                             |
          //+------------------------------------------------------------------+
          
          void OnTick()
            {
             //create an array for several prices
             double myMovingAverageArray1[], myMovingAverageArray2[];
             
             //define the properties of  MAs - simple MA, 1st 20 / 2nd 50
             int movingAverage1 = iMA(_Symbol, _Period, 20, 0, MODE_SMA, PRICE_CLOSE);
             int movingAverage2 = iMA(_Symbol,_Period,50,0,MODE_SMA,PRICE_CLOSE);
             
             //sort the price arrays 1, 2 from current candle
             ArraySetAsSeries(myMovingAverageArray1,true);
             ArraySetAsSeries(myMovingAverageArray2,true);
             
             //Defined MA1, MA2 - one line - currentcandle, 3 candles - store result
             CopyBuffer(movingAverage1,0,0,3,myMovingAverageArray1);
             CopyBuffer(movingAverage2,0,0,3,myMovingAverageArray2);
             
             //Check if we have a buy entry signal
             if (
                (myMovingAverageArray1[0]>myMovingAverageArray2[0])
             && (myMovingAverageArray1[1]<myMovingAverageArray2[1])
                )
                   {
                   Comment("BUY");
                   }
              
             //check if we have a sell entry signal      
             if (
                (myMovingAverageArray1[0]<myMovingAverageArray2[0])
             && (myMovingAverageArray1[1]>myMovingAverageArray2[1])
                )
                   {
                   Comment("SELL");
                   }          
            }
          //+------------------------------------------------------------------+
          


          执行程序后,它会根据此策略在图表上显示带有当前信号(买入或卖出)的注释。 如下图所示:


          30- SMA - 注释


           31- SMA - 卖出注释

          下面的图片将解释我们如何从终端找到我们设计的系统,以及如何执行它:

          32- 简单 MA 程序位置

          拖放或双击程序后,将弹出以下窗口:

          33- 简单 MA 程序界面

          启用“允许算法交易”选项,然后单击“确定”。 之后,智能交易系统将被附加到图表上,并在成功加载时在日志选项卡中显示一条消息:


           34- 简单 MA 程序实现1


          35- 简单 MA 程序实现2

          如此,我们创建并执行了自动判断两条简单移动平均值交叉的程序。 我想在这里提到的是,这是一个简单的例子,我们可以为我们的交易编码。 然而,我们可以用这个强大的 MQL5 工具针对任何其它交易策略进行编码和自动化。

          同样,本文的主要目标不是使用这种策略,而是学习 MQL5 的一些基础知识,了解我们如何基于自己的想象进行创造,我们可以做什么,从而令我们的交易更容易和有利可图。 故此,如果您打算使用它,这个策略需要很多改进,这也是您唯一的责任。


          结束语

          MQL5 是一款优秀的工具,通过设计良好且盈利的算法交易系统,能帮助我们,令交易变得更容易和有利可图。 因此,您在学习和使用这一伟大工具上的投入,将是一项回报非常丰厚的投资。

          本文由MetaQuotes Ltd译自英文
          原文地址: https://www.mql5.com/en/articles/10293

          DoEasy 函数库中的图形(第九十三部分):准备创建复合图形对象的功能 DoEasy 函数库中的图形(第九十三部分):准备创建复合图形对象的功能
          在本文中,我将着手开发用于创建复合图形对象的功能。 该函数库将支持创建复合图形对象,允许这些对象含有任意层次的连接。 我将为这些对象的后续实现准备所有必要的类。
          交易中的数学:夏普(Sharpe)和索蒂诺(Sortino)比率 交易中的数学:夏普(Sharpe)和索蒂诺(Sortino)比率
          投资回报率是投资者和萌新交易员用来分析交易绩效的最明显指标。 专业交易者会采用更可靠的工具来分析策略,比如夏普(Sharpe)比率和索蒂诺(Sortino)比率等。
          MetaTrader 5 的 WebSocket — 使用 Windows API MetaTrader 5 的 WebSocket — 使用 Windows API
          在本文中,我们将使用 WinHttp.dll 针对 MetaTrader 5 平台创建 WebSocket 客户端程序。 客户端最终将作为一个类实现,并借助 Binary.com 的 WebSocket API 进行测试。
          从市场里选择智能交易系统的正确途径 从市场里选择智能交易系统的正确途径
          在本文中,我们将研究购买智能交易系统时应该注意的一些要点。 我们还将寻求提升盈利的方法,从而明智地花钱,并从付出中获取盈利。 此外,读完本文之后,您会发现,即便使用简单免费的产品也有可能赚到钱。