程序端
- 修正导致程序端和MetaEditor阻止Windows关机和重新启动的错误。
- 修正应用模板时的图表切换。
MQL5
- 修正在某些情况下减慢编译速度的错误。
修正崩溃日志中报告的错误。
修正崩溃日志中报告的错误。
MetaTrader 5 build 1745 will be the last platform version supporting Microsoft Windows XP/2003/Vista. The minimum required operating system version for running MetaTrader 5 is Windows 7. However, we strongly recommend using the 64-bit version of Windows 10.
MetaTrader 5 build 1745将是最后一个支持Microsoft Windows XP/2003/Vista操作系统的平台版本。现在运行MetaTrader 5所需的最低操作系统版本为Windows 7。然而,我们仍强烈建议您使用64位版本的Windows 10。
新版平台发布后,将停止对旧版本的桌面版和移动版的支持:
为了支持新的共享项目,我们更新了MQL5存储的操作协议。因此,平台更新后,您将需要检查核对来自存储的所有数据。更新过程中,MQL5存储中的所有数据都不会丢失或受到影响。
更新到新版平台之前,我们建议您执行提交操作,将所有本地更改发送到MQL5存储。
如何工作
例如,您可以创建一个工具显示美元指数(USDX)。它使用下面的公式:
50.14348112 * pow(ask(EURUSD),-0.576) * pow(USDJPY,0.136) * pow(ask(GBPUSD),-0.119) * pow(USDCAD,0.091) * pow(USDSEK,0.042) * pow(USDCHF,0.036)
注意:USDEUR和USDGBP货币对在源美元指数公式中使用。因为平台中仅可以使用反向货币对,因此合成交易品种公式中使用的是负能量和买价,而不是卖价。
平台将根据您交易商提供的其他六个交易品种报价来计算新工具的实时价格。价格变化将在市场报价窗口和图表上显示:
int CustomTicksAdd( const string symbol, // 交易品种名称 const MqlTick& ticks[] // 可以用于自定义交易品种的报价数据数组 );CustomTicksAdd函数允许提供报价,如同从交易商服务器接收这些报价。数据被发送至市场报价窗口,而不是直接写入报价数据库。然后,程序端将报价从市场报价窗口保存至数据库。如果在一次调用中传递了大量的数据,那么函数行为就会发生变化来节省资源。如果传送的报价数超过256个,那么数据会被分成两个部分。较大的部分直接记录到报价数据库(类似CustomTicksReplace)。第二部分由最近的128个报价组成,被发送到市场报价,程序端从这里将报价保存到数据库。
功能全面的项目现在已可以在MetaEditor中使用。程序开发过程已变得更加方便。
现在主要的MQL5程序文件不会呈现为项目文件。项目是独立的"MQPROJ"文件,它可以存储程序设置,编译所有已用文件的参数和信息。主要的项目设置可以从独立的对话框访问,所以,现在无需通过#property在源代码中指定项目设置。
为了便于进行项目工作,还提供了独立的导航标签。全部文件,例如包含文件,资源文件,标题文件和其他文件都被安排到这个标签类别中。所有文件都会自动添加到项目导航中。例如,如果您包括了一个新的MQH文件,那么它将自动出现在导航的“相关性”部分。
在更新的MQL5存储在线库中也实现了对新项目的支持。现在,通过与MQL5.community其他成员的协作,开发大型项目变得更加方便。
为组项目提供了新的共享项目部分。在这部分创建的项目会即时发送到存储中:您可以授予其他用户的权限并立即开始协作。
当您在共享项目中编译一个项目时,根据程序类型,可执行文件EX5会自动复制到本地专家,指标或脚本目录。您可以轻松地在图表上启动程序,而无需手动复制文件。
MQL5存储操作中的新功能
为了实现对新共享项目的支持,我们已经更改了MQL5存储的操作协议。因此,平台更新后,您将需要检查核对来自存储的所有数据。更新过程中,MQL5存储中的所有数据都不会丢失或受到影响。
“检查存储”命令现在已经不可用。而是使用“激活MQL5存储”和“更新存储文件”命令来接收数据:
新项目:创建和操作细节的示例
新项目版块已被添加到MetaEditor。项目是一个mqproj文件,可以存储普通程序属性和有关所有已用文件的信息。现在,程序属性可以通过独立的MetaEditor对话框方便地管理,不必在源代码中手动更改属性(使用#property指令)。
如果您有可用代码,您可以通过使用“来自源代码的新项目”命令来轻松地测试新项目。
在已选文件所在的目录中,将会创建一个具有相同名称和mqproj为扩展名的新项目文件。通过#property在源代码中指定的主要程序属性将被自动添加到项目,包括名称,版权,版本,链接到开发者网站和程序描述。
编译MQL5程序的两个新选项已被添加到项目属性:
若要使用项目服务,请使用导航窗口独立的项目标签。项目服务中使用的所有文件都以方便的形式展示在这个标签。当项目从源文件生成时,所有使用的包含文件(在主MQ5文件及其包含文件中通过#include目录指定)都会自动添加到相关性部分。
当新的包含文件添加到源代码时,它也出现在项目导航中。已用的标题文件添加到标题版块;在项目中用作资源的图片,声音和其他MQL5程序也被添加到资源版块。带有源代码的MQ5文件显示在资源版块。在“设置和文件”版块,您可以添加其他文件,例如用于测试的set文件和图表模板。
使用快捷菜单命令向项目添加现有文件或从项目中删除文件。删除文件时请注意,因为您不但可以从项目中移除文件(解除绑定)还可以从硬盘中彻底删除文件:
创建一个新项目犹如创建普通MQL5程序一样简单。单击“新项目”,选择新程序类型并指定MQL5向导中的属性(例如名称,事件处理程序)。
若要获得可执行文件EX5,您可以打开这个项目并按下F7(编译命令)或打开程序的主MQ5文件并编译它。
MQL5存储中的共享项目:操作细节
共享项目是由一个单独的共享项目版块来管理。如果您还没有连接存储库,请在所需文件夹的快捷菜单执行“激活MQL5存储”命令。MetaEditor将检查您的存储库是否包含任何保存数据以及是否有任何共享项目可供您使用。所有可用的数据都将从存储库中恢复并上传到您的电脑(检验操作)。可用的组项目出现在共享项目版块。若要恢复项目,请在快捷菜单中执行“在存储库检查”。
若要创建新组项目,请选择共享项目文件夹并点击“新项目”:
然后完成标准的MQL5步骤:设置所需程序的类型,名称和属性。对于组项目,您应该使用清晰易懂的名称,以便其他参与者能够轻松地找到它们。项目名称中只可以使用没有空格的拉丁字符和数字。
创建的对象会立刻添加到MQL5存储库中。项目中使用的标准程序库文件不会添加到存储库中,您可以手动添加它们。
若要允许其他参与者使用项目,请打开项目属性。在这里,您可以通过指定MQL5.community登录名,以及为组工作设定公共参数,来向选定用户授予权限:
当您编译一个组项目时,根据程序类型,可执行文件EX5会自动复制到本地专家,指标或脚本目录。它允许您在程序端立即运行程序而不必手动复制到适当的目录。
MQL5存储中的公共项目:参与开发
如上所述,MQL5存储中的每个组项目都有公共设置:项目可以是私人的,也可以是对其他人公开的。现在,您可以免费加入的所有项目都显示在单独的“公共项目”标签。
每个人都可以找到心仪的项目并加入其开发过程。仅需单击加入,接收存储项目。
//+------------------------------------------------------------------+ //| 脚本程序起始函数 | //+------------------------------------------------------------------+ void OnStart() { //--- 作为二进制数组的模板文件 unsigned char my_template[]= { 0xFF,0xFE,0x3C, ... ,0x00 // 本例中数据数组被缩短 }; //--- 保存和应用模板 if(FileSave("my_template.tpl",my_template)) { Print("Custom template saved in \\MQL5\\Files"); if(ChartApplyTemplate(0,"\\Files\\my_template.tpl")) Print("Custom template applied to the current chart"); else Print("Failed to apply custom template"); } else Print("Failed to save custom template"); }
函数 | 行为 |
---|---|
CustomSymbolCreate | 在指定组以指定名称创建一个自定义交易品种 |
CustomSymbolDelete | 删除指定名称的自定义交易品种 |
CustomSymbolSetInteger | 为自定义交易品种设置整型属性值 |
CustomSymbolSetDouble | 为自定义交易品种设置真实型属性值 |
CustomSymbolSetString | 为自定义交易品种设置字符串类型属性值 |
CustomSymbolSetMarginRate | 根据订单类型和方向为自定义交易品种设置预付款比例 |
CustomSymbolSetSessionQuote | 为指定交易品种和工作日设置指定报价期的起止时间 |
CustomSymbolSetSessionTrade | 为指定交易品种和工作日设置指定交易时期的起止时间 |
CustomRatesDelete | 在指定时间间隔内从自定义交易品种的价格历史记录中删除所有柱形图 |
CustomRatesReplace | 在指定时间间隔内用MqlRates类型数组的数据完全替换自定义交易品种的价格历史记录 |
CustomRatesUpdate | 将缺失的柱形图添加到自定义交易品种的历史记录并用MqlRates类型数组的数据替换现有的数据 |
CustomTicksAdd | 将MqlTick类型的数组数据添加到自定义交易品种的价格历史记录。自定义交易品种必须在市场报价窗口中选择。 |
CustomTicksDelete | 在指定时间间隔内从自定义交易品种的价格历史记录中删除所有报价 |
CustomTicksReplace | 在指定时间间隔内用MqlTick类型数组的数据完全替换自定义交易品种的价格历史记录 |
程序库位于程序端工作目录的Include\Generic文件夹。
bool ArraySwap( void& array1[], // 第一数组 void& array2[] // 第二数组 );这个函数接受相同类型和相同维度的动态数组。对于多维数组,除了第一元素以外,所有维度中的元素数量都应该匹配。
The new version provides the possibility to view market statistics of financial instruments traded in the exchange execution mode. In order to view the statistics, open the menu of any symbol in Market Watch, and select 'Statistics'.
Operations with positions in the Trade tab have become more convenient. Now, a single tap on a position or order will reveal the detailed information and available actions, such as closing, modifying or increasing the position volume, as well as opening the chart of the position symbol.
新版本中可以查看交易所执行模式下进行交易的金融工具市场统计信息。打开市场报价(Market Watch)中任何交易品种的菜单,选择“统计”,来查看市场统计信息。
此外,新版本中交易标签的持仓操作也更加便捷。现在,单击持仓或订单将会显示详细信息和可用操作,例如平仓,更改或增加持仓交易量,以及打开持仓交易品种的图表。
In MetaTrader 5 for Android, it is now possible to easily create preliminary brokerage accounts. Select "Open a real account" from the menu and find your broker in the list of servers. You will only need attach two documents, including your identity document and a bank account statement. Your request will be forwarded to the broker, who may request additional information required for account opening.
MetaTrader 5 Android版,现在能够轻松创建初始真实交易账户。从菜单选择“开立真实账户”并在服务器列表中找到您的交易商。您只需附加两份文件,包括您的身份证明文件和银行账户账单。然后您的请求将被转发至交易商,同时开立账户时您可能会被要求提供其他信息。
union LongDouble { long long_value; double double_value; };与结构不同,不同的union成员属于同一个内存区。在该示例中,LongDouble函数的union是通过共享同一个内存区的long和double类型值来声明。请注意,由于long_value 和 double_value 变量重复(在内存中),所以union不可以同时存储long整型值和double真实型值(不同于结构)。 换句话说,MQL5程序随时都可以将union的数据处理为整型(long)或真实型(double)值。因此,union允许接收表示相同数据序列的两种(或更多种)选项。
union LongDouble { long long_value; double double_value; }; //+------------------------------------------------------------------+ //| 脚本程序起始函数 | //+------------------------------------------------------------------+ void OnStart() { //--- LongDouble lb; //--- 获得并显示无效 -nan(ind) 数字 lb.double_value=MathArcsin(2.0); printf("1. double=%f integer=%I64X",lb.double_value,lb.long_value); //--- 最大的标准化数值 (DBL_MAX) lb.long_value=0x7FEFFFFFFFFFFFFF; printf("2. double=%.16e integer=%I64X",lb.double_value,lb.long_value); //--- 最小的正标准化 (DBL_MIN) lb.long_value=0x0010000000000000; printf("3. double=%.16e integer=%.16I64X",lb.double_value,lb.long_value); } /* Execution result 1. double=-nan(ind) integer=FFF8000000000000 2. double=1.7976931348623157e+308 integer=7FEFFFFFFFFFFFFF 3. double=2.2250738585072014e-308 integer=0010000000000000 */
class Foo { int value; public: string Description(void){return IntegerToString(value);}; //--- 默认构造函数 Foo(void){value=-1;}; //--- 参数化构造函数 Foo(int v){value=v;}; }; //+------------------------------------------------------------------+ //| 包括 Foo 类型对象的结构 | //+------------------------------------------------------------------+ struct MyStruct { string s; Foo foo; }; //+------------------------------------------------------------------+ //| 脚本程序起始函数 | //+------------------------------------------------------------------+ void OnStart() { //--- MyStruct a,b; Foo an_foo(5); a.s="test"; a.foo=an_foo; Print("a.s=",a.s," a.foo.Description()=",a.foo.Description()); Print("b.s=",b.s," b.foo.Description()=",b.foo.Description()); //--- Print("b=a"); b=a; //--- Print("a.s=",a.s," a.foo.Description()=",a.foo.Description()); Print("b.s=",b.s," b.foo.Description()=",b.foo.Description()); /* Execution result; a.s=test a.foo.Description()=5 b.s= b.foo.Description()=-1 b=a a.s=test a.foo.Description()=5 b.s=test b.foo.Description()=5 */ }在隐式操作符中执行对象的成员逐一复制。
ENUM_POSITION_REASON | ENUM_DEAL_REASON | ENUM_ORDER_REASON | 原因描述 |
---|---|---|---|
POSITION_REASON_CLIENT | DEAL_REASON_CLIENT | ORDER_REASON_CLIENT | 激活从桌面程序端下单的订单而执行该操作 |
POSITION_REASON_MOBILE | DEAL_REASON_MOBILE | ORDER_REASON_MOBILE | 激活从手机应用下单的订单而执行该操作 |
POSITION_REASON_WEB | DEAL_REASON_WEB | ORDER_REASON_WEB | 激活从网页平台下单的订单而执行该操作 |
POSITION_REASON_EXPERT | DEAL_REASON_EXPERT | ORDER_REASON_EXPERT | 激活从MQL5程序下单的订单而执行该操作,例如EA交易或脚本 |
- | DEAL_REASON_SL | ORDER_REASON_SL | 激活止损而执行该操作 |
- | DEAL_REASON_TP | ORDER_REASON_TP | 激活止赢而执行该操作 |
- | DEAL_REASON_SO | ORDER_REASON_SO | 由于Stop out 事件而执行该操作 |
- | DEAL_REASON_ROLLOVER | - | 由于展期交割而执行交易 |
- | DEAL_REASON_VMARGIN | - | 收取变动预付款后执行交易 |
- | DEAL_REASON_SPLIT | - | 股票或其他资产分割(价格减少)后执行交易,宣布分割期间拥有持仓 |
新版MetaTrader 5 iOS build 1605提供了轻松开立初始交易账户的可能性。请从菜单选择“开立真实账户”并在服务器列表寻找您的交易商。填写您的个人详细资料,附加两份可以确认您身份和地址的文档并提交请求。您的交易商将会为您开立一个真实账户,必要情况下您还需要提供其他信息。
新版MetaTrader 5 iOS还具有优化和重新设计邮箱版块的特性:
更新文档。
MetaTrader 5 Android的交易历史现在能够以持仓的形式显示。在此之前,历史标签仅仅包含订单和交易信息,然而现在,可以根据持仓信息来分析交易。持仓相关的全部交易数据都集中显示在一条记录,显示如下:
现在交易历史能够以持仓的形式显示。在此之前,历史标签仅仅包含订单和交易数据。现在,它还包括了持仓数据。交易平台收集持仓相关的交易数据,然后将数据合并为一个记录。该记录包括:
//+------------------------------------------------------------------+ //| 模板函数 | //+------------------------------------------------------------------+ template<typename T1,typename T2> string Assign(T1 &var1,T2 var2) { var1=(T1)var2; return(__FUNCSIG__); } //+------------------------------------------------------------------+ //| bool+string的特殊重载 | //+------------------------------------------------------------------+ string Assign(bool &var1,string var2) { var1=(StringCompare(var2,"true",false) || StringToInteger(var2)!=0); return(__FUNCSIG__); } //+------------------------------------------------------------------+ //| 脚本起始函数 | //+------------------------------------------------------------------+ void OnStart() { int i; bool b; Print(Assign(i,"test")); Print(Assign(b,"test")); }代码执行后,我们可以看到Assign() 模板函数已被用于int+string组,而重载版也已在第二次调用时用于bool+string组。
string Assign<int,string>(int&,string) string Assign(bool&,string)
template<typename T> T Func() { return (T)0; } void OnInit() { Func<double>(); // 模板函数显式规范 }因此,类型的显式规范将会执行代表参数而非调用参数。
更新文档。
更新文档。
添加通过Facebook注册和登录您的MQL5.com账户的功能。如果您拥有该群组网络的账户,只需几次点击您就可以访问聊天功能及全套的MetaTrader 5服务。
string str; ... if(str) // 将会导致"不能转换'string'类型到'bool'"编译错误(在之前版本不会出现错误) Print("str is true");应该使用明确的条件:
string str; ... //--- 检查字符串是否被初始化 if(str!=NULL) Print("str is true"); or //--- 检查字符串值是否为"true" if(StringCompare(str,"true",false)) Print("str is true"); or //--- 检查字符串是否为不等于零的整数 if((int)str!=0) Print("str is true");
void ArrayPrint( const void& array[], // 输出数组 uint digits=_Digits, // 小数位数 const string separator=NULL, // 结构字段值之间的分隔符 ulong start=0, // 最先显示元素的指数 ulong count=WHOLE_ARRAY, // 显示的元素数 ulong flags=ARRAYPRINT_HEADER|ARRAYPRINT_INDEX|ARRAYPRINT_LIMIT|ARRAYPRINT_ALIGN );ArrayPrint无法打印全部结构数组字段到日志 – 跳过对象的数组字段和指针字段。如果您想打印全部结构字段,您应该使用所需格式批量打印的定制功能。
//--- 显示最近的10个柱形图值 MqlRates rates[]; if(CopyRates(_Symbol,_Period,1,10,rates)) { ArrayPrint(rates); Print("Проверка\n[time]\t[open]\t[high]\t[low]\t[close]\t[tick_volume]\t[spread]\t[real_volume]"); for(int i=0;i<10;i++) { PrintFormat("[%d]\t%s\t%G\t%G\t%G\t%G\t%G\t%G\t%I64d\t",i, TimeToString(rates[i].time,TIME_DATE|TIME_MINUTES|TIME_SECONDS), rates[i].open,rates[i].high,rates[i].low,rates[i].close, rates[i].tick_volume,rates[i].spread,rates[i].real_volume); } } else PrintFormat("CopyRates failed, error code=%d",GetLastError()); //--- 日志示例 /* [time] [open] [high] [low] [close] [tick_volume] [spread] [real_volume] [0] 2016.11.09 04:00:00 1.11242 1.12314 1.11187 1.12295 18110 10 17300175000 [1] 2016.11.09 05:00:00 1.12296 1.12825 1.11930 1.12747 17829 9 15632176000 [2] 2016.11.09 06:00:00 1.12747 1.12991 1.12586 1.12744 13458 10 9593492000 [3] 2016.11.09 07:00:00 1.12743 1.12763 1.11988 1.12194 15362 9 12352245000 [4] 2016.11.09 08:00:00 1.12194 1.12262 1.11058 1.11172 16833 9 12961333000 [5] 2016.11.09 09:00:00 1.11173 1.11348 1.10803 1.11052 15933 8 10720384000 [6] 2016.11.09 10:00:00 1.11052 1.11065 1.10289 1.10528 11888 9 8084811000 [7] 2016.11.09 11:00:00 1.10512 1.11041 1.10472 1.10915 7284 10 5087113000 [8] 2016.11.09 12:00:00 1.10915 1.11079 1.10892 1.10904 8710 9 6769629000 [9] 2016.11.09 13:00:00 1.10904 1.10913 1.10223 1.10263 8956 7 7192138000 Check [time] [open] [high] [low] [close] [tick_volume] [spread] [real_volume] [0] 2016.11.09 04:00:00 1.11242 1.12314 1.11187 1.12295 18110 10 17300175000 [1] 2016.11.09 05:00:00 1.12296 1.12825 1.1193 1.12747 17829 9 15632176000 [2] 2016.11.09 06:00:00 1.12747 1.12991 1.12586 1.12744 13458 10 9593492000 [3] 2016.11.09 07:00:00 1.12743 1.12763 1.11988 1.12194 15362 9 12352245000 [4] 2016.11.09 08:00:00 1.12194 1.12262 1.11058 1.11172 16833 9 12961333000 [5] 2016.11.09 09:00:00 1.11173 1.11348 1.10803 1.11052 15933 8 10720384000 [6] 2016.11.09 10:00:00 1.11052 1.11065 1.10289 1.10528 11888 9 8084811000 [7] 2016.11.09 11:00:00 1.10512 1.11041 1.10472 1.10915 7284 10 5087113000 [8] 2016.11.09 12:00:00 1.10915 1.11079 1.10892 1.10904 8710 9 6769629000 [9] 2016.11.09 13:00:00 1.10904 1.10913 1.10223 1.10263 8956 7 7192138000 */
void OnStart() { int arr[]; //--- 最初使用的内存数量 Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); //--- 用于数组大小1的内存数量,保留 ArrayResize(arr,1,1024*1024); Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); //--- 增加数组以后,使用的内存数量因保留而无法更改 ArrayResize(arr,1024*512,1024*1024); Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); //--- 减少数组以后,内存大小也不会改变 ArrayResize(arr,1); Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); //--- 移除储备内存后将释放未使用的内存 ArrayResize(arr,1,-1); Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); }
#include <Graphics/Graphic.mqh> double Func1(double x) { return MathPow(x,2); } double Func2(double x) { return MathPow(x,3); } double Func3(double x) { return MathPow(x,4); } void OnStart() { GraphPlot(Func1,Func2,Func3,-2,2,0.05,CURVE_LINES); }结果:
#include <Math/Stat/Binomial.mqh> #include <Graphics/Graphic.mqh> void OnStart(void) { double vars[101]; double results[101]; const int N=2000; //--- MathSequence(0,N,20,vars); MathProbabilityDensityBinomial(vars,N,M_PI/10,true,results); ArrayPrint(results,4); GraphPlot(results); //--- }结果:
更新文档。