Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >MQL5从入门到精通【第五章】函数function

MQL5从入门到精通【第五章】函数function

作者头像
程序员小助手
发布于 2020-04-08 03:20:03
发布于 2020-04-08 03:20:03
1.6K00
代码可运行
举报
文章被收录于专栏:程序员小助手程序员小助手
运行总次数:0
代码可运行

讲完了数据类型,操作语句,接着我们把这些元素组合在一起使用。封装起来,成为函数。可供程序内调用,减少冗余代码,提高代码可维护性,降低程序复杂度。

function是一组代码块,用于完成特定动作,比如处理一个订单,调整止损价位等。我们的教程中,会讲到不少自建的函数,用于完成交易相关的动作。MQL5也提供了许多内置函数,从简单的获取订单信息,到复杂的数学运算,都可信手拈来,直接使用。

好比积木,函数精简为一个一个独立的积木块,然后我们使用程序,将独立的积木块搭建成复杂的结构。

抽象出来的函数,一定要精简,要获取订单信息,那好了,我根据需要的传入参数,传入该函数,它给我返回订单信息便是。程序的任意位置,均可调用。

函数一般要有返回值,当然没有返回值也可以,声明的时候冠以void关键字即可。下面举例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
double BuyStopLoss(string pSymbol, int pStopPoints, double pOpenPrice)
{
    // 代码块
}

函数要求传入三个参数,返回一个double类型数据。按照规则写就OK了。注意三个参数都必须填写,是必填项,不能缺省。字符类型的 pSymbol,整型的 pStopPoints,实数 pOpenPrice。

下面我们实现一个功能,根据三个参数,给函数计算返回值。补充函数代码块部分:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
double BuyStopLoss(string pSymbol, int pStopPoints, double pOpenPrice)
{
    double stopLoss = pOpenPrice - (pStopPoints * _Point);
    stopLoss = NormalizeDouble(stopLoss,_Digits);
    return(stopLoss);
}

逐句分析。

double stopLoss = pOpenPrice - (pStopPoints * _Point);

使用开盘价格,减去 止损点与货币报价中当前交易品种的大小点的成绩,计算出来的就是止损价格。注意使用了_Point预定义常量。

stopLoss = NormalizeDouble(stopLoss,_Digits);

此处_Digits也是系统预定义常量。定义当前图表交易品种的价格精确度。使用NormalizeDouble格式化小数保留相应的精度。

return(stopLoss);

返回计算后的值stopLoss。这就是函数的返回值。函数执行到此,直接返回,如果后面还有语句,并不执行。

所以您看到了,函数体内,也有提前终端执行,跳出函数的方法,就是使用return返回。这与上一章循环中的break与异曲同工之处。

准备好这个函数,我们可以在程序中用一用,体现一下其价值。我们定义一个输入变量,用于与用户交互,让用户输入止损价,然后在onTick事件处理中调用此函数。

onTick 当NewTick事件发生时在EA中调用这个函数,来处理一个新报价。

也就是报价有更新时,调用此事件内的程序。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 定义输入变量
input int StopLoss = 500;

// onTick事件
double orderPrice = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
double useStopLoss = BuyStopLoss(_Symbol,StopLoss,orderPrice);

注意,函数要先定义再使用。可以在头部定义,如果是公用函数,单独写出来,在顶部引入即可。

## 默认值

如果一个函数,接收5个参数,但是有些并不是经常变化的参数,或者在函数调用的时候,是否能够选填呢,作为可选参数?可以的。在声明函数的形参中,给其默认值,那么在调用的时候,就可以不给这个位置传参。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
double BuyStopLoss(string pSymbol, int pStopPoints, double pOpenPrice = 0)
{
    double stopLoss = pOpenPrice - (pStopPoints * _Point);
    stopLoss = NormalizeDouble(stopLoss,_Digits);
    return(stopLoss);
}

上述同样的函数定义,我们在形参中声明pOpenPrice默认=0。那么如果调用BuyStopLoss时,这个位置的参数如果不传,函数体内,pOpenPrice就用0.0这个默认值了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
BuyStopLoss(_Symbol,StopLoss);

就想上面这个一样。

那是不是我只要声明了默认值的参数位置,就可以不填了呢?不可以!可选参数列表放在形参的尾部,这样可变参数在前,不变参数在后,写的时候,你就可以像下面这样用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
double grad(int x1=1,int y1=2,int x2=3,int y2=4){
    return (y2-y1)/(x2-x1);
}

上述函数计算两个点的斜率。坐标点都有默认值,调用的时候,下面的使用方法都是正确的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
grad();
grad(1);
grad(1,2);
grad(1,2,3);
grad(1,2,3,4);

