第五章 普通函数

这里列出了不包含在任何专门分组中的普通函数。

函数 命令
Alert 在独立窗口中显示消息(弹窗式报警)
CheckPointer 返回对象指针的类型
Comment 在图表左上角显示注解文本
CryptEncode 将数据从 数组 转换为指定的 方法
CryptDecode 执行来自 数组 的数据的逆变换
DebugBreak 程序断点调试
ExpertRemove 停止 EA交易程序 并从图表中卸载
GetPointer 返回对象 指针
GetTickCount 返回系统启动后经过的毫秒数
GetMicrosecondCount 返回MQL5程序启动后经过微秒数
MessageBox 创建,显示消息盒子,然后管理(弹窗式消息)
PeriodSeconds 在周期中返回秒数
PlaySound 播放一个音频文件
Print 在日志中显示一则消息
PrintFormat 在日志文件中按照预先设定的格式,组织并打印一则字符串和变量的值组成的消息
ResetLastError 设置 预定义变量 _LastError的值 为 0
ResourceCreate 创建基于数据集的图像资源
ResourceFree 删除 动态创建资源 (释放分配的内存)
ResourceReadImage 读取由ResourceCreate()函数创建的,或在编译期间保存在EX5文件中的图形资源的数据
ResourceSave 将资源保存在指定文件
SetUserError 将预定义变量 _LastError 设置为等于 ERR_USER_ERROR_FIRST + user_error 的值
SetReturnError 设置完成操作时返回程序端进程的代码
SendFTP 按”选项”设置窗口中“FTP”标签中指定的地址发送一个文件
SendMail 按”选项”设置窗口中“电邮”标签中指定的地址发送一个邮件
SendNotification 按”选项”设置窗口中“通知”标签中指定的 MetaQuotes ID 推送一个短消息
Sleep 在指定的间隔内暂停当前EA程序 或 脚本 的执行。
TerminalClose 命令客户端完成操作
TesterStatistics 返回基于测试结果计算的指定统计量的值
TesterWithdrawal 在测试过程中模拟出金操作
TranslateKey 考虑当前输入语言 和 控制键状态 的虚拟按键编码,返回对应的Unicode字符。
ZeroMemory 重新设置通过引用传递给它的变量。除了具有构造函数的 类 和结构 之外,变量可以是任何类型的。

# 5.1 Alert

在独立窗口中显示消息(弹窗式报警)
    void  Alert(
   argument,     // 第一值
   ...           // 其他值
   );
1
2
3
4
5

参数

argument

[in] 用逗号分隔的任何值。为了将信息输出分成几行,您可以使用“\n”或“\r\n”转义符。参数的数量不能超过64个。

返回值

没有返回值。

注意

数组不能作为参数传递给Alert() 函数,应该将数组的 元素 作为参数传递给Alert() 函数。双精度类型的数据可以输出小数点后8位,浮点类型的数据可以输出小数点后5位。要以不同的精度或以科学计数法的格式输出实际的数字,请使用DoubleToString()函数。

布尔类型的数据输出为“true”或“false”字符串。日期的输出是YYYY.MM.DD HH:MI:SS格式。要以另一种格式显示日期,请使用TimeToString()函数。颜色类型的数据如果是在一个颜色集合中,输出时要么是一个R,G,B字符串,要么是一个颜色名称。

Alert() 函数在策略测试器中不工作。

# 5.2 CheckPointer

函数返回对象指针的类型。

ENUM_POINTER_TYPE  CheckPointer(
   object* anyobject      // 对象指针
   );
1
2
3

参数

anyobject

[in] 对象指针

返回值

从 ENUM_POINTER_TYPE 枚举中返回值。

注意

使用错误的指针,会导致终端运行时错误,直接终止程序。这就是为什么需要在使用指针之前调用CheckPointer函数。在下列情况下,指针可能不正确: • 指针等于 NULL; • 对象已被 delete 操作删除;

这个函数可以用来检查 指针 的有效性。一个非零值保证,该指针可用于访问。

示例:

