论坛全局菜单下方 - TICKMILL 285X70论坛全局菜单下方 - ThinkMarkets285X70论坛全局菜单下方 - 荔枝返现285X70论坛全局菜单下方 -  icmarkets285X70
  • 1
  • 2
前往
共 37 条
查看:3995回复:36
一苇渡江
注册时间2005-11-24
[原创]MT 4.0编程Step by Step
楼主发表于:2006-03-14 11:28只看该作者倒序浏览
1楼 电梯直达
电梯直达
MT4.0和3.x相比,编程语言迥然不同,基本上是C语言的翻版,所以有一些C语言基础是很容易学会MT编程的。 MT4.0可以编写的程序有好几类,主要是自动交易程序和指标,估计大家都是为了给自己的投资策略,由于我的精力有限,所以接下来只介绍自动交易程序。 1. MT程序的语法 MT程序既然是C语言的翻版,语法和C语言当然很接近了,用有限的篇幅来说明其语法似乎是一个不能完成的任务,我这里只能告诉大家如何去学习。 语法说明可以在Meta Editor的帮助中找到,在工具栏上点MQL Navigator,就会弹出MT编程的导航,其中Dictionary就是语言和函数库的帮助。 在这个树状帮助目录下,语法的说明在Basic下,主要包括Syntax, Data type, Operations & Expressions, Operators, Functions, Variables, Preprocessor 如果会C的话,粗略看一下即可,如果不会,结合例程学习一遍吧。 由于帮助基本是英文的,所以刚开始学还是有难度的,不过没有办法,我也帮不上忙,大家有问题就提吧,我尽量回答。啥时候能出个中文版的就好了。 学习的时候,从网上搜一些现成的程序进行学习和修改是加快学习的一个办法,上一次我贴的Grid的交易程序就是一个很好的学习的例子。 2. 函数库 MT的函数库帮助进行了分类,看起来还是比较方便的。这里也没有办法详细介绍,做一个扼要介绍。 还是在帮助的Dictionary下,看这些帮助要考验一下大家的英文,特别要涉及到金融和计算机专业英语。 包括以下几类: (1) Stardard constants 也就是系统定义的标准常量,主要是一些枚举类型和窗口常量等,一般先不用管它,在别的地方会链接过来。 (2) Predifined variables 一些系统常量,包括买入价,卖出价,最高、最低价等,还是很有用的,不过不太多,挨个儿看一下吧。 (3) Account Information 账户有关的函数 (4) Array functions 数组处理函数。 (5) Common functions 常用处理函数。 (6) Conversion functions 转换函数,主要是字符串和主要类型之间的转换函数。 (7) Custom Indicators 编写自定义指标用到的函数,如果不编写自定义指标的话,可以不管它。 (8) Date&Time functions 时间日期有关的函数 (9) File functions 文件处理函数 (10) Globle variables 全局变量有关的处理函数。 (11) Math & Trig 数学计算函数 (12)Object functions 对象处理函数,主要是在图表中处理对象的函数,对象是指直线、文本等。 (13) String functions 字符串处理函数。 (14) Technical indicators 技术指标函数,相信大家一定会经常用到的。大家通过指标的英文,应该比较容易看出来谁是谁。 (15) Trading functions 交易函数。这一类对自动交易系统是很重要的。 (16) Window functions 窗口处理函数,基本不需要用到。 3. 创建程序 在MT的程序组中,有一个Meta Editor,这就是MT的编译器,还是很容易上手的。用过Visual Studio C++的人一看,有点熟,对吧? 首先,点击菜单File->New,弹出对话框,程序类型选择Expert Advisor,后面按导航操作输入名称即可。 这样一个简单的MT空白交易程序就创建了,点按钮Compile或直接按快捷键F5就可以编译通过了。因为是空白的,这时候它什么也不能干。 注意:自动交易程序一定要存放在安装目录下的Experts子目录。 4. 修改 (1)全局变量 在程序的开头,可以定义一下全局变量。前面加extern的全局变量的值,在自动交易程序启动的时候可以直接在MT改,不需要重新编译。 (2)入口函数 MT程序的调用入口是start()函数,和C程序的main()函数是一样的,一般就在这里写处理过程即可。 (3) 子函数 比较复杂的过程,可以写子函数,在start()函数里调用子函数。 5. 例程:以下是在MT官方网站的论坛下hdb写的Grid自动交易程序,供参考。 //+------------------------------------------------------------------+ //| MakeGrid.mq4 | //| Copyright ? 2005, hdb | //| http://www.dubois1.net/hdb | //+------------------------------------------------------------------+ #property copyright "Copyright ? 2005, hdb" #property link "http://www.dubois1.net/hdb" //#property version "1.8" // DISCLAIMER ***** IMPORTANT NOTE ***** READ BEFORE USING ***** // This expert advisor can open and close real positions and hence do real trades and lose real money. // This is not a 'trading system' but a simple robot that places trades according to fixed rules. // The author has no pretentions as to the profitability of this system and does not suggest the use // of this EA other than for testing purposes in demo accounts. // Use of this system is free - but u may not resell it - and is without any garantee as to its // suitability for any purpose. // By using this program you implicitly acknowledge that you understand what it does and agree that // the author bears no responsibility for any losses. // Before using, please also check with your broker that his systems are adapted for the frequest trades // associated with this expert. // 1.8 changes // made wantLongs and wantShorts into local variables. Previously, if u set UseMACD to true, // it did longs and shorts and simply ignored the wantLongs and wantShorts flags. // Now, these flags are not ignored. // added a loop to check if there are 'illicit' open orders above or below the EMA when the limitEMA34 // flag is used. These accumulate over time and are never removed and is due to the EMA moving. // removed the switch instruction as they dont seem to work - replaced with if statements // made the EMA period variable // // // modified by cori. Using OrderMagicNumber to identify the trades of the grid extern int uniqueGridMagic = 11111; // Magic number of the trades. must be unique to identify // the trades of one grid extern double Lots = 0.1; // extern double GridSize = 6; // pips between orders - grid or mesh size extern double GridSteps = 12; // total number of orders to place extern double TakeProfit = 12 ; // number of ticks to take profit. normally is = grid size but u can override extern double StopLoss = 0; // if u want to add a stop loss. normal grids dont use stop losses extern double UpdateInterval = 1; // update orders every x minutes extern bool wantLongs = true; // do we want long positions extern bool wantShorts = true; // do we want short positions extern bool wantBreakout = true; // do we want longs above price, shorts below price extern bool wantCounter = true; // do we want longs below price, shorts above price extern bool limitEMA = false; // do we want longs above ema only, shorts below ema only extern int EMAperiod = 34; // the length of the EMA.. was previously fixed at 34 extern double GridMaxOpen = 0; // maximum number of open positions : not yet implemented.. extern bool UseMACD = false; // if true, will use macd >0 for longs only, macd >0 for shorts only // on crossover, will cancel all pending orders. This will override any // wantLongs and wantShort settings - at least for now. extern bool CloseOpenPositions = false;// if UseMACD, do we also close open positions with a loss? extern bool doHouseKeeping = true; // just a test // modified by cori. internal variables only string GridName = "Grid"; // identifies the grid. allows for several co-existing grids double LastUpdate = 0; // counter used to note time of last update //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { //---- #property show_inputs // shows the parameters - thanks Slawa... //---- // added my corri and removed by hdb!! lol.. just to stay compatible with open grids... // GridName = StringConcatenate( "Grid", Symbol() ); return(0); } //+------------------------------------------------------------------------+ //| tests if there is an open position or order in the region of atRate | //| will check for longs if checkLongs is true, else will check | //| for shorts | //+------------------------------------------------------------------------+ bool IsPosition(double atRate, double inRange, bool checkLongs ) { int totalorders = OrdersTotal(); for(int j=0;j=0;j--) // scan all orders and positions... { OrderSelect(j, SELECT_BY_POS); // modified as per cori. Using OrderMagicNumber to identify the trades of the grid // hdb added or gridname for compatibility if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) ) // only look if mygrid and symbol... { int type = OrderType(); if ( type > 1 ) bool result = OrderDelete( OrderTicket() ); } } return; } //+------------------------------------------------------------------------+ //| cancells all pending orders and closes open positions | //+------------------------------------------------------------------------+ void CloseOpenOrders() { int total = OrdersTotal(); for(int i=total-1;i>=0;i--) { OrderSelect(i, SELECT_BY_POS); int type = OrderType(); bool result = false; // modified by cori. Using OrderMagicNumber to identify the trades of the grid // hdb added or gridname for compatibility if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) ) // only look if mygrid and symbol... { //Close opened long positions if ( type == OP_BUY ) result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), 5, Red ); //Close opened short positions if ( type == OP_SELL ) result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), 5, Red ); //Close pending orders if ( type > 1 ) result = OrderDelete( OrderTicket() ); } } return; } //+------------------------------------------------------------------------+ //| cancells all open orders which fall on the wrong side of the EMA | //+------------------------------------------------------------------------+ void CloseOrdersfromEMA( double theEMAValue ) { int totalorders = OrdersTotal(); for(int j=totalorders-1;j>=0;j--) // scan all orders and positions... { OrderSelect(j, SELECT_BY_POS); if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) ) // only look if mygrid and symbol... { int type = OrderType(); bool result = false; //if (type > 1) Print(type," ",theEMAValue," ",OrderOpenPrice()); if ( type == OP_BUYLIMIT && OrderOpenPrice() <= theEMAValue ) result = OrderDelete( OrderTicket() ); if ( type == OP_BUYSTOP && OrderOpenPrice() <= theEMAValue ) result = OrderDelete( OrderTicket() ); if ( type == OP_SELLLIMIT && OrderOpenPrice() >= theEMAValue ) result = OrderDelete( OrderTicket() ); if ( type == OP_SELLSTOP && OrderOpenPrice() >= theEMAValue ) result = OrderDelete( OrderTicket() ); } } return; } //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int start() { //---- int i, j,k, ticket, entermode, totalorders; bool doit; double point, startrate, traderate; //---- setup parameters if ( TakeProfit <= 0 ) // { TakeProfit = GridSize; } bool myWantLongs = wantLongs; bool myWantShorts = wantShorts; //---- if (MathAbs(CurTime()-LastUpdate)> UpdateInterval*60) // we update the first time it is called and every UpdateInterval minutes { LastUpdate = CurTime(); point = MarketInfo(Symbol(),MODE_POINT); startrate = ( Ask + point*GridSize/2 ) / point / GridSize; // round to a number of ticks divisible by GridSize k = startrate ; k = k * GridSize ; startrate = k * point - GridSize*GridSteps/2*point ; // calculate the lowest entry point double myEMA=iMA(NULL,0,EMAperiod,0,MODE_EMA,PRICE_CLOSE,0); if (limitEMA) { if (doHouseKeeping) CloseOrdersfromEMA(myEMA); } if ( UseMACD ) { double Macd0=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0); double Macd1=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1); double Macd2=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,2); if( Macd0>0 && Macd1>0 && Macd2<0) // cross up { CloseAllPendingOrders(); if ( CloseOpenPositions == true ) { CloseOpenOrders(); } } if( Macd0<0 && Macd1<0 && Macd2>0) // cross down { CloseAllPendingOrders(); if ( CloseOpenPositions == true ) { CloseOpenOrders(); } } myWantLongs = false; myWantShorts = false; if( Macd0>0 && Macd1>0 && Macd2>0 && wantLongs ) // is well above zero { myWantLongs = true; } if( Macd0<0 && Macd1<0 && Macd2<0 && wantShorts ) // is well below zero { myWantShorts = true; } } for( i=0;i myEMA)) { if ( IsPosition(traderate,point*GridSize,true) == false ) // test if i have no open orders close to my price: if so, put one on { double myStopLoss = 0; if ( StopLoss > 0 ) { myStopLoss = traderate-point*StopLoss ; } if ( traderate > Ask ) { entermode = OP_BUYSTOP; } else { entermode = OP_BUYLIMIT ; } if ( ((traderate > Ask ) && (wantBreakout)) || ((traderate <= Ask ) && (wantCounter)) ) { // modified by cori. Using OrderMagicNumber to identify the trades of the grid ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate+point*TakeProfit,GridName,uniqueGridMagic,0,Green); } } } if ( myWantShorts && (!limitEMA || traderate < myEMA)) { if (IsPosition(traderate,point*GridSize,false)== false ) // test if i have no open orders close to my price: if so, put one on { myStopLoss = 0; if ( StopLoss > 0 ) { myStopLoss = traderate+point*StopLoss ; } if ( traderate > Bid ) { entermode = OP_SELLLIMIT; } else { entermode = OP_SELLSTOP ; } if ( ((traderate < Bid ) && (wantBreakout)) || ((traderate >= Bid ) && (wantCounter)) ) { // modified by cori. Using OrderMagicNumber to identify the trades of the grid ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate-point*TakeProfit,GridName,uniqueGridMagic,0,Red); } } } } } return(0); } //+------------------------------------------------------------------+ [ 本帖最后由 管理员No.6 于 2006-3-14 19:32 编辑 ]
TK29帖子1楼右侧xm竖版广告90-240
个性签名

