📅 财经日历 📊 实时波动 📈 大盘云图 📶 行情走势 🆚 投机情绪 🚀 今日热点

    MT4.0编程函数库

    2013-07-11 · 9496 阅读
    MT4.0编程函数库
    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自动交易程序,供参考。
    #property copyright "***************"
    #property link ""
    //#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 localvariables. 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

    #property copyright "**********"
    #property link ""

    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 {
    OrderSelect(j, SELECT_BY_POS);
    // 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...
    { int type = OrderType();
    if (MathAbs( OrderOpenPrice() - atRate ) < (inRange*0.9)) // dont look for exact price but price proximity (less than gridsize) - added 0.9 because of floating point errors
    { if ( ( checkLongs && ( type == OP_BUY || type == OP_BUYLIMIT || type == OP_BUYSTOP ) ) || (!checkLongs && ( type == OP_SELL || type == OP_SELLLIMIT || type == OP_SELLSTOP ) ) )
    {
    return(true);
    }
    }
    }
    }
    return(false);
    }
    //+------------------------------------------------------------------------+
    //| cancells all pending orders |
    //+------------------------------------------------------------------------+
    void CloseAllPendingOrders( )
    {
    int totalorders = OrdersTotal();
    &bsp; for(int j=totalorders-1;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(), 骗子Info(OrderSymbol(), MODE_BID), 5, Red );
    //Close opened short positions
    if ( type == OP_SELL ) result = OrderClose( OrderTicket(), OrderLots(), 骗子Info(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 = 骗子Info(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
    &nbp; {
    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 {
    traderate = startrate + i*point*GridSize;
    if ( myWantLongs && (!limitEMA || traderate > 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);
    }
    //+------------------------------------------------------------------+
    自动交易系统的测试
    很多人都想用历史数据测试自己的自动交易系统结果怎么样。
    在MT的View菜单下,有一个Strategy tester。
    选定自己的交易系统,设定好币种,历史数据的时间周期,交易系统的属性,勾上Recalculate,设定时间范围,点Start按钮即开始测试。
    特别强调的是,由于历史数据不能反映内部的波动情况,测试中可以选择三种插值方式,但是因为要使用插值,测试结果可能是不准确的,尤其是在以下两种情况下:
    (1) 有止损的策略
    (2) 使用的TimeFrame比较大
    找了一个根据均线交易的例子,我自己择主要的加了一些中文注释,看看有没有帮助。
    //+------------------------------------------------------------------+
    //| Moving Average.mq4 |
    //| Copyright ?2005, MetaQuotes Software Corp. |
    //| http://forexea.com |
    //+------------------------------------------------------------------+
    #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;i {
    if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) // 如果获取Order失败,则退出
    break;
    if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA) // 获取仓位成功
    {
    if(OrderType()==OP_BUY) buys++; // 如果是买单,买单计数器加一
    if(OrderType()==OP_SELL) sells++; // 如果是卖单,卖单计数器加一
    }
    }
    //---- return orders volume
    if(buys>0) return(buys); // 有至少一张买单,返回买单数量
    else return(-sells); // 否则,返回卖单数量的负值
    }

    //+------------------------------------------------------------------+
    //| 计算最优仓位
    //+http://blog.sina.com.cn/zhouxiaoyin18---------------------+
    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] {
    // 建立仓位
    res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,0,"",MAGICMA,0,Red);
    return;
    }
    //---- buy conditions
    if(Open[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;i {
    if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
    if(OrderMagicNumber()!=MAGICMA || OrderSymbol()!=Symbol()) continue;
    //---- check order type
    if(OrderType()==OP_BUY)
    {
    if(Open[1]>ma && Close[1] break;
    }
    if(OrderType()==OP_SELL)
    {
    if(Open[1]ma) OrderClose(OrderTicket(),OrderLots(),Ask,3,White);
    break;
    }
    }
    //----
    }

    ""
    还没有人打赏,支持一下
    回复

    举报

     

    回答|共 25 个

    好和利口酒 LV3

    发表于 2014-11-13 00:52:32 | 显示全部楼层

    多谢分享 看看是什么

    花生牛奶 LV5

    发表于 2014-11-15 03:02:59 | 显示全部楼层

    EA真的能赚钱么?

    hvwrd LV7

    发表于 2014-11-16 01:20:29 | 显示全部楼层

    找版主

    樱花难忘 LV3

    发表于 2014-11-17 03:03:16 | 显示全部楼层


    继续,学习了

    东登 LV3

    发表于 2014-11-18 03:03:22 | 显示全部楼层

    研究研究

    太阳当空照 LV3

    发表于 2018-9-10 12:00:57 | 显示全部楼层

    路过,学习下

    chonglou00 LV4

    发表于 2018-9-25 19:07:46 | 显示全部楼层

    谢谢,赞一个

    bodog LV4

    发表于 2020-3-11 20:02:26 | 显示全部楼层

    不错,支持下楼主

    我说你喜欢我 LV3

    发表于 2020-3-20 20:08:01 | 显示全部楼层

    路过,学习下
    123下一页
    您需要登录后才可以回帖 登录 | 注册

    提醒: 禁止引战、谩骂、灌水内容

    微信二维码

    有问题联系客服