下载MetaTrader 5

MQL语言编码规范,在您进行编码之前应该阅读的规范(For beginner) [有兴趣的请联系QQ:1031130533]

要添加评论,请登录注册
有问题询问应用程序开发者吗? - 在注释里提问
WFBI
65
WFBI 2009.11.12 11:29 

1.说明
为了保证在软件开发过程中,全体成员的代码风格一致,便于维护,提高软件产品的质量和保持开发产品的延续性,特制定本编码规范。本规范详细规定了源代码书写、变量命名、函数/过程的书写、错误和异常处理等方面。
2. 程序约定
2.1 排版规则
程序应采用缩进风格编写,每层缩进使用一个制表位(TAB),类定义、方法都应顶格书写;
左花括号要另起一行,不能跟在上一行的行末;
一个变量定义占一行,一个语句占一行;
对独立的程序块之间、变量说明之后必须加空行;
对于较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读;
循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分;
在结构成员赋值等情况,等号对齐,最少留一个空格;
若函数或过程中的参数较长,则要进行适当的划分。

2.2 命名约定
2.2.1 应用程序的命名

2.2.2 子模块的命名
每个子模块的名字应该由描述模块功能的1-3以单词组成。每个单词的首字母应大写。在这些单词中可以使用一些较通用的缩写。
2.2.3 变量的命名
变量的命名的基本原则是使得变量的含义能够从名字中直接理解。可以用多个英文单词拼写而成,每个英文单词的首字母要大写,其中英文单词有缩写的可用缩写;变量的前缀表示该变量的类型;对于作用域跨越10行以上的变量名称不能少于4个字符,除循环变量,累加变量外不得使用I、j、k等名称的变量。变量分为取全局变量和局部变量,对于全局变量以加前缀“g_”来区分。

另外,要注意的是:全局变量在程序中不要定义太多,能用局部变量的就用局部变量。如果要使用相关的变量,建议采用类的方式或者结构的方式存放,以减少具体变量的个数。
2.2.4 常量的命名
常量所有的字母均为大写。并且单词之间使用下划线”_”隔开。
2.2.5 函数/过程的命名
函数/过程名称应该尽量使用能够表达函数功能的英文名称,函数名称中应该禁止使用如同function1,function2等含义不清的名称。单词间应该使用大小写分隔。全局函数/过程名称以“g_”前缀开始。
2.2.6 接口命名
接口名称要以大写字母开头。如果接口包含多个单词,每个单词的首字母大写,其他字母小写2.2.7 类的命名
2.2.8 方法的命名
方法名称以小写字母开头;
方法名称如果包含多个单词,除了第一个单词外,每个单词的首字母大写,其它字母小写。如果这些单词是缩略语(例如XML),也要首字母大写,其它字母小写(写作Xml)。
方法名称应该是一个动词或动名词短语,意思是“完成什么功能”,“执行什么操作”;
2.3 参数的约定
2.3.1 输入参数的约定
有些函数有输入参数,这些参数指由函数外部(调用者)输入,并在函数内部使用。在函数业务流程说明后跟输入参数说明区,用“输入参数”或“Input Parameters”标记。在参数名列表中的每个参数后增加该参数的注释。
2.3.2 输出参数的约定
有些函数有输出参数,这些参数指由函数外部(调用者)定义,在函数内部使用并返回给调用者的参数。

2.3.3 返回值的约定
每个函数均有返回值,除非操作非常简单。\返回值说明,要说明各种不同类型返回值以及它们的含义。
2.4 注释约定
在软件中对每个文件头,自定义函数和变量,重要的处理过程都要有必要的注释。
2.4.1 源程序头的注释和规范
每个文件头插入注释,标明文件的用途和作者,注释如下:(注释尽量用中文)
//程序名称
//版权说明
//版本号:
//其他
2.4.2 函数的注释
每个函数前面注明函数的功能和输入,输出。注释为:
//名称
//功能:(说明函数的功能)
//输入参数:(说明每个输入参数的用途和取值约定)
//输出参数:(说明每个输出参数的用途和取值约定)
//返回:(说明返回值,返回值的含义和约定)
2.4.3 变量注释
直接在变量后面注明变量的用途和取值约定,