谋定而后动

广告
TK30+TK31帖子一樓廣告
TK30+TK31帖子一樓廣告
一苇渡江
注册时间2005-11-24
楼主发表于:2006-03-14 11:31只看该作者
2楼
这个只是入门的东东,有问题请在这个帖子下提,偶尽量回答。
airman888
注册时间2005-11-03
积极参与奖
发表于:2006-03-14 11:40只看该作者
3楼
入。。。。。。。。门。。。。。。。。。。。。。。
个性签名

哎,又浪费一个小时,我为什么什么事情都那么认真?以后尽量不上论坛了。

一苇渡江
注册时间2005-11-24
楼主发表于:2006-03-14 11:41只看该作者
4楼
自动交易系统的测试 很多人都想用历史数据测试自己的自动交易系统结果怎么样。 在MT的View菜单下,有一个Strategy tester。 选定自己的交易系统,设定好币种,历史数据的时间周期,交易系统的属性,勾上Recalculate,设定时间范围,点Start按钮即开始测试。 特别强调的是,由于历史数据不能反映内部的波动情况,测试中可以选择三种插值方式,但是因为要使用插值,测试结果可能是不准确的,尤其是在以下两种情况下: (1) 有止损的策略 (2) 使用的TimeFrame比较大
奔跑中
注册时间2005-11-07
图文并茂奖
一苇渡江
注册时间2005-11-24
楼主发表于:2006-03-14 11:49只看该作者
6楼
原帖由 奔跑中 于 2006-3-14 19:45 发表 太难了,俺不会,嘿嘿
没关系,我教你。:handshake:handshake:handshake 只收你利润的一半做学费。:lol:lol:lol
奔跑中
注册时间2005-11-07
图文并茂奖
发表于:2006-03-14 11:55只看该作者
7楼
原帖由 一苇渡江 于 2006-3-14 19:49 发表 没关系,我教你。:handshake:handshake:handshake 只收你利润的一半做学费。:lol:lol:lol
嗬嗬,俺是电脑盲,嘿嘿,你的那些符号俺都不懂,:lol:lol:lol:lol 现成的有没让俺看看,嘿嘿:lol:lol:lol:lol
望云
注册时间2005-12-08
发表于:2006-03-14 11:59只看该作者
8楼
收藏了,可惜我E文太次了。
GOLDMEDAL
注册时间2005-08-23
发表于:2006-03-14 12:09只看该作者
9楼
谢谢,收藏了慢慢学
梦靥
注册时间2005-06-09
发表于:2006-03-14 12:48只看该作者
10楼
留名收藏,不晓得楼主给人编一个收多少MM?
个性签名