//+------------------------------------------------------------------+
//| 通过删除元素来删除列表                                              |
//+------------------------------------------------------------------+
void CMyList::Destroy()
  {
//--- 循环工作服务指针
   CItem* item;
//--- 循环检测并删除动态指针
   while(CheckPointer(m_items)!=POINTER_INVALID)
     {
      item=m_items;
      m_items=m_items.Next();
      if(CheckPointer(item)==POINTER_DYNAMIC)
        {
         Print("Dynamic object ",item.Identifier()," to be deleted");
         delete (item);
        }
      else Print("Non-dynamic object ",item.Identifier()," cannot be deleted");
     }
//---
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

相关参考 对象指针 ,检测对象指针 , 对象删除操作符的删除

# 5.3 Comment

在图表左上角显示注解文本

void  Comment(
   argument,     // 第一值
   ...           // 下一值
   );
1
2
3
4

参数

...

[in]用逗号分隔的任何值。为了将信息输出分成几行,您可以使用“\n”或“\r\n”转义符。参数的数量不能超过64个。输入的注解文本(包括隐形的字符)的总长度不能超过2045个字节(在输出过程中超出的字符会被删去)

返回值

没有返回值

注意

数组不能作为参数传递给Comment()函数,数组必须按一个接一个的元素传递给Comment()函数。

双精度类型的数据,精确度保留到小数点后16位,以 传统 或 科学计数法 的方式输出,取决于什么 方式 更紧凑。浮点型数据保留小数点后5位,要用另一个精度 或 预定义格式输出实际数字,请使用DoubleToString()函数。

布尔类型的数据输出为“true”或“false”字符串。日期的输出是YYYY.MM.DD HH:MI:SS格式。要以另一种格式显示日期,请使用TimeToString()函数。颜色类型的数据如果是在一个颜色集合中,输出时要么是一个R,G,B字符串,要么是一个颜色名称。

示例:

void OnTick()
  {
//---
   double Ask,Bid;
   int Spread;
   Ask=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
   Bid=SymbolInfoDouble(Symbol(),SYMBOL_BID);
   Spread=SymbolInfoInteger(Symbol(),SYMBOL_SPREAD);
//--- 3行输出值
   Comment(StringFormat("Show prices\nAsk = %G\nBid = %G\nSpread = %d",Ask,Bid,Spread));
  }
1
2
3
4
5
6
7
8
9
10
11

相关参考 ChartSetString , ChartGetString

# 5.4 CryptEncode

通过指定的 方法 转换来自数组的数据。

int  CryptEncode(
   ENUM_CRYPT_METHOD   method,        // 方法
   const uchar&        data[],        // 源数组
   const uchar&        key[],         // 密钥
   uchar&              result[]       // 目标数组
   );

1
2
3
4
5
6
7

参数

method

[in] 数据转换方法。取值范围是ENUM_CRYPT_METHOD 枚举值之一。

data[]

[in] 源数组。

key[]

[in] 密钥数组。

result[]

[out] 目标数组。

返回值

返回目标数组的字节数,如果发生错误则返回0。若要获得有关错误的信息,可以调用 GetLastError() 函数。

例如:

//+------------------------------------------------------------------+
//| ArrayToHex                                                       |
//+------------------------------------------------------------------+
string ArrayToHex(uchar &arr[],int count=-1)
  {
   string res="";
//--- 检查
   if(count<0 || count>ArraySize(arr))
      count=ArraySize(arr);
//--- 转换到 HEX 字符串
   for(int i=0; i<count; i++)
      res+=StringFormat("%.2X",arr[i]);
//---
   return(res);
  }
//+------------------------------------------------------------------+
//| 脚本程序起始函数                                                   |
//+------------------------------------------------------------------+
void OnStart()
  {
   string text="The quick brown fox jumps over the lazy dog";
   string keystr="ABCDEFG";
   uchar src[],dst[],key[];
//--- 准备密钥
   StringToCharArray(keystr,key);
//--- 复制文本到源数组src[]
   StringToCharArray(text,src);
//--- 打印初始数据
   PrintFormat("Initial data: size=%d, string='%s'",ArraySize(src),CharArrayToString(src));
//--- 用key[]的DES56位密钥加密DES src[]
   int res=CryptEncode(CRYPT_DES,src,key,dst);
//--- 检查错误
   if(res>0)
     {
      //--- 打印加密数据
      PrintFormat("Encoded data: size=%d %s",res,ArrayToHex(dst));
      //--- 解码 dst[] 到 src[]
      res=CryptDecode(CRYPT_DES,dst,key,src);
      //--- 检查错误
      if(res>0)
        {
         //--- 打印解码数据
         PrintFormat("Decoded data: size=%d, string='%s'",ArraySize(src),CharArrayToString(src));
        }
      else
         Print("Error in CryptDecode. Error code=",GetLastError());
     }
   else
      Print("Error in CryptEncode. Error code=",GetLastError());
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

相关参考 数组函数, CryptDecode()

# 5.5 CryptDecode

执行数组数据逆转换,通过CryptEncode()转换。

int  CryptEncode(
   ENUM_CRYPT_METHOD   method,        // 方法
   const uchar&        data[],        // 源数组
   const uchar&        key[],         // 密钥
   uchar&              result[]       // 目标数组
   );
1
2
3
4
5
6

参数

method

[in] 数据转换方法。取值范围是ENUM_CRYPT_METHOD 枚举值之一。

data[]

[in] 源数组。

key[]

[in] 密钥数组。

result[]

[out] 目标数组。

返回值

返回目标数组的字节数,如果发生错误则返回0。若要获得有关错误的信息,可以调用 GetLastError() 函数。

相关参考 数组函数,CryptEncode()

# 5.6 DebugBreak

在排除故障中的程序断点。

void  DebugBreak();
1

返回值

没有返回值。

注意

只有在调试模式下启动程序时,才会中断MQL5程序的执行。该函数可用于查看变量值 和/或 进一步逐步执行。

# 5.7 ExpertRemove

此函数将停止 EA交易程序 并 从图表中卸载。

void  ExpertRemove();
1

返回值

没有返回值。

注意

一旦调用ExpertRemove()函数,EA交易不会立即停止,只是设立一个停止EA操作的标帜,之后不能处理任何事件,然后调用 OnDeinit() ,EA交易程序就会卸载并且从图表中删除。

示例:

//+------------------------------------------------------------------+
//|                                            Test_ExpertRemove.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
input int ticks_to_close=20;//  EA 卸载前的跳价编号
//+------------------------------------------------------------------+
//| EA反初始化函数                                                     |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   Print(TimeCurrent(),": " ,__FUNCTION__," reason code = ",reason);
//--- "清除" 注释
   Comment("");
//---
  }
//+------------------------------------------------------------------+
//| EA跳价编号函数                                                     |
//+------------------------------------------------------------------+
void OnTick()
  {
   static int tick_counter=0;
//---
   tick_counter++;
   Comment("\nBefore unloading expert advisor ",__FILE__," left",
           (ticks_to_close-tick_counter)," ticks");
//--- 以前
   if(tick_counter>=ticks_to_close)
     {
      ExpertRemove();
      Print(TimeCurrent(),": ",__FUNCTION__," expert advisor will be unloaded");
     }
   Print("tick_counter =",tick_counter);
//---
  }
//+------------------------------------------------------------------+

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

相关参考 程序运行 , 客户端事件

# 5.8 GetPointer

此函数返回对象指针。

void*  GetPointer(
   any_class anyobject      // 任何类的对象
   );
1
2
3

参数

anyobject

[in] 任何 类 的对象。

返回值

函数返回对象指针

注意

只有 类 对象有指针。结构的实例 和 简单类型的变量没有指针。类 对象不是使用new()操作符创建的,但是,例如,在对象数组中自动创建的 对象,仍然有一个指针。但是这个指针将是自动类型的POINTER_AUTOMATIC,因此delete()操作符不能应用于它。除此之外,类型指针与POINTER_AUTOMATIC类型的动态指针没有区别。

由于结构类型和简单类型的变量没有指针,所以禁止将GetPointer()函数应用到它们。也禁止将指针作为函数参数传递。在这些情况下,编译器都会通知错误。

试图调用不正确的指针会导致程序的运行时错误并直接终止。这就是为什么在使用指针之前应该调用CheckPointer()函数来检查一下。在下列情况下,指针可能不正确:

• 指针等于 NULL ; • 对象已被 delete 操作删除;

这个函数可以用来检查 指针 的有效性。一个非零值保证,该指针可用于访问

示例:

//+------------------------------------------------------------------+
//|                                             Check_GetPointer.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

//+------------------------------------------------------------------+
//| 执行列表元素的类                                                   |
//+------------------------------------------------------------------+
class CItem
  {
   int               m_id;
   string            m_comment;
   CItem*            m_next;
public:
                     CItem() { m_id=0; m_comment=NULL; m_next=NULL; }
                    ~CItem() { Print("Destructor of ",m_id,
                                     (CheckPointer(GetPointer(this))==POINTER_DYNAMIC)?
                                     "dynamic":"non-dynamic"); }
   void              Initialize(int id,string comm) { m_id=id; m_comment=comm; }
   void              PrintMe() { Print(__FUNCTION__,":",m_id,m_comment); }
   int               Identifier() { return(m_id); }
   CItem*            Next() {return(m_next); }
   void              Next(CItem *item) { m_next=item; }
  };
//+------------------------------------------------------------------+
//| 列表中最简单的类                                                   |
//+------------------------------------------------------------------+
class CMyList
  {
   CItem*            m_items;
public:
                     CMyList() { m_items=NULL; }
                    ~CMyList() { Destroy(); }
    bool             InsertToBegin(CItem* item);
    void             Destroy();
  };
//+------------------------------------------------------------------+
//| 从开始嵌入列表元素                                                  |
//+------------------------------------------------------------------+
bool CMyList::InsertToBegin(CItem* item)
  {
   if(CheckPointer(item)==POINTER_INVALID) return(false);
//---
   item.Next(m_items);
   m_items=item;
//---
   return(true);
  }
//+------------------------------------------------------------------+
//| 通过删除元素删除列表                                                |
//+------------------------------------------------------------------+
void CMyList::Destroy()
  {
//--- 循环工作服务指针
   CItem* item;
//--- 循环检测并删除动态指针
   while(CheckPointer(m_items)!=POINTER_INVALID)
     {
      item=m_items;
      m_items=m_items.Next();
      if(CheckPointer(item)==POINTER_DYNAMIC)
        {
         Print("Dynamyc object ",item.Identifier()," to be deleted");
         delete (item);
        }
      else Print("Non-dynamic object ",item.Identifier()," cannot be deleted");
     }
//---
  }
//+------------------------------------------------------------------+
//| 脚本程序启动函数                                                   |
//+------------------------------------------------------------------+
void OnStart()
  {
   CMyList list;
   CItem   items[10];
   CItem*  item;
//--- 创建并加入一个动态对象指针到列表
   item=new CItem;
   if(item!=NULL)
     {
      item.Initialize(100,"dynamic");
      item.PrintMe();
      list.InsertToBegin(item);
     }
//--- 添加自动指针到列表
   for(int i=0; i<10; i++)
     {
      items[i].Initialize(i,"automatic");
      items[i].PrintMe();
      item=GetPointer(items[i]);
      if(CheckPointer(item)!=POINTER_INVALID)
         list.InsertToBegin(item);
     }
//--- 在列表开始添加一个以上动态对象指针
   item=new CItem;
   if(item!=NULL)
     {
      item.Initialize(200,"dynamic");
      item.PrintMe();
      list.InsertToBegin(item);
     }
//--- 删除所有列表元素
   list.Destroy();
//--- 脚本结束后所有列表元素都被删除
//--- 在客户端查看 (专家)EA 标签
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

相关参考 对象指针 , 检测对象指针 ,对象删除操作符的删除

# 5.9 GetTickCount

自从程序开始以来,GetTickCount()函数返回已过去的毫秒数。

uint  GetTickCount();
1

返回值

无符号整型值

注意

计数器受系统定时器的限制。时间被存储为无符号整数,因此,如果一台计算机不间断地工作,那么每49.7天就会被填满。

例如:

#define MAX_SIZE 40
//+------------------------------------------------------------------+
//| 测量40个裴波那契数列计算时间的脚本                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- 记住初始值
   uint start=GetTickCount();
//--- 在裴波那契数列获得下一个数列的变量
   long fib=0;
//--- 循环计算来自裴波那契数列的指定数列量
   for(int i=0;i<MAX_SIZE;i++) fib=TestFibo(i);
//--- 获取毫秒为单位的所用时间
   uint time=GetTickCount()-start;
//--- 导出信息到专家日志
   PrintFormat("Calculating %d first Fibonacci numbers took %d ms",MAX_SIZE,time);
//--- 已完成脚本
   return;
  }
//+------------------------------------------------------------------+
//| 通过数列号获得裴波那契数列的函数                                      |
//+------------------------------------------------------------------+
long TestFibo(long n)
  {
//--- 裴波那契数列的第一个成员
   if(n<2) return(1);
//--- 所有其他成员通过以下公式计算
   return(TestFibo(n-2)+TestFibo(n-1));
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

相关参考 日期和时间

# 5.10 GetMicrosecondCount

自从程序开始以来,GetMicrosecondCount()函数返回已过去的微秒数。

ulong  GetMicrosecondCount();
1

返回值

无符号长整型的值。

示例:

//+------------------------------------------------------------------+
//| 测试函数                                                          |
//+------------------------------------------------------------------+
void Test()
  {
   int    res_int=0;
   double res_double=0;
//---
   for(int i=0;i<10000;i++)
     {
      res_int+=i*i;
      res_int++;
      res_double+=i*i;
      res_double++;
     }
  }
//+------------------------------------------------------------------+
//| 脚本程序开始函数                                                   |
//+------------------------------------------------------------------+
void OnStart()
  {
   uint   ui=0,ui_max=0,ui_min=INT_MAX;
   ulong  ul=0,ul_max=0,ul_min=INT_MAX;
//--- 测量次数
   for(int count=0;count < 1000;count++)
     {
      uint  ui_res=0;
      ulong ul_res=0;
      //---
      for(int n=0;n<2;n++)
        {
         //--- 选择测量类型
         if(n==0) ui=GetTickCount();
         else     ul=GetMicrosecondCount();
         //--- 执行代码
         Test();
         //--- 添加测量结果 (根据类型)
         if(n==0) ui_res+=GetTickCount()-ui;
         else     ul_res+=GetMicrosecondCount()-ul;
        }
      //--- 为两个测量计算最小和最大的时间值
      if(ui_min>ui_res) ui_min=ui_res;
      if(ui_max<ui_res) ui_max=ui_res;
      if(ul_min>ul_res) ul_min=ul_res;
      if(ul_max<ul_res) ul_max=ul_res;
     }
//---
   Print("GetTickCount error(msec): ",ui_max-ui_min);
   Print("GetMicrosecondCount error(msec): ",DoubleToString((ul_max-ul_min)/1000.0,2));
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

# 5.11 MessageBox

此函数创建并显示一个对话框,并管理它。一个对话框可以包括信息和标题,任何组合的预定义的标签和命令按钮。

int  MessageBox(
   string  text,             // 信息文本
   string  caption=NULL,     // 对话框表头
   int     flags=0           // 对话框按键设置
   );
1
2
3
4
5

参数

text

[in] 文本,包括信息输出。

caption=NULL

[in] 此项为可选项,显示标题文本。如果参数是空的,那么EA程序的名称将显示在标题中。

flags=0

[in] 此项为可选项,定义消息框的外观和行为。标帜可以指定一组标帜的组合。

返回值

如果函数成功执行,返回值是MessageBox()返回代码的枚举值常量之一。

注意

不建议在定制指示器中使用该函数,因为在等待用户响应时,对MessageBox()的调用会在整个过程中暂停指标的执行线程。由于每个交易品种的所有指标都在一个线程中执行,所以这个交易品种的所有时间框架的所有图表都将会被暂停。

MessageBox()函数在策略测试中不工作。

# 5.12 PeriodSeconds

此函数返回一个时间框架的秒数。

int  PeriodSeconds(
   ENUM_TIMEFRAMES  period=PERIOD_CURRENT      // 图表周期
   );
1
2
3

参数

period=PERIOD_CURRENT

[in] 枚举值ENUM_TIMEFRAMES中的图表周期值,如果参数未标明,在程序运行中,返回当前图表时间框架周期的秒数。

返回值

所选周期中的秒数。

相关参考

_Period, 图表时间表 , 日期和时间 , 对象可见性

# 5.13 PlaySound

播放声音文件。

bool  PlaySound(
   string  filename      // 文件名
   );
1
2
3

参量

filename

[in] 声音文件的路径。 如果 filename=NULL,停止回放。

返回值

true —— 如果发现文件, 否则 —— false.

注意

文件加载到terminal_directory\Sounds 的子目录中,只能播放wav类型文件。

调用PlaySound()参数为 NULL 表示停止播放。

PlaySound() 函数在策略测试中不工作。

相关参考

资源

# 5.14 Print

在EA交易日志中打印输出文本消息。参数可以是任何类型。

void  Print(
   argument,     // 第一值
   ...           // 下一值
   );
1
2
3
4

参数

...

[in] 用逗号分隔的任意值,参数总数量不能超过64个。

注意

数组不能作为参数传递给Print()函数,数组必须按一个接一个的元素传递给Print()函数。

双精度类型的数据,精确度保留到小数点后16位,以 传统 或 科学计数法 的方式输出,取决于什么 方式 更紧凑。浮点型数据保留小数点后5位,要用另一个精度 或 预定义格式输出实际数字,使用 PrintFormat() 函数。

布尔类型的数据输出为“true”或“false”字符串。日期的输出是YYYY.MM.DD HH:MI:SS格式。要以另一种格式显示日期,请使用TimeToString()函数。颜色类型的数据如果是在一个颜色集合中,输出时要么是一个R,G,B字符串,要么是一个颜色名称。

Print() 函数在优化期间在策略测试中不工作。

示例:

void OnStart()
  {
//--- 用Print()导出DBL_MAX,这相当于PrintFormat(%%.16G,DBL_MAX)
   Print("---- how DBL_MAX looks like -----");
   Print("Print(DBL_MAX)=",DBL_MAX);
//--- 现在用PrintFormat()导出DBL_MAX number
   PrintFormat("PrintFormat(%%.16G,DBL_MAX)=%.16G",DBL_MAX);
//--- 导出到专家日志
// Print(DBL_MAX)=1.797693134862316e+308
// PrintFormat(%.16G,DBL_MAX)=1.797693134862316E+308

//--- 请看浮动如何导出
   float c=(float)M_PI; // 我们应该明确目标类型
   Print("c=",c, "    Pi=",M_PI, "    (float)M_PI=",(float)M_PI);
// c=3.14159    Pi=3.141592653589793    (float)M_PI=3.14159

//--- 显示真实类型算术运算会发生什么
   double a=7,b=200;
   Print("---- Before arithmetic operations");
   Print("a=",a,"   b=",b);
   Print("Print(DoubleToString(b,16))=",DoubleToString(b,16));
//--- a 除以 b (7/200)
   a=a/b;
//--- 现在模仿恢复b变量的值
   b=7.0/a; // 期待 b=7.0/(7.0/200.0)=>7.0/7.0*200.0=200 - 但却不同
//--- 导出最新计算的b值
   Print("----- After arithmetic operations");
   Print("Print(b)=",b);
   Print("Print(DoubleToString(b,16))=",DoubleToString(b,16));
//--- 导出到专家日志
// Print(b)=200.0
// Print(DoubleToString(b,16))=199.9999999999999716 (可见b不再等于200.0)

//--- 创建一个非常小的值 epsilon=1E-013
   double epsilon=1e-13;
   Print("---- Create a very small value");
   Print("epsilon=",epsilon); // 获得 epsilon=1E-013
//--- 现在从b减去epsilon 并且导出值到专家日志
   b=b-epsilon;
//--- 使用两种方式
   Print("---- After subtracting epsilon from the b variable");
   Print("Print(b)=",b);
   Print("Print(DoubleToString(b,16))=",DoubleToString(b,16));
//--- 导出到专家日志
// Print(b)=199.9999999999999  (现在减去epsilon以后的b值不能四舍五入到200)
// Print(DoubleToString(b,16))=199.9999999999998578
//    (现在减去epsilon以后的b值不能四舍五入到200)
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

相关参考 DoubleToString, StringFormat

# 5.15 PrintFormat

在EA专家日志中,按照预先设定的格式,格式化并打印输出字符串和值。

void  PrintFormat(
   string format_string,   // 格式行
   ...                     // 简单类型值
   );
1
2
3
4

参数 format_string

[in] 格式规范字符串由简单的字符组成,如果格式字符串后跟参数,它也包含格式规范。

...

[in] 简单类型的任何值用逗号分隔,参数的总数量不能超过64个,包括格式化规范的字符。

返回值

字符串。

注意

PrintFormat() 函数在策略测试器中做优化时不工作。

参数的数量,顺序和类型必须与格式化规范的修饰语明确匹配,否则打印结果无法确定。您可以使用 printf() 替代PrintFormat() 。

如果格式规范字符串后跟参数,则该字符串必须包含表示这些参数的输出格式的格式规范。格式规范总是以百分号(%)开始。

格式规范字符串是从左向右读取的。当满足第一个格式规范(如果有)时,格式化字符串之后的第一个参数的值将根据预先设置的规范进行转换和输出。第二种格式规范调用第二个参数的转换和输出,以此类推,直到格式字符串结束。

格式规格字符如下形式:

%[flags][width][.precision][{h | l | ll | I32 | I64}]type

格式规范的每个字段要么是一个简单的符号,要么是一个表示简单格式选项的数字。最简单的格式规范只包含百分比符号(%)和定义输出参数类型的符号(例如,%s)。如果需要在格式字符串中输出百分号,请使用格式规范%%。

标记(flags)

标记 描述 默认动作
- (减号) 在设置宽度内左对齐。 右对齐
+ (加号) 打印输出 值 的 + 或 - (正负)符号。 只显示负号
0 (零) 在设置宽度内的输出值前加零。如果使用整数格式指定0标记(例如,u、x、x、o、d)和精度规范(例如,%04.d),则忽略0。 什么都不添加
space 如果值是一个 符号(+-号) 和 正值。在输出之前显示一个空格。 不插入空间
# 如果与格式o、x或x一起使用,则分别在输出值0、0x或0x之前添加。 什么都不添加
如果与格式e、e、a或a一起使用,值总是以小数点显示。 如果小数部分非零,显示小数点
如果与格式g或g一起使用,标志将在输出值中定义小数点的存在,并防止前导零的切断。 当与格式c、d、i、u、s一起使用时,标记#被忽略。 如果小数部分非零,显示小数点,切断前导零

宽度
设置格式化值的最小输出符号数的非负十进制数。如果输出符号的数量小于指定的宽度,则从左边或右边添加相应数量的空格,这取决于对齐(标志)。如果有标志0(0),则在输出值之前添加相应数量的零。如果输出符号的数量大于指定的宽度,输出值就不会被切断。
如果将星号(*)指定为宽度,则必须在传递参数列表的相应位置指定int类型的值。它将用于指定输出值的宽度。
精确度
一种非负十进制数,它将输出精度设为小数点后的位数。与宽度规范不同的是,精度规范可以在不舍入的情况下将分式的部分切断。 对于不同的格式类型,使用精度规范是不同的。

类型 描述 默认动作
a, A 精度规范设置小数点后的位数 默认精确度 - 6
c, C 不使用
d, i, u, o, x, X 设置最小输出位数。如果对应的参数中位数小于这个精度,则将0添加到输出值的左边。如果输出数字大于指定的精度,输出值就不会被切断 默认精确度 - 1
e, E, f 设置小数点后的输出位数。最后一个数字被四舍五入 默认精确度-6,如果建立的精确度是0或者小数部分空缺,不显示小数点
g, G 设置有意义数字的最大数目 输出六位有意义数字
s, S 设置字符串的输出符号的数量。如果字符串长度超过了精度,字符串将被切断 整个线路输出

h | l | ll | I32 | I64

指定数据的大小,以参数的形式传递。

参数类型 使用前缀 类型共同说明符
int l (小写字母 L) d, i, o, x, or X
uint l (小写字母 L) o, u, x, or X
long ll (两个小写字母 L) d, i, o, x, or X
short h d, i, o, x, or X
ushort h o, u, x, or X
int I32 d, i, o, x, or X
uint I32 o, u, x, or X
long I64 d, i, o, x, or X
ulong I64 o, u, x, or X

类型 类型说明符是格式化规范输出的唯一必需字段。

符号 类型 输出格式
c int short 型字符(Unicode)
C int char型字符(ANSI)
d int 带符号(+-号)的十进制整数
i int 带符号(+-号)的十进制整数
o int 无符号(+-号)的八进制整数
u int 无符号(+-号)的十进制整数
x int 无符号(+-号)的十六进制整数,使用"abcdef"
X int 无符号(+-号)的十六进制整数,使用 "ABCDEF"
e double 格式规范一个实数[-] d.dddde[+/-符号] ddd,其中d —— 表示一个十进制数字,dddd —— 表示一个或更多的十进制数字,ddd—— 表示一个三位数,决定指数的大小,符号 —— 表示正负。
E double 与e格式相同,除了指数的符号是由大写字母输出(E代替e)
f double 格式规范一个实数[-] dddd.dddd ,这里的 dddd —— 表示一个或多个十进制数字。小数点前显示数字的数目取决于数值的大小。小数点后位数取决于所需的精度。
g double f或者e格式的输出实数值取决于输出量更紧凑
G double F或者E的输出真值取决于输出量更紧凑
a double 格式规范一个实数 [−]0xh.hhhh p±dd,这里的h.hhhh —— 表示十六进制格式的尾数,使用"abcdef",dd ——表示一个或者更多指数,小数点的位数由精度规范决定。
A double 格式规范一个实数 [−]0xh.hhhh P±dd。这里的hhhh —— 尾数以十六进制数字的形式,使用“ABCDEF”,dd ——表示一个或者更多指数,小数点的位数由精度规范决定。
s string 字符串输出

可以使用printf()取代PrintFormat()。 示例:

void OnStart()
  {
//--- 交易服务器名称
   string server=AccountInfoString(ACCOUNT_SERVER);
//--- 账号
   int login=(int)AccountInfoInteger(ACCOUNT_LOGIN);
//--- 长整型值输出
   long leverage=AccountInfoInteger(ACCOUNT_LEVERAGE);
   PrintFormat("%s %d: leverage = 1:%I64d",
               server,login,leverage);
//--- 账户货币
   string currency=AccountInfoString(ACCOUNT_CURRENCY);
//--- 小数点后两位的双精度值输出
   double equity=AccountInfoDouble(ACCOUNT_EQUITY);
   PrintFormat("%s %d: account equity = %.2f %s",
               server,login,equity,currency);
//--- +/-符号强制输出的双精度值输出
   double profit=AccountInfoDouble(ACCOUNT_PROFIT);
   PrintFormat("%s %d: current result for open positions = %+.2f %s",
               server,login,profit,currency);
//--- 小数点后可变数位的双精度值输出
   double point_value=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
   string format_string=StringFormat("%%s: point value  = %%.%df",_Digits);
   PrintFormat(format_string,_Symbol,point_value);
//--- 整型值输出
   int spread=(int)SymbolInfoInteger(_Symbol,SYMBOL_SPREAD);
   PrintFormat("%s: current spread in points = %d ",
               _Symbol,spread);
//--- 小数点后17个有意义数位的科学(浮点)格式双精度值输出
   PrintFormat("DBL_MAX = %.17e",DBL_MAX);
//--- 小数点后17个有意义数位的科学(浮点)格式双精度值输出
   PrintFormat("EMPTY_VALUE = %.17e",EMPTY_VALUE);
//--- 以默认精度使用PrintFormat()输出
   PrintFormat("PrintFormat(EMPTY_VALUE) = %e",EMPTY_VALUE);
//--- 使用Print()简单输出
   Print("Print(EMPTY_VALUE) = ",EMPTY_VALUE);
/* 执行结果
   MetaQuotes-Demo 1889998: leverage = 1:100
   MetaQuotes-Demo 1889998: account equity = 22139.86 USD
   MetaQuotes-Demo 1889998: current result for open positions = +174.00 USD
   EURUSD: point value  = 0.00001
   EURUSD: current spread in points = 12
   DBL_MAX = 1.79769313486231570e+308
   EMPTY_VALUE = 1.79769313486231570e+308
   PrintFormat(EMPTY_VALUE) = 1.797693e+308
   Print(EMPTY_VALUE) = 1.797693134862316e+308
*/
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

相关参考 StringFormat ,DoubleToString , 真实类型(双精度,浮点)

# 5.16 ResetLastError

设置预定义常量 _LastError 的值归0。

void  ResetLastError();
1

返回值

没有返回值

注意

应该注意,GetLastError()函数不会让 _LastError变量归零。通常在调用函数之前调用ResetLastError()函数,然后检查是否有错误出现。

# 5.17 ResourceCreate

基于数据设置创建图像资源。该函数有两种变量:

根据文件创建资源

bool  ResourceCreate(
   const string      resource_name,       // 资源名称
   const string      path                 // 文件的相对路径
   );
1
2
3
4

基于像素数组创建资源

bool  ResourceCreate(
   const string      resource_name,       // 资源名称
   const uint&       data[],              // 数据设置为数组
   uint              img_width,           // 图像的宽度
   uint              img_height,          // 图像的高度
   uint              data_xoffset,        // 图像左上角水平向右偏移量
   uint              data_yoffset,        // 图像左上角垂直向下偏移量
   uint              data_width,          // 基于数据设置的图像总宽度
   ENUM_COLOR_FORMAT color_format         // 颜色处理方案
   );
1
2
3
4
5
6
7
8
9
10

参数

resource_name

[in] 资源名称。

data[][]

[in] 用于创建完整图像的一维或二维数组。

img_width

[in] 矩形图像区域的宽度以图像的形式放置在资源中。它不能大于data_width值。

img_height

[in] 矩形图像区域的高度以图像的形式放置在资源中。

data_xoffset

[in] 图像的矩形区域的水平向右偏移量。

data_yoffset

[in] 图像的矩形区域的垂直向下偏移量。

data_width

[in] 只需要一维数组。它表示来自数据集的图像的全部宽度。如果data_width=0,则假定它等于img_width。对于二维数组,该参数被忽略,并假定它等于data[][]数组的第二个维度。

color_format

[in] 颜色处理方案,来自ENUM_COLOR_FORMAT 枚举值。

返回值

如果成功返回true,否则false。若要获得有关错误的信息,请调用GetLastError() 函数。可能会发生以下错误:
• 4015 —— ERR_RESOURCE_NAME_DUPLICATED (动态和静态资源的相同名称)
• 4016 —— ERR_RESOURCE_NOT_FOUND (资源没找到)
• 4017 —— ERR_RESOURCE_UNSUPPORTED_TYPE (这种类型的资源不支持)
• 4018 —— ERR_RESOURCE_NAME_IS_TOO_LONG (资源名称太长)

ENUM_COLOR_FORMAT

标识符 描述
COLOR_FORMAT_XRGB_NOALPHA 阿尔法通道的组件被忽略
COLOR_FORMAT_ARGB_RAW 客户端不处理颜色组件(用户必须正确设置)
COLOR_FORMAT_ARGB_NORMALIZE 客户端不处理颜色组件

相关参考 资源, ObjectCreate(), ObjectSetString(), OBJPROP_BMPFILE

# 5.18 ResourceFree

该函数删除动态创建的资源 (释放分配的内存)。

bool  ResourceFree(
   const string  resource_name      // 资源名称
   );
1
2
3

参数

resource_name

[in] 资源 名称应以"::"开头。

返回值

如果成功返回true,否则false。若要获得有关错误的信息,请调用GetLastError() 函数。

注意

ResourceFree() 允许mql5应用开发者们管理内存消耗。从内存删除的绑定资源的图形对象 会在删除后正确显示。然而,新创建的图形对象(OBJ_BITMAP 和 OBJ_BITMAP_LABEL) 将不能使用已删除的资源。

函数仅删除通过程序创建的动态资源。

相关参考

资源, ObjectCreate(), PlaySound(), ObjectSetString(), OBJPROP_BMPFILE

# 5.19 ResourceReadImage

函数读取来自通过ResourceCreate()函数创建的 或 编译期间保存在 EX5 文件中的图形资源的数据。

bool  ResourceReadImage(
   const string      resource_name,       // 用于读取的图形资源名称
   uint&             data[],              // 用于从资源接收数据的数组
   uint&             width,               // 用于在资源中接收图像宽度
   uint&             height,              // 用于在资源中接收图像高度
   );
1
2
3
4
5
6

参数

resource_name

[in] 包含图像的图形资源的名称。为了获得对其自身资源的访问权,该名称使用“::resourcename”的简单形式。如果我们从已编译的EX5文件中下载了一个资源,那么完整的名称应该与MQL5目录、文件和资源名称的路径一起使用—— “路径\filename.ex5::resourcename”。

data[][]

[in] 接收图形资源数据的一维或二维数组。

img_width

[out] 图形资源图像的像素宽度。

img_height

[out] 图形资源图像的像素高度。

返回值

如果成功返回true,否则false。若要获得有关错误的信息,请调用GetLastError() 函数。

注意

如果data[] 数组被用于创建图形资源, COLOR_FORMAT_ARGB_NORMALIZE 或 COLOR_FORMAT_XRGB_NOALPHA 颜色格式应该被使用。

如果data[][]数组是二维的,它的第二个维度小于X(宽度)图形资源大小,那么ResourceReadImage()函数返回false,而不执行读取。但是如果资源存在,实际的图像大小将返回到宽度和高度参数。这将允许再次尝试从资源中接收数据。

相关参考 资源, ObjectCreate(), ObjectSetString(), OBJPROP_BMPFILE

# 5.20 ResourceSave

保存资源到指定文件。

    bool  ResourceSave(
   const string  resource_name      // 资源名称
   const string  file_name          // 文件名称
   );
1
2
3
4

参数

resource_name

[in] 资源名称,必须以"::"开始。

file_name

[in] 相对于MQL5\Files文件名称。

返回值

true 表示成功,否则false。对于错误信息,可调用GetLastError()查看。

注意

该函数总是覆盖一个文件,并在必要时在文件名中创建所有必需的中间目录。

相关参考 资源, ObjectCreate(), PlaySound(), ObjectSetString(), OBJPROP_BMPFILE

# 5.21 SetReturnError

设置完成操作时返回程序端进程的代码。

void  SetReturnError(
   int ret_code      // 客户端完成代码
   );
1
2
3

参数

ret_code

[in] 完成操作时由客户端进程返回的代码。

返回值

无返回值。

注意

使用SetReturnError()函数设置指定的 ret_code返回代码有利于分析通过命令行启用程序端时程序操作完成的原因。

与TerminalClose()不同,SetReturnError()函数未完成程序端操作。相反,它只设置完成后返回程序端进程的代码。

如果SetReturnError()函数被调用多次和/或从不同的MQL5程序调用,程序端返回最后一次设置的返回代码。

除下列情况外,程序端进程完成后返回设置代码:

执行期间发生严重错误;

已调用以指定代码发行程序端操作完成命令的TerminalClose(int ret_code)函数。

另见 程序运行、运行错误、未初始化原因代码、TerminalClose

# 5.22 SetUserError

设置 预定义变量 _LastError 的值,等于 ERR_USER_ERROR_FIRST + user_error

void  SetUserError(
   ushort user_error,   // 错误代码编号
   );
1
2
3

参量

user_error

[in] 用户设置的错误代码编号。

返回值

没有返回值

注意

在使用SetUserError(user_error) 函数发生错误后, GetLastError() 返回值等于 ERR_USER_ERROR_FIRST + user_error.

示例:

void OnStart()
  {
//--- 设置错误编号 65537=(ERR_USER_ERROR_FIRST +1)
   SetUserError(1);
//--- 获得上一个错误代码
   Print("GetLastError = ",GetLastError());
/*
   Result
   GetLastError = 65537
*/
  }
1
2
3
4
5
6
7
8
9
10
11

# 5.23 Sleep

在指定的间隔内暂停当前EA程序 或 脚本 的执行。

void  Sleep(
   int  milliseconds      // 间隔
   );
1
2
3

参量

milliseconds

[in] 内部延期时间,单位:毫秒

返回值

没有返回值

注意

Sleep()函数不能被自定义指标调用,因为指标是以界面线路通过并不能够放慢速度,智能交易每0.1 second秒会检测。

不能在自定义指标中调用Sleep()函数,因为指标是在接口线程中执行的,并且不能降低它的速度。该函数有一个内置检查,每0.1秒检查一次EA的停止标帜。

# 5.24 TerminalClose

该函数关闭客户端

bool  TerminalClose(
   int ret_code      // 关闭客户端代码
   );
1
2
3

参数

ret_code

[in] 返回代码,在操作完成后通过客户端返回。

返回值

函数成功true,否则false。

注意

TerminalClose() 函数不会立即停止客户端,它只命令客户端完成它的操作。

EA交易的代码叫做TerminalClose()指令必须有立即完成所有的安排(例如,所有以前打开的文件必须以正常模式关闭)。该函数的调用通过 返回操作符执行。

ret_code参数允许指示必要的返回代码,以分析在命令提示符启动时终止客户端操作的原因。

示例:

//--- 输入参量
input int  tiks_before=500; // 订单号数目直到终止
input int  pips_to_go=15;   //  pips 间的距离
input int  seconds_st=50;   // 给予EA交易的秒数
//--- 全局
datetime   launch_time;
int        tick_counter=0;
//+------------------------------------------------------------------+
//| EA反法初始化函数                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   Print(__FUNCTION__," reason code = ",reason);
   Comment("");
  }
//+------------------------------------------------------------------+
//| EA跳价执行函数                                                     |
//+------------------------------------------------------------------+
void OnTick()
  {
   static double first_bid=0.0;
   MqlTick       tick;
   double        distance;
//---
   SymbolInfoTick(_Symbol,tick);
   tick_counter++;
   if(first_bid==0.0)
     {
      launch_time=tick.time;
      first_bid=tick.bid;
      Print("first_bid =",first_bid);
      return;
     }
//---  pips 的价格距离
   distance=(tick.bid-first_bid)/_Point;
//--- 通过EA操作显示告示
   string comm="From the moment of start:\r\n\x25CF elapsed seconds: "+
               IntegerToString(tick.time-launch_time)+" ;"+
               "\r\n\x25CF ticks received: "+(string)tick_counter+" ;"+
               "\r\n\x25CF price went in points: "+StringFormat("%G",distance);
   Comment(comm);
//--- 检测关闭程序端状态的部分
   if(tick_counter>=tiks_before)
      TerminalClose(0);    // 推出订单号计数器
   if(distance>pips_to_go)
      TerminalClose(1);    // 同于pips_to_go增长pips数量
   if(distance<-pips_to_go)
      TerminalClose(-1);   // 同于pips_to_go下降pips的数量
   if(tick.time-launch_time>seconds_st)
      TerminalClose(100);  // 超时终止
//---
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

相关参考 程序运行 ,执行错误 , 无法初始化原因

# 5.25 TesterHideIndicators

设置显示/隐藏EA中使用的指标的模式。这个函数仅用于在测试期间管理已用指标的可见性。
void  TesterHideIndicators(
   bool      hide     // 标识
   );
1
2
3
4

参数

hide

[in] 用于测试时隐藏指标的标识。设置隐藏已创建指标为true,否则为false。

返回值

无。

注意

默认情况下,已测试EA创建的所有指标都显示在可视测试图表上。此外,这些指标还显示在测试完成后自动打开的图表上。TesterHideIndicators()函数允许开发人员实现禁止显示已用指标的功能。

若要禁止显示测试EA时已用的指标,请在创建EA句柄之前调用TesterHideIndicators()等于true – 在此后创建的所有指标都被标记为隐藏标识。这些指标在可视测试期间和测试完成后自动打开的图表上都不显示。

若要禁用新创建指标的隐藏模式,请调用TesterHideIndicators() 等于false。只有从测试EA直接生成的指标才可以显示在测试图表上。这个规则只适用于<data_folder>MQL5\Profiles\Templates没有单一模板的情况下。

如果<data_folder>MQL5\Profiles\Templates文件目录包含一个特殊模板<EA_name>.tpl,那么只有该模板的指标可以在可视测试期间和测试图表上显示。在这种情况下,测试EA中无已用指标可显示。即使在EA代码中调用TesterHideIndicators()等于true,这种情况下仍然存在。

如果<data_folder>MQL5\Profiles\Templates目录不包含特殊模板<EA_name>.tpl而是以tester.tpl来替代,那么没有被TesterHideIndicators()函数禁用的来自tester.tpl的指标和来自EA的指标会在可视测试期间和测试图表上显示。如果没有tester.tpl模板,则使用default.tpl模板的指标来替代。

如果策略测试发现了不合适的模板(<EA_name>.tpl,tester.tpl或default.tpl),那么EA中使用的指标的显示则完全由TesterHideIndicators() 函数管理。

例如:

bool CSampleExpert::InitIndicators(void)
  {
   TesterHideIndicators(true);
//--- 创建MACD指标
   if(m_handle_macd==INVALID_HANDLE)
      if((m_handle_macd=iMACD(NULL,0,12,26,9,PRICE_CLOSE))==INVALID_HANDLE)
        {
         printf("Error creating MACD indicator");
         return(false);
        }
   TesterHideIndicators(false);
//--- 创建EMA指标并将其添加到集
   if(m_handle_ema==INVALID_HANDLE)
      if((m_handle_ema=iMA(NULL,0,InpMATrendPeriod,0,MODE_EMA,PRICE_CLOSE))==INVALID_HANDLE)
        {
         printf("Error creating EMA indicator");
         return(false);
        }
//--- 成功
   return(true);
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

另见 IndicatorRelease

# 5.26 TesterStatistics

函数返回基于测试结果计算的指定统计量的值。

    double  TesterStatistics(
   ENUM_STATISTICS statistic_id      // ID
   );
1
2
3

参数

statistic_id

[in] 来自 ENUM_STATISTICS 枚举的统计参数的ID。

返回值

来自测试结果的统计参数的值。

在策略测试

器中函数可以在OnTester() 或 OnDeinit() 内部调用。其他情况下结果不确定。

# 5.27 TesterStop

当测试时,给予程序操作完成命令。

void  TesterStop();
1

返回值

无返回值。

注意

TesterStop()函数是为测试代理上的EA例行早期关闭而设计的 – 例如,当达到指定数量的亏损交易或预先设定的下降水平时。

TesterStop()调用被认为是测试的正常完成,因此OnTester() 函数被调用,将全部累积的交易统计数据和优化准则值提交到策略测试。

在策略测试中调用 ExpertRemove()还意味着正常测试完成并允许获取交易统计数据,但EA从代理内存中卸载。在这种情况下,对下一组参数执行传递需要一段时间来重新加载重新。因此,TesterStop() 是早期例行完成测试的首选选项。

另见 程序运行、测试交易策略、 ExpertRemove、SetReturnError

# 5.28 TesterWithdrawal

在测试过程中模拟出金操作

bool  TesterWithdrawal(
   double money      // 出金总额
   );
1
2
3

参数

money

[in] 要求出金的总金额(使用存款货币的单位)

返回值

成功,返回 true,否则 false.

# 5.29 TranslateKey

考虑当前输入语言 和 控制键状态 的虚拟按键编码,返回对应的Unicode字符。

short  TranslateKey(
   int  key_code      // 接收Unicode字符的 按键 码
   );
1
2
3

参数

key_code

[in] 键码。

返回值

转换成功的Unicode字符。错误情况下,函数返回 -1。

注意

函数使用ToUnicodeEx将用户按下的键码转换为Unicode字符。如果没有触发ToUnicodeEx则可能发生错误 —— 例如,试图接收SHIFT键字符时。

例如:

void OnChartEvent(const int id,const long& lparam,const double& dparam,const string& sparam)
  {
   if(id==CHARTEVENT_KEYDOWN)
     {
      short sym=TranslateKey((int)lparam);
      //--- 如果输入的字符成功转换为Unicode
      if(sym>0)
         Print(sym,"'",ShortToString(sym),"'");
      else
         Print("Error in TranslateKey for key=",lparam);
     }
  }
1
2
3
4
5
6
7
8
9
10
11
12

相关参考 客户端事件,OnChartEvent

# 5.30 ZeroMemory

函数重新设置(归零)通过形式参数传递给它的变量。

void  ZeroMemory(
   void & variable      // 变量重置
   );
1
2
3

参数

variable

[in] [out] 变量通过形式参数传递,然后重置(从0开始初始化)

返回值

没有返回值

注意

如果传递的形式参数是一个字符串,那么调用将等效于表示为空值。

对于简单类型及其数组,以及包含此类型的 结构/类,这是一个简单的重置。

对于包含字符串和动态数组的对象,将对每个元素调用ZeroMemory()。

对于任何不受const修饰符保护的数组,这将会把所有元素归零。

对于复杂对象的数组,需要对每个元素调用ZeroMemory()。

ZeroMemory()不能应用于具有受保护的 成员 或 继承的 类。