我们再看必选参数在中间的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
double grad(int x1 = 1, int y1, int x2 = 3, int y2 = 4){
    return (y2-y1)/(x2-x1);
}

那么调用的时候,只能有以下写法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
grad(1,2);
grad(7,3,3,5);

也就是第二个参数,是必填的。无论前面的是否可选,前面的也得填。所以,最佳实践就是把可选参数放后面去。

## return 操作符

像上面所说的,如果提前终结函数运行,可以直接return。函数运行到return这个位置,就跳出了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int ga(double price, bool is_half){
    if(is_half== false) return(price * price);
    else return(price / 2);
    Print('Never exec');
    return(0);
}

因为if-else把两种情况均考虑了,一定会返回一个数值。那么下面的print根本没有机会执行。

## void类型

有时候我们写一个函数,仅仅为了一段功能和动作,可能不不期望有返回值。那么就可以在函数声明前冠以void。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void TradeEmail()
{
    string subject = "Trade placed";
    string text = "A trade was placed on " + _Symbol;
    SendMail(subject,text);
}

这段代码,使用标题和内容发送一封邮件,不期望有返回值,使用void就可以了。函数内大可不必有return操作符。

## 引用传递参数

一般,我们把参数传递给函数,传递的是这个参数的值。参数的值也保持不变。

那么,如果是某个变量,我们想要其在函数处理中改变其数值,怎么办呢?可以使用引用传递。MQL5程序中,数组和结构体,经常用到引用传递reference。

下面的例子,我们引用传递一个结构体给系统函数SymbolInfoTick()。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bool SymbolInfoTick(
    string symbol,
    MqlTick& tick // 引用结构体MqlTick
);

下面是代码中我们的用法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MqlTick myTick;
SymbolInfoTick(_Symbol,myTick);
Print(myTick.bid);

第一行,使用系统内置结构体声明一个变量myTick。

第二行,系统函数调用后将返回值更改了变量myTick。

第三行,值更改后的myTick打印属性。

下面再举一个例子,我们接收一个空数组,将其进行填充。这个函数就需要引用传递。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void fill(int &a[]){
    ArrayResize(a,3);
    a[0] = 1;
    a[1] = 2;
    a[2] = 3;
}

这样做的好处是,不用返回值了,再赋值给原始函数,省去一大段代码。

调用的时候这样用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int f[];
fill(f);
Print(f[0]); // = 1

有没有对引用传递有个质的理解了呢?

## 函数重载

面向对象编程中,我们用到很多概念,如接口,抽象类,继承。那么,在继承层级比较深的类内,有些继承的方法在该类内会有特殊的用法,这时候我们需要重写该方法,也称为“重载”。MQL5函数也可使用重载。说白话就是,同一个函数名,参数不同,写两次。你用的时候,编译器根据传入的参数匹配相应的函数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bool TrailingStop(string pSymbol, int pTrailPoints, int pMinProfit = 0, int pStep = 10);
bool TrailingStop(string pSymbol, double pTrailPrice, int pMinProfit = 0, int pStep = 10);

更改一个参数,函数名保持不变。像下面这样用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bool b;
b = TrailingStop(_Symbol, 549);

系统会判定使用第一个函数,因为第二个参数很显然,int型。像下面这样用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bool b;
b = TrailingSop(_Symbol, 125.89);

系统判定是访问第二个函数,因为第二个参数位置是double型。

