下载MetaTrader 5

MQL5 Cookbook: 获取仓位属性

18 十月 2013, 09:45
Anatoli Kazharski
0
811

简介

前一篇文章:"MQL5 Cookbook: 使用不同的打印模式" 向我们展示了如何快速写一个脚本来使用三种不同模式打印所需的信息,现在让我们创建一个脚本来向用户显示所有的仓位属性。

我们需要允许用户从脚本的外部参数中选择对应的选项,如下实现:或者只取得一个(当前)交易品种的仓位属性,或者一个接一个地遍历所有交易品种的所有持仓。这一次,我们会在对话框中查看所需的信息,这非常方便,你们中的一些人可能会觉得这种方法更为有用。

写脚本

程序的开头部分和前一篇文章多少类似 (参见下面的代码)。我们从程序的属性开始,它们之后是使用#define的预定义代码,我们可以使用MQL5InfoString()函数并指定MQL5_PROGRAM_NAME常量为参数,赋值给SCRIPT_NAME变量来为脚本命名,更多有关MQL5InfoString() 函数所有可能值的信息可以在MQL5参考中找到。

我们继续看模式的枚举,如果您为每个标识符写了注释,这些注释的文本将在外部参数的下拉列表中显示。我们将实现两个选项:

  • 当前交易品种 - 只显示当前交易品种的仓位属性,还有
  • 所有交易品种 - 显示所有交易品种的仓位信息。

这里将会有一个唯一的外部参数(mode)用于选择对应的模式。外部参数之后的注释也会在外部参数窗口上显示出来,这使我们能够创建更有含义的参数名称,同时,短一点的变量名在代码中使用更加方便。

#property copyright   "Copyright 2012, http://tol64.blogspot.com"
#property link        "http://tol64.blogspot.com"
#property description "email: hello.tol64@gmail.com"
#property version     "1.0"
#property script_show_inputs
//---
#define SCRIPT_NAME MQL5InfoString(MQL5_PROGRAM_NAME) // 脚本名称
//---
// 模式枚举
enum ENUM_SYMBOLS_MODE
  {
   CURRENT_SYMBOL =0,                     // 当前交易品种
   ALL_SYMBOLS    =1                      // 所有交易品种
  };
//---
// 输入参数
input ENUM_SYMBOLS_MODE mode=CURRENT_SYMBOL;     // 模式

代码之后是全局变量,为了使全局变量能够在脚本的任何部分都可以访问,它们应该被放置在函数之外(通常在程序的最前面)。

// 全局变量
long                 pos_magic=0;         // 幻数
string               pos_symbol="";       // 交易品种
string               pos_comment="";      // 注释
double               pos_swap=0.0;        // 库存费
double               pos_commission=0.0;  // 手续费
double               pos_price=0.0;       // 仓位的当前价格
double               pos_cprice=0.0;      // 仓位的当前价格
double               pos_profit=0.0;      // 仓位的利润/亏损
double               pos_volume=0.0;      // 仓位交易量
double               pos_sl=0.0;          // 仓位止损价位
double               pos_tp=0.0;          // 仓位获利价位
datetime             pos_time=NULL;       // 仓位建仓时间
long                 pos_id=0;            // 仓位编号
ENUM_POSITION_TYPE   pos_type=NULL;       // 仓位类型
//---

在程序的主函数中,我们只调用一个用户定义的函数,PrintPositionProperties(), 它将进行所有所需的操作:

//+------------------------------------------------------------------+
//| 主函数                                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   PrintPositionProperties();
  }

现在让我们分步看一下用户定义的PrintPositionProperties() 函数的结构。我们要先为未来工作打好基础,它非常简单,实现上看起来如下:

//+------------------------------------------------------------------+
//| 打开对话框并显示交易品种数据                            |
//+------------------------------------------------------------------+
void PrintPositionProperties()
  {
   int err=0; // 处理错误的变量
//---
// 如果您只需要获取当前交易品种的仓位属性
   if(mode==CURRENT_SYMBOL)
     {
 
     }
//---
// 如果您需要获取全部交易品种的仓位属性
   if(mode==ALL_SYMBOLS)
     {
 
     }
  }