2.4.4 类型定义注释
2.4.5 注释
码通常使用几个函数和过程来实现某一项功能,这时候需要使用区注释将这些具有共同目的的函数和过程标明出来。
使用整行的”*”作为隔离行,让程序清晰可读。
一般删除的代码不建议直接删除,最好用“//”注释起来。
2.4.6 代码中的注释
在代码中要求注释的地方有:
代码中的关键部分;
在使用特殊算法或者逻辑性较强的代码;
在修改或删除代码部分,需要加注释;修改/删除人,目的.
2.5 变量的作用范围
尽量做到缩小变量的作用范围,对于变量是指针的,应遵循以下约定:
在局部分配的空间在局部释放。
函数体内不能分配空间并将空间指针作为函数参数返回。
动态全局空间在程序结束时一定要释放。
所有动态分配的空间在对应层次的模块释放,并且用完马上释放。不重复释放相同的指针。
2.6 函数/过程的定义
在函数的定义处应当增加本函数的功能描述的注释。
用一句话描述清楚功能。
可用英文或中文。
功能注释格式要求所有代码一致。
2.7 函数业务流程的定义
在函数功能描述后,要增加函数的主要业务流程注释。
可以用多行描述,以解释清楚业务流程为主。
可用英文或中文。
业务流程注释格式要求所有代码一致。
业务流程注释可以尽量详细,注释的长度可以与代码长度差不多,但是不要太长。
注意:函数业务流程的说明并不在乎有多长,但是在乎能否说明过程。有些像N阶乘的函数流程比较简单,但是有些比较复杂。当比较复杂时,可以用标号来说明。
3. 接口/函数过程调用的约定
几乎每一个项目中,都存在开发接口API给其他应用调用。
3.1 头文件
提供给使用API的应用的标准头文件。头文件必须包含三部分。
防止调用文件重复引用的编译条件

函数定义
函数的定义是为了方便应用知道LIB、DLL里引出了怎样的API,应该如何使用。如上面的例子。
错误代码定义
错误代码是接口API里因为内部某种错误返回的代码,它告诉应用出现了什么错误,以便开发者进行调试和排错。
3.2 函数
提供给应用调用的执行体。实现函数时,必须根据以下规范开发
3.2.1 变量定义
在函数代码中,变量的定义必须放在第一部分,同时给指针类型的变量赋空(NULL)。
3.2.2 参数合法性检查
在使用应用传递的输入输出参数之前,必须对参数进行合法性检查,保证代码执行使用参数的安全性。比如,应用的一个输出参数地址为NULL,如果处理之前不检查参数的合法性,那么将导致一个内存错误;如果检查合法性,就不会造成代码执行时出现问题。
3.2.3执行处理
在处理代码开发中,必须注意以下的一系列的问题:
必须先分配系统资源,才能分配函数内部需要的资源;相反,必须首先释放函数内部分配的资源,再释放系统资源。
3.2.4 返回值
4. 错误和异常处理规范
4.1 出错类型定义约定
在整个系统软件产品的出错定义要一致;
统一模块层次的出错类型统一定义;
出错类型分为错误、警告、提示等三类信息,