这就是重载。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-12-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员小助手 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——15.C++11(2)
C++11 引入的可变模板参数(variadic templates)使得模板参数的数量可以是任意多个,极大地提升了 C++ 的模板编程能力。以下是 C++11 中可变模板参数的详细总结:
hope kc
2025/06/02
820
移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——15.C++11(2)
MQL5从入门到精通【第七章】MQL5程序结构
顶部,是预处理声明;接着是输入变量和全局变量。最后是函数,类,以及定义的程序处理器。
程序员小助手
2020/04/08
1.1K0
MQL5从入门到精通【第二章】变量与数据类型(四)
输入变量是MQL5中仅有的,可供用户修改数值的变量。这些变量可由交易配置,指示器配置,止损收益配置等等组成。这些变量展示在程序的属性窗口。
程序员小助手
2020/04/08
1.1K0
【漆学军】EA编程速成教程(2)第一个程序:下单
大家好,我是漆天编程团队的漆学军,也是MT4专家论坛的创办者,下面是我为大家准备的《EA编程速成教程》第二课。
漆学军
2019/12/27
1.9K0
【漆学军】EA编程速成教程(2)第一个程序:下单
【漆学军】EA编程速成教程(4)修改止损止盈
大家好,我是漆天编程团队的漆学军,也是MT4专家论坛的创办者,下面是我为大家准备的《EA编程速成教程》第四课。
漆学军
2020/04/16
2.3K4
【漆学军】EA编程速成教程(4)修改止损止盈
MQL5从入门到精通「第二章」变量与数据类型(一)
变量是程序必备元素。我们主要讲一下,程序的基础,数据结构的基础,数据类型。因为这是底层的知识,与计算机硬件息息相关。
程序员小助手
2020/04/08
1.8K0
MQL5从入门到精通【第二章】变量与数据类型(三)
枚举是特殊的整数类型,定义了一列常量,用于指代整数值。枚举类型,只有定义了才能使用,没定义了,你找不到它的值,报错!
程序员小助手
2020/04/08
1.2K0
MQL5从入门到精通【第六章】面向对象编程(二)
如果不显式声明构造器,系统会自动创建一个默认的构造器初始化变量。这个默认的构造器并不可见。
程序员小助手
2020/04/08
8910
MQL5从入门到精通【第六章】面向对象编程(一)
MQL5中增加的一个重要特性就是面向对象。面向对象编程提倡代码的重用,对用户隐藏无意义的接口细节。这位灵活创建大型的应用奠定了基础。
程序员小助手
2020/04/08
1.1K0
【漆学军】分享我自用多年的马丁策略EA完整源码(winkey),曾半年将我账户翻3倍
马丁策略一直都是具有很大争议的,因为有太多的人使用这个策略爆仓了,但是依然有人使用这个赚钱了。那些使用这个策略爆仓了的人会认为马丁策略不行,是垃圾,我是不同意这种说法的。
漆学军
2021/06/07
4.4K4
【漆学军】分享我自用多年的马丁策略EA完整源码(winkey),曾半年将我账户翻3倍
MQL5从入门到精通【第二章】变量与数据类型(二)
我们讲了变量和数据类型,都是单个的变量,及其值。那么这个数组,是用来装载多个数据的一种结构。你可以把数组想象为一个数字列表,每个数字对应不同的值。可以从头按照数字遍历这个列表,并获取其相对应的值。
程序员小助手
2020/04/08
1.2K0
Go基础——function函数
我们以写一个计算商品价格的函数为例,输入参数是单件商品的价格和商品的个数,两者的乘积为商品总价,作为函数的输出值。
羊羽shine
2019/05/28
6850
MQL5从入门到精通【第四章】(一)条件判断语句
程序的基础功能之一就是做判断。判断语句通过评估条件的真伪作出决定。MQL5中有三个条件判断语句:if - else,三目操作符,和switch - case语句。
程序员小助手
2020/04/08
1.1K0
【C++11特性篇】lambda表达式玩法全解
YY的秘密代码小屋
2024/01/23
2260
【C++11特性篇】lambda表达式玩法全解
《JavaSE-第五章》之C中的函数-java中的方法
我们在C语言中学习函数,因为我们太懒了懒的写代码,为了提高代码的复用性避免重复的造轮子,我们可以将常用的功能独立成函数,在java中也是如此只是在java中没有函数这个概念,却有等同于函数的东西,那就是方法,接下来让我们走进java中方法,去领略方法的调用,方法的声明周期以及方法重载。
用户10517932
2023/10/07
1890
《JavaSE-第五章》之C中的函数-java中的方法
【C++】C++11——lambda表达式
为了实现一个比较算法, 都要重新去写一个类,如果每次比较的逻辑不一样,还要去实现多个类,特别是相同类的命名,看代码的人就遭殃了,非常的烦,这些都非常地不方便。所以,C++11中的语法Lambda表达式由此登场。
平凡的人1
2023/10/15
1720
【C++】C++11——lambda表达式
Go 从入门到精通(三)字符串,时间,流程控制,函数
coders
2018/01/04
6970
【Python从入门到精通】(十一)Python的函数的方方面面【收藏下来保证有用!!!】
您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦。本文主要介绍Python的函数,函数的定义,使用,可变参数等等都有详细介绍。 干货满满,建议收藏,需要用到时常看看。小伙伴们如有问题及需要,欢迎踊跃留言哦~ ~ ~。
码农飞哥
2021/08/18
4760
杨老师课堂_Java教程第五篇之函数运用
今天主要是讲解以下知识点: 1、方法基础知识 2、方法高级内容 3、方法案例
杨校
2018/12/06
4910
C++lambda表达式
先来说背景:当我们需要对一些的元素进行排序的时候,可以使用std::sort来进行排序,而当需要对一些自定义类型的元素来排序的时候,要去写一个类,或者说是需要写一个仿函数,而如果功能要求上需要根据不同的比较去排序,那就需要写好几个仿函数用于去排序,因此这个是很不方便的,比如下面代码:
二肥是只大懒蓝猫
2023/10/13
1790
推荐阅读
相关推荐
移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——15.C++11(2)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验