我们只有两个分支和一个局部变量err,它用于错误处理并且在函数的开始部分声明。现在我们需要写下每个选项的用例,让我们从第一个开始,也就是"如果您只需要获取当前交易品种的仓位信息"。

它非常简单,首先,我们需要检查当前交易品种是否有持仓,这可以通过MQL5中的PositionSelect()函数实现,其唯一参数为交易品种的名称。为了传入当前交易品种的名称,我们需要使用Symbol() 函数或者已经包含当前交易品种名称的预定义变量 _Symbol。如果此交易品种已有持仓,PositionSelect() 将返回一个正值, 如果没有持仓或者出错,则会返回负值。

以下提供了涵盖详细描述的第一个选项的代码:

//---
      // 如果已有持仓,那么...
      if(PositionSelect(_Symbol))
        {
         // ...获取它的属性
         GetPositionProperties();
         //---
         // 打开对话框显示我们获得的全部数据
         MessageBox("交易品种        : "+pos_symbol+"\n"+
                    "注释      : "+pos_comment+"\n"+
                    "幻数  : "+IntegerToString(pos_magic)+"\n"+
                    "建仓价位    : "+DoubleToString(pos_price,_Digits)+"\n"+
                    "当前价位 : "+DoubleToString(pos_cprice,_Digits)+"\n"+
                    "止损价位     : "+DoubleToString(pos_sl,_Digits)+"\n"+
                    "获利价位   : "+DoubleToString(pos_tp,_Digits)+"\n"+
                    "类型          : "+PositionTypeToString(pos_type)+"\n"+
                    "交易量        : "+DoubleToString(pos_volume,2)+"\n"+
                    "手续费    : "+DoubleToString(pos_commission,2)+"\n"+
                    "库存费          : "+DoubleToString(pos_swap,2)+"\n"+
                    "利润        : "+DoubleToString(pos_profit,2)+"\n"+
                    "时间          : "+TimeToString(pos_time)+"\n"+
                    "编号    : "+IntegerToString(pos_id)+"",
                    //---
                    "消息框",MB_ICONASTERISK);
         //---
         return;
        }
      // 如果没有持仓或者出错,则报告
      else
        {
         err=GetLastError(); // 获取最后注册的错误编号
         //---
         if(err>0) // 如果有错误
           {
            // 打印相关信息
            MessageBox("当选择("+_Symbol+")仓位时出错 ("+IntegerToString(err)+")  !\n\n"+
                       "也许该交易品种没有持仓. 如果不是这种情况,请重试.",
                       "错误",
                       MB_ICONWARNING);
            //---
            return; // 退出函数
           }
        }
      //---

在以上代码中,我们可以看到两个用户定义的函数-GetPositionProperties()和 PositionTypeToString()。 因为我们必须在整个程序的不同地方获取仓位属性,我们最好建立一个独立的函数以便减少代码量以及使代码有更好的可读性。以下是这个函数的代码。请确保查阅MQL5参考来了解GetPositionProperties()函数中所使用MQL5函数和标识符的更多信息。