错误代码统一用宏描述,并且放在一个头文件中;
例子string GetLastErrorStr() {
int l_error_0 = GetLastError();
switch (l_error_0) {
case 0/* NO_ERROR */:
return ("没有错误返回." + "[" + l_error_0 + "]");
case 1/* NO_RESULT */:
return ("没有错误返回,但结果不明." + "[" + l_error_0 + "]");
case 2/* COMMON_ERROR */:
return ("一般错误." + "[" + l_error_0 + "]");
case 3/* INVALID_TRADE_PARAMETERS */:
return ("无效的交易参数." + "[" + l_error_0 + "]");
case 4/* SERVER_BUSY */:
return ("交易服务器繁忙." + "[" + l_error_0 + "]");
case 5/* OLD_VERSION */:
return ("客户终端版本太旧." + "[" + l_error_0 + "]");
case 6/* NO_CONNECTION */:
return ("没有连接到服务器." + "[" + l_error_0 + "]");
case 7/* NOT_ENOUGH_RIGHTS */:
return ("没有足够权限进行相应操作." + "[" + l_error_0 + "]");
case 8/* TOO_FREQUENT_REQUESTS */:
return ("请求过于频繁." + "[" + l_error_0 + "]");
case 9/* MALFUNCTIONAL_TRADE */:
return ("交易运行故障." + "[" + l_error_0 + "]");
case 64/* ACCOUNT_DISABLED */:
return ("帐户被禁止." + "[" + l_error_0 + "]");
case 65/* INVALID_ACCOUNT */:
return ("无效的帐户." + "[" + l_error_0 + "]");
case 128/* TRADE_TIMEOUT */:
return ("交易超时." + "[" + l_error_0 + "]");
case 129/* INVALID_PRICE */:
return ("无效的价格." + "[" + l_error_0 + "]");
case 130/* INVALID_STOPS */:
return ("无效的止损价格." + "[" + l_error_0 + "]");
case 131/* INVALID_TRADE_VOLUME */:
return ("无效的下单量." + "[" + l_error_0 + "]");
case 132/* MARKET_CLOSED */:
return ("市场已关闭." + "[" + l_error_0 + "]");
case 133/* TRADE_DISABLED */:
return ("交易被禁止." + "[" + l_error_0 + "]");
case 134/* NOT_ENOUGH_MONEY */:
return ("资金不足." + "[" + l_error_0 + "]");
case 135/* PRICE_CHANGED */:
return ("价格已变化." + "[" + l_error_0 + "]");
case 136/* OFF_QUOTES */:
return ("开价." + "[" + l_error_0 + "]");
case 137/* BROKER_BUSY */:
return ("经纪人繁忙." + "[" + l_error_0 + "]");
case 138/* REQUOTE */:
return ("重新开价." + "[" + l_error_0 + "]");
case 139/* ORDER_LOCKED */:
return ("定单被锁定." + "[" + l_error_0 + "]");
case 140/* LONG_POSITIONS_ONLY_ALLOWED */:
return ("只允许开多仓." + "[" + l_error_0 + "]");
case 141/* TOO_MANY_REQUESTS */:
return ("请求过多." + "[" + l_error_0 + "]");
case 145/* TRADE_MODIFY_DENIED */:
return ("因为价格过于接近市价,所以操作被拒绝." + "[" + l_error_0 + "]");
case 146/* TRADE_CONTEXT_BUSY */:
return ("交易作业忙." + "[" + l_error_0 + "]");
case 147/* ERR_TRADE_EXPIRATION_DENIED */:
return ("服务器禁止设定过期时间." + "[" + l_error_0 + "]");
case 148/* ERR_TRADE_TOO_MANY_ORDERS */:
return ("开单和挂单总数已被经纪限定." + "[" + l_error_0 + "]");
}
return ("未知错误." + "[" + l_error_0 + "]");
}

注意:出错类型的定义一定要统一,并且一定要注意编码问题。
4.2异常的捕获
在程序中会出现各种异常,如除0错误、内存错误都要处理。要有异常可能的都要捕获。
4.3异常和错误的处理
每个函数独立处理内部的异常,对影响结果的异常通过返回值返回。对于在函数内部不能处理的异常,捕获后已另外的形式向调用者抛出,但是要在接口文档中详细写明。
注意:处理异常一般有两种方法,一是通过将异常转化为另一个异常抛出,二是通过函数返回值返回。在本规范中,我们倾向于用第二种方法。

好了,写的太多了,估计大家没有耐心看这些枯燥的语言了,有兴趣的请联系QQ:1031130533

zhimadog
84
zhimadog 2009.11.12 17:31  

赞同。

eaf
72
eaf 2009.11.13 04:45  

楼主是靠给别人写ea吃饭吗?

jxbgq
5
jxbgq 2009.11.16 03:26  
WFBI 写道 >>