韬客社区www.talkfx.co

广告
论坛谏言--外汇交易不应是你投资的全部,交易外汇也不应是你生活的全部
一苇渡江
注册时间2005-11-24
楼主发表于:2006-03-14 13:02只看该作者
11楼
原帖由 梦靥 于 2006-3-14 20:48 发表 留名收藏,不晓得楼主给人编一个收多少MM?
暂不收费,呵呵!纯粹处于兴趣。
afeng
注册时间2005-12-31
发表于:2006-03-14 13:13只看该作者
12楼
大老,有空举个例,一句一个中文的,随便什么指标。。, 不胜感谢!!!
一苇渡江
注册时间2005-11-24
楼主发表于:2006-03-14 13:53只看该作者
13楼
原帖由 afeng 于 2006-3-14 21:13 发表 大老,有空举个例,一句一个中文的,随便什么指标。。, 不胜感谢!!!
找了一个根据均线交易的例子,我自己择主要的加了一些中文注释,看看有没有帮助。 //+------------------------------------------------------------------+ //| Moving Average.mq4 | //| Copyright ?2005, MetaQuotes Software Corp. | //| http://www.metaquotes.net/ | //+------------------------------------------------------------------+ #define MAGICMA 20050610 // extern的全局变量,编译后可以直接在MT中修改 extern double Lots = 0.1; extern double MaximumRisk = 0.02; extern double DecreaseFactor = 3; extern double MovingPeriod = 12; extern double MovingShift = 6; //+------------------------------------------------------------------+ //| 入口函数,程序从这里开始运行 | //+------------------------------------------------------------------+ void start() { //---- if(Bars<100 //如果历史数据不足100根K线 || IsTradeAllowed()==false) // 或者系统目前不允许交易 return; // 退出 //---- if(CalculateCurrentOrders(Symbol())==0)// 调用子函数CalculateCurrentOrders检查现有仓位,是否需要建仓 CheckForOpen(); // 调用子函数CheckForOpen开始建立仓位 else CheckForClose(); // 否则检查是否需要平仓 //---- } //+------------------------------------------------------------------+ //| 检查现有仓位| //+------------------------------------------------------------------+ int CalculateCurrentOrders(string symbol) { int buys=0,sells=0; //---- for(int i=0;i0) return(buys); // 有至少一张买单,返回买单数量 else return(-sells); // 否则,返回卖单数量的负值 } //+------------------------------------------------------------------+ //| 计算最优仓位 //+------------------------------------------------------------------+ double LotsOptimized() { double lot=Lots; int orders=HistoryTotal(); // history orders total int losses=0; // number of losses orders without a break //---- select lot size lot=NormalizeDouble(AccountFreeMargin()*MaximumRisk/1000.0,1); //---- calcuulate number of losses orders without a break if(DecreaseFactor>0) { for(int i=orders-1;i>=0;i--) { if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) { Print("Error in history!"); break; } if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue; //---- if(OrderProfit()>0) break; if(OrderProfit()<0) losses++; } if(losses>1) lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1); } //---- return lot size if(lot<0.1) lot=0.1; return(lot); } //+------------------------------------------------------------------+ //| 检查是否建仓 | //+------------------------------------------------------------------+ void CheckForOpen() { double ma; int res; //---- go trading only for first tiks of new bar if(Volume[0]>1) return; //---- 指标调用,iMA就是均线(Moving Average) ma=iMA(NULL,0,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE,0); //---- sell conditions if(Open[1]>ma && Close[1]ma) { res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,0,"",MAGICMA,0,Blue); return; } //---- } //+------------------------------------------------------------------+ //| 检查是否平仓 | //+------------------------------------------------------------------+ void CheckForClose() { double ma; //---- go trading only for first tiks of new bar if(Volume[0]>1) return; //---- get Moving Average ma=iMA(NULL,0,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE,0); //---- for(int i=0;ima && Close[1]ma) OrderClose(OrderTicket(),OrderLots(),Ask,3,White); break; } } //---- }
一苇渡江
注册时间2005-11-24
楼主发表于:2006-03-14 14:14只看该作者
15楼
原帖由 道拉德 于 2006-3-14 22:07 发表 还是懵懂
要是看几眼就能学会编程,中国也就不缺软件工程师了。 偶做了八年软件,还花了一个星期才学会呢,就这,我还觉得自己算是学的快的呢,呵呵! [ 本帖最后由 一苇渡江 于 2006-3-14 22:16 编辑 ]
金吒
注册时间2006-01-27
发表于:2006-03-14 14:16只看该作者
16楼
好东西啊,顶
途中
注册时间2005-02-05
发表于:2006-03-14 14:17只看该作者
17楼
哦! 已好久没有编过程了!怕都生疏了
望云
注册时间2005-12-08
发表于:2006-03-14 14:49只看该作者
18楼
请教用第二个例调试历史数据,可以用C的fopen()把返回值写到一个文件吗? 我没学过作图函数。
个性签名

进程:开户->理性分析师->理性投注师

一苇渡江
注册时间2005-11-24
楼主发表于:2006-03-14 15:13只看该作者
19楼
原帖由 望云 于 2006-3-14 22:49 发表 请教用第二个例调试历史数据,可以用C的fopen()把返回值写到一个文件吗? 我没学过作图函数。
有类似的函数,前面介绍库函数的时候,其中有一组帮助是关于文件操作的函数。可以查以下帮助。
afeng
注册时间2005-12-31
发表于:2006-03-14 15:27只看该作者
20楼
原帖由 一苇渡江 于 2006-3-14 21:53 发表 找了一个根据均线交易的例子,我自己择主要的加了一些中文注释,看看有没有帮助。 //+------------------------------------------------------------------+ //| ...
:P 好人哪!谢谢!!!
  • 1
  • 2
前往
共 37 条

本站免责声明:

1、本站所有广告及宣传信息均与韬客无关,如需投资请依法自行决定是否投资、斟酌资金安全及交易亏损风险;

2、韬客是独立的、仅为投资者提供交流的平台,网友发布信息不代表韬客的观点与意思表示,所有因网友发布的信息而造成的任何法律后果、风险与责任,均与韬客无关;

3、金融交易存在极高法律风险,未必适合所有投资者,请不要轻信任何高额投资收益的诱导而贸然投资;投资保证金交易导致的损失可能超过您投入的资金和预期。请您考虑自身的投资经验及风险承担能力,进行合法、理性投资;

4、所有投资者的交易帐户应仅限本人使用,不应交由第三方操作,对于任何接受第三方喊单、操盘、理财等操作的投资和交易,由此导致的任何风险、亏损及责任由投资者个人自行承担;

5、韬客不隶属于任何券商平台,亦不受任何第三方控制,韬客不邀约客户投资任何保证金交易,不接触亦不涉及投资者的任何资金及账户信息,不代理任何交易操盘行为,不向客户推荐任何券商平台,亦不存在其他任何推荐行为。投资者应自行选择券商平台,券商平台的任何行为均与韬客无关。投资者注册及使用韬客即表示其接受和认可上述声明,并自行承担法律风险。

版权所有:韬客外汇论坛 www.talkfx.com 联络我们:[email protected]