//+------------------------------------------------------------------+
//| 获取交易品种属性                                        |
//+------------------------------------------------------------------+
void GetPositionProperties()
  {
   pos_symbol     =PositionGetString(POSITION_SYMBOL);
   pos_comment    =PositionGetString(POSITION_COMMENT);
   pos_magic      =PositionGetInteger(POSITION_MAGIC);
   pos_price      =PositionGetDouble(POSITION_PRICE_OPEN);
   pos_cprice     =PositionGetDouble(POSITION_PRICE_CURRENT);
   pos_sl         =PositionGetDouble(POSITION_SL);
   pos_tp         =PositionGetDouble(POSITION_TP);
   pos_type       =(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
   pos_volume     =PositionGetDouble(POSITION_VOLUME);
   pos_commission =PositionGetDouble(POSITION_COMMISSION);
   pos_swap       =PositionGetDouble(POSITION_SWAP);
   pos_profit     =PositionGetDouble(POSITION_PROFIT);
   pos_time       =(datetime)PositionGetInteger(POSITION_TIME);
   pos_id         =PositionGetInteger(POSITION_IDENTIFIER);
  }

这个用户定义的PositionTypeToString()函数把返回的持仓类型从整数型转换为可读的字符串格式,其代码如下所示:

//+------------------------------------------------------------------+
//| 把仓位类型转换为字符串                             |
//+------------------------------------------------------------------+
string PositionTypeToString(int position_type)
  {
   string str="";
//---
   if(position_type==0) { str="买入";  }
   if(position_type==1) { str="卖出"; }
//---
   return(str);
  }

这样,第一个选项,即我们仅查看当前交易品种仓位属性的代码已经完成了。如果您按照文章描述的所有步骤做下来,它甚至可以马上测试了。使用标准工具在MetaTrader 5中建立一个仓位,为了这个目标, 按下F9 键打开订单窗口,在那里你可以在仓位建立之前看到所有必要的选项来设置仓位属性:

图 1. MetaTrader 5客户终端中的订单窗口.

图 1. MetaTrader 5客户终端中的订单窗口.

当所有属性设置完成,选择卖出或者买入,然后双击脚本或者把它拖到图表上来运行脚本,脚本窗口将会打开,模式参数的所需值 (当前交易品种)已经被默认填好了,点击“确定”按钮将会打开一个对话框,显示当前交易品种的所有仓位属性:

图 2. 显示当前交易品种仓位属性的对话框.

图 2. 显示当前交易品种仓位属性的对话框.

另一方面,假如当前交易品种没有持仓,会出现一个提醒对话框:

图 3. 提醒对话框.

图 3. 提醒对话框.

一切都和计划中一样工作正常,和我们代码中所实现的一样。

让我们回顾一下那些选择查看所有交易品种仓位属性要用到的程序代码,代码和详细的注释如下:

//---
      int digits=0; // 小数位数
      int mb_res=-1; // 对话框中选择选项的变量
      int pos_total=PositionsTotal(); // 终端中的持仓个数
      //---
      // 在循环中挨个查看所有仓位的属性
      for(int i=0; i<pos_total; i++)
        {
         ResetLastError(); // 重设最后的错误
         //---
         pos_symbol=PositionGetSymbol(i); // 读取交易品种名称
         digits=(int)SymbolInfoInteger(pos_symbol,SYMBOL_DIGITS); // 取得价格的小数位数
         //---
         // 如果这个交易品种有持仓,那么...
         if(PositionSelect(pos_symbol))
           {
            // ...获取它的属性
            GetPositionProperties();
            //---
            // 打开一个对话框显示所有获得的仓位属性
            mb_res=MessageBox("全部/当前持仓: "+IntegerToString(pos_total)+"/"+IntegerToString(i+1)+"\n"+
                              "---------------------------------\n"+
                              "交易品种: "        +pos_symbol+"\n"+
                              "注释: "       +pos_comment+"\n"+
                              "幻数: "  +IntegerToString(pos_magic)+"\n"+
                              "建仓价位: "    +DoubleToString(pos_price,digits)+"\n"+
                              "当前价位: " +DoubleToString(pos_cprice,digits)+"\n"+
                              "止损价位: "     +DoubleToString(pos_sl,digits)+"\n"+
                              "获利价位: "   +DoubleToString(pos_tp,digits)+"\n"+
                              "类型: "          +PositionTypeToString(pos_type)+"\n"+
                              "交易量: "        +DoubleToString(pos_volume,2)+"\n"+
                              "手续费: "    +DoubleToString(pos_commission,2)+"\n"+
                              "库存费: "          +DoubleToString(pos_swap,2)+"\n"+
                              "利润: "        +DoubleToString(pos_profit,2)+"\n"+
                              "时间: "          +TimeToString(pos_time)+"\n"+
                              "编号: "    +IntegerToString(pos_id)+"",
                              //---
                              "消息框",MB_CANCELTRYCONTINUE|MB_ICONASTERISK);
            //---
            if(mb_res==IDCANCEL) // 如果您点击了取消或者关闭
              { Print("程序 ("+SCRIPT_NAME+") 被用户终止!"); return; } // 退出函数
            //---
            // 如果您点击了重试   
            if(mb_res==IDTRYAGAIN) { i--; } // 重设计数器并重试
           }
         else // 如果没有持仓或者出错,则报告
           {
            err=GetLastError(); // 获取最后注册的错误编号
            //---
            if(err>0) // 如果有错误
              {
               // 打印相关信息
               MessageBox("错误 ("+IntegerToString(err)+") 当选择仓位 ("+pos_symbol+") !\n\n"+
                          "也许该交易品种没有持仓. 如果不是这种情况,请重试.",
                          "错误",
                          MB_ICONWARNING);
              }
           }
        }
      //---

现在我们只需要测试这个选项,让我们在两个交易品种上建立仓位,(比如AUDUSD和 EURUSD)。当我们运行脚本的时候,在外部参数下拉列表中选择所有交易品种模式并点击确定, 一个对话框会如下显示:

Fig. 4. 显示第二个选项仓位属性的对话框

Fig. 4. 显示第二个选项仓位属性的对话框

结论

您可以在上图中看到,对话框有三个按钮,如果您点击了重试,循环计数器会被重设,当前显示在对话框中的交易品种仓位属性会被刷新;如果您点击了继续,程序会处理下一个交易品种;取消按钮用于终止程序。

请注意,仓位属性以上的第一行包含持仓总数信息(仓位总数)和仓位计数器的当前编号(当前)。

就是这样,请随意下载附件中的源代码,它们需要在MetaQuotes语言编辑器中编译。

本文译自 MetaQuotes Software Corp. 撰写的俄文原文
原文地址: https://www.mql5.com/ru/articles/639

附加的文件 |
MQL5 Cookbook: 使用不同的打印模式 MQL5 Cookbook: 使用不同的打印模式

这是 MQL5 Cookbook 系列的第一篇文章,我将会从简单的实例开始,让那些刚刚开始编程的人逐渐熟悉这门新语言。我还记得我开始设计和编写交易系统时的尝试,可以说是非常困难,事实上那是我所学的第一门编程语言,然而,后来还是比我想象的简单一些,我只用了几个月的时间就能够开发相对复杂的程序了。

在 MQL5 中使用 WinInet。第二部分:POST 请求和文件 在 MQL5 中使用 WinInet。第二部分:POST 请求和文件

在本文中,我们将继续学习使用 HTTP 请求处理互联网和与服务器进行信息交换的原则。它介绍了 CMqlNet 类的新函数、从表单发送信息的方法、使用 POST 请求发送文件的方法以及使用 Cookie 在您登录网站时进行身份验证。

MQL5 Cookbook: 自定义信息面板上的仓位属性 MQL5 Cookbook: 自定义信息面板上的仓位属性

这一次我们创建一个简单的EA交易,它可以取得当前交易品种的仓位属性并且在人工交易的时候在自定义信息面板上显示它们。信息面板将使用图形对象创建,显示的信息在每当有订单时都会刷新,这将比系列文章的前一篇 - "MQL5 Cookbook: 获取仓位属性"中提到的每次必须人工运行脚本要方便得多。

MQL5 Cookbook: 在MetaTrader 5策略测试器中分析仓位属性 MQL5 Cookbook: 在MetaTrader 5策略测试器中分析仓位属性

我们将会展示一个来自前一篇文章,"MQL5 Cookbook: 自定义信息面板上的仓位属性"的修改版的EA交易。我们将会解决一些问题,包括从柱中获得数据,在当前交易品种中检查新柱事件,在文件中包含标准库中的交易类,创建一个函数来搜索交易信号,还有一个执行交易操作的函数以及在OnTrade()函数中判断交易事件。