1.说明
为了保证在软件开发过程中,全体成员的代码风格一致,便于维护,提高软件产品的质量和保持开发产品的延续性,特制定本编码规范。本规范详细规定了源代码书写、变量命名、函数/过程的书写、错误和异常处理等方面。
2. 程序约定
2.1 排版规则
程序应采用缩进风格编写,每层缩进使用一个制表位(TAB),类定义、方法都应顶格书写;
左花括号要另起一行,不能跟在上一行的行末;
一个变量定义占一行,一个语句占一行;
对独立的程序块之间、变量说明之后必须加空行;
对于较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读;
循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分;
在结构成员赋值等情况,等号对齐,最少留一个空格;
若函数或过程中的参数较长,则要进行适当的划分。

2.2 命名约定
2.2.1 应用程序的命名

2.2.2 子模块的命名
每个子模块的名字应该由描述模块功能的1-3以单词组成。每个单词的首字母应大写。在这些单词中可以使用一些较通用的缩写。
2.2.3 变量的命名
变量的命名的基本原则是使得变量的含义能够从名字中直接理解。可以用多个英文单词拼写而成,每个英文单词的首字母要大写,其中英文单词有缩写的可用缩写;变量的前缀表示该变量的类型;对于作用域跨越10行以上的变量名称不能少于4个字符,除循环变量,累加变量外不得使用I、j、k等名称的变量。变量分为取全局变量和局部变量,对于全局变量以加前缀“g_”来区分。

另外,要注意的是:全局变量在程序中不要定义太多,能用局部变量的就用局部变量。如果要使用相关的变量,建议采用类的方式或者结构的方式存放,以减少具体变量的个数。
2.2.4 常量的命名
常量所有的字母均为大写。并且单词之间使用下划线”_”隔开。
2.2.5 函数/过程的命名
函数/过程名称应该尽量使用能够表达函数功能的英文名称,函数名称中应该禁止使用如同function1,function2等含义不清的名称。单词间应该使用大小写分隔。全局函数/过程名称以“g_”前缀开始。
2.2.6 接口命名
接口名称要以大写字母开头。如果接口包含多个单词,每个单词的首字母大写,其他字母小写2.2.7 类的命名
2.2.8 方法的命名
方法名称以小写字母开头;
方法名称如果包含多个单词,除了第一个单词外,每个单词的首字母大写,其它字母小写。如果这些单词是缩略语(例如XML),也要首字母大写,其它字母小写(写作Xml)。
方法名称应该是一个动词或动名词短语,意思是“完成什么功能”,“执行什么操作”;
2.3 参数的约定
2.3.1 输入参数的约定
有些函数有输入参数,这些参数指由函数外部(调用者)输入,并在函数内部使用。在函数业务流程说明后跟输入参数说明区,用“输入参数”或“Input Parameters”标记。在参数名列表中的每个参数后增加该参数的注释。
2.3.2 输出参数的约定
有些函数有输出参数,这些参数指由函数外部(调用者)定义,在函数内部使用并返回给调用者的参数。

2.3.3 返回值的约定
每个函数均有返回值,除非操作非常简单。\返回值说明,要说明各种不同类型返回值以及它们的含义。
2.4 注释约定
在软件中对每个文件头,自定义函数和变量,重要的处理过程都要有必要的注释。
2.4.1 源程序头的注释和规范
每个文件头插入注释,标明文件的用途和作者,注释如下:(注释尽量用中文)
//程序名称
//版权说明
//版本号:
//其他
2.4.2 函数的注释
每个函数前面注明函数的功能和输入,输出。注释为:
//名称
//功能:(说明函数的功能)
//输入参数:(说明每个输入参数的用途和取值约定)
//输出参数:(说明每个输出参数的用途和取值约定)
//返回:(说明返回值,返回值的含义和约定)
2.4.3 变量注释
直接在变量后面注明变量的用途和取值约定,

2.4.4 类型定义注释
2.4.5 注释
码通常使用几个函数和过程来实现某一项功能,这时候需要使用区注释将这些具有共同目的的函数和过程标明出来。
使用整行的”*”作为隔离行,让程序清晰可读。
一般删除的代码不建议直接删除,最好用“//”注释起来。
2.4.6 代码中的注释
在代码中要求注释的地方有:
代码中的关键部分;
在使用特殊算法或者逻辑性较强的代码;
在修改或删除代码部分,需要加注释;修改/删除人,目的.
2.5 变量的作用范围
尽量做到缩小变量的作用范围,对于变量是指针的,应遵循以下约定:
在局部分配的空间在局部释放。
函数体内不能分配空间并将空间指针作为函数参数返回。
动态全局空间在程序结束时一定要释放。
所有动态分配的空间在对应层次的模块释放,并且用完马上释放。不重复释放相同的指针。
2.6 函数/过程的定义
在函数的定义处应当增加本函数的功能描述的注释。
用一句话描述清楚功能。
可用英文或中文。
功能注释格式要求所有代码一致。
2.7 函数业务流程的定义
在函数功能描述后,要增加函数的主要业务流程注释。
可以用多行描述,以解释清楚业务流程为主。
可用英文或中文。
业务流程注释格式要求所有代码一致。
业务流程注释可以尽量详细,注释的长度可以与代码长度差不多,但是不要太长。
注意:函数业务流程的说明并不在乎有多长,但是在乎能否说明过程。有些像N阶乘的函数流程比较简单,但是有些比较复杂。当比较复杂时,可以用标号来说明。
3. 接口/函数过程调用的约定
几乎每一个项目中,都存在开发接口API给其他应用调用。
3.1 头文件
提供给使用API的应用的标准头文件。头文件必须包含三部分。
防止调用文件重复引用的编译条件

函数定义
函数的定义是为了方便应用知道LIB、DLL里引出了怎样的API,应该如何使用。如上面的例子。
错误代码定义
错误代码是接口API里因为内部某种错误返回的代码,它告诉应用出现了什么错误,以便开发者进行调试和排错。
3.2 函数
提供给应用调用的执行体。实现函数时,必须根据以下规范开发
3.2.1 变量定义
在函数代码中,变量的定义必须放在第一部分,同时给指针类型的变量赋空(NULL)。
3.2.2 参数合法性检查
在使用应用传递的输入输出参数之前,必须对参数进行合法性检查,保证代码执行使用参数的安全性。比如,应用的一个输出参数地址为NULL,如果处理之前不检查参数的合法性,那么将导致一个内存错误;如果检查合法性,就不会造成代码执行时出现问题。
3.2.3执行处理
在处理代码开发中,必须注意以下的一系列的问题:
必须先分配系统资源,才能分配函数内部需要的资源;相反,必须首先释放函数内部分配的资源,再释放系统资源。
3.2.4 返回值
4. 错误和异常处理规范
4.1 出错类型定义约定
在整个系统软件产品的出错定义要一致;
统一模块层次的出错类型统一定义;
出错类型分为错误、警告、提示等三类信息,

错误代码统一用宏描述,并且放在一个头文件中;
例子string GetLastErrorStr() {
int l_error_0 = GetLastError();
switch (l_error_0) {
case 0/* NO_ERROR */:
return ("没有错误返回." + "[" + l_error_0 + "]");
case 1/* NO_RESULT */:
return ("没有错误返回,但结果不明." + "[" + l_error_0 + "]");
case 2/* COMMON_ERROR */:
return ("一般错误." + "[" + l_error_0 + "]");
case 3/* INVALID_TRADE_PARAMETERS */:
return ("无效的交易参数." + "[" + l_error_0 + "]");
case 4/* SERVER_BUSY */:
return ("交易服务器繁忙." + "[" + l_error_0 + "]");
case 5/* OLD_VERSION */:
return ("客户终端版本太旧." + "[" + l_error_0 + "]");
case 6/* NO_CONNECTION */:
return ("没有连接到服务器." + "[" + l_error_0 + "]");
case 7/* NOT_ENOUGH_RIGHTS */:
return ("没有足够权限进行相应操作." + "[" + l_error_0 + "]");
case 8/* TOO_FREQUENT_REQUESTS */:
return ("请求过于频繁." + "[" + l_error_0 + "]");
case 9/* MALFUNCTIONAL_TRADE */:
return ("交易运行故障." + "[" + l_error_0 + "]");
case 64/* ACCOUNT_DISABLED */:
return ("帐户被禁止." + "[" + l_error_0 + "]");
case 65/* INVALID_ACCOUNT */:
return ("无效的帐户." + "[" + l_error_0 + "]");
case 128/* TRADE_TIMEOUT */:
return ("交易超时." + "[" + l_error_0 + "]");
case 129/* INVALID_PRICE */:
return ("无效的价格." + "[" + l_error_0 + "]");
case 130/* INVALID_STOPS */:
return ("无效的止损价格." + "[" + l_error_0 + "]");
case 131/* INVALID_TRADE_VOLUME */:
return ("无效的下单量." + "[" + l_error_0 + "]");
case 132/* MARKET_CLOSED */:
return ("市场已关闭." + "[" + l_error_0 + "]");
case 133/* TRADE_DISABLED */:
return ("交易被禁止." + "[" + l_error_0 + "]");
case 134/* NOT_ENOUGH_MONEY */:
return ("资金不足." + "[" + l_error_0 + "]");
case 135/* PRICE_CHANGED */:
return ("价格已变化." + "[" + l_error_0 + "]");
case 136/* OFF_QUOTES */:
return ("开价." + "[" + l_error_0 + "]");
case 137/* BROKER_BUSY */:
return ("经纪人繁忙." + "[" + l_error_0 + "]");
case 138/* REQUOTE */:
return ("重新开价." + "[" + l_error_0 + "]");
case 139/* ORDER_LOCKED */:
return ("定单被锁定." + "[" + l_error_0 + "]");
case 140/* LONG_POSITIONS_ONLY_ALLOWED */:
return ("只允许开多仓." + "[" + l_error_0 + "]");
case 141/* TOO_MANY_REQUESTS */:
return ("请求过多." + "[" + l_error_0 + "]");
case 145/* TRADE_MODIFY_DENIED */:
return ("因为价格过于接近市价,所以操作被拒绝." + "[" + l_error_0 + "]");
case 146/* TRADE_CONTEXT_BUSY */:
return ("交易作业忙." + "[" + l_error_0 + "]");
case 147/* ERR_TRADE_EXPIRATION_DENIED */:
return ("服务器禁止设定过期时间." + "[" + l_error_0 + "]");
case 148/* ERR_TRADE_TOO_MANY_ORDERS */:
return ("开单和挂单总数已被经纪限定." + "[" + l_error_0 + "]");
}
return ("未知错误." + "[" + l_error_0 + "]");
}

注意:出错类型的定义一定要统一,并且一定要注意编码问题。
4.2异常的捕获
在程序中会出现各种异常,如除0错误、内存错误都要处理。要有异常可能的都要捕获。
4.3异常和错误的处理
每个函数独立处理内部的异常,对影响结果的异常通过返回值返回。对于在函数内部不能处理的异常,捕获后已另外的形式向调用者抛出,但是要在接口文档中详细写明。
注意:处理异常一般有两种方法,一是通过将异常转化为另一个异常抛出,二是通过函数返回值返回。在本规范中,我们倾向于用第二种方法。

好了,写的太多了,估计大家没有耐心看这些枯燥的语言了,有兴趣的请联系QQ:1031130533

老大:MQL4语言好象异类指标之间不能比较?比如布林和K线

WFBI
65
WFBI 2009.11.18 08:48  
你的定义的类型必须相同
WFBI
65
WFBI 2009.11.25 08:16  

大家多练习啊

WFBI
65
WFBI 2009.12.02 11:52  
学习
WFBI
65
WFBI 2010.01.02 06:44  
只有规范,才能提高
WFBI
65
WFBI 2010.01.02 06:44  
只有规范,才能提高
eaf
72
eaf 2010.01.02 21:29  
WFBI 写道 >>
只有规范,才能提高

写这么多规范,确实可以提高,不过提高的只是编程水平,而不是交易水平,程序写的再好再规范,但是无法在市场当中赚钱,那又有什么用呢.呵呵

qian2qian
6
qian2qian 2010.01.03 04:52  

有这方面的书籍吗? 谢谢

12
要添加评论,请登录注册