龙听期货论坛's Archiver

龙听 发表于 2017-10-30 14:41

一个简洁地基于MA的EA源码分析

交易流程分析:
下面的源码是一个基于移动平均线的智能交易系统的代码
,整个程序非常简洁但EA的功能又非常齐全,实现了完全由电脑自动下单和平仓,整个程序只用了一个START()
函数来实现 ,我们知道所谓电脑自动交易系统,也就是让电脑来模拟交易员的操作进行交易的下单和平仓过程。
我们首先来分析一个外汇交易员手工进行外汇交易的操作过程:其步骤如下:
1.打开外汇交易客户端,选定一种货币对图表;
2。监视该货币对的K线趋势图,俗称盯盘,寻找开仓或者是平仓的时机,即开仓或者是平仓的条件
3。如果条件满足,进行下单开仓(做多或者做空)或者平仓
4。重复第二步,继续盯盘,假定第二步是开仓,就是寻找平仓的条件。
5。如果平仓的条件满足,进行平仓操作,计算盈亏核算。完成一次交易的循环。
6。若继续交易,重复2->3->4->5步
7。若不进行交易,退出外汇客户端。
基于以上的分析,我们已经知道一个完整的智能交易系统(俗称EA)在运行后必须要实现的基本功能,就是上述的人工操作的1-5步。

相关MQL语言知识:
为了实现机器操作,再来看看所需的MQL4语言的相关知识:
1.掌握MQL4语言的基本语法和程序的构成,及运行流程
     有关语法部分,请读者参看相关的资料,这里略去。
     关于程序的构成,对于一个智能交易系统EA程序来说:主要由三个函数构成分别是:
     init():初始化函数,负责程序变量及数据初始输入;只在程序调入时执行一次,一般不用重写内容。
     deinit():反初始化函数,负责程序退出时,将数据从内存中清除;只在程序退出时,执行一次,一般不用重写内容。
     start():开始函数,也即程序的主函数,负责EA程序 的全部交易执行过程,实际上他是一个EA的交易管理与执行函数。每隔一定时间,一般几秒之内,执行一次,就是循环执行,起到程序退出时终止
     运行流程:启动EA后,程序的INTI()开始执行一次,-->然后 START()循环执行--->最后退出EA时deinit()执行一次

2。mql4中与交易相关的交易函数:

  开仓函数:
int OrderSend( string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, void comment, void magic, void expiration, void arrow_color)
     这个功能主要应用于开仓位置和挂单交易.
参量:
symbol   -   交易货币对。
cmd  -  购买方式。
volume -  购买手数。
price   -   收盘价格。
slippage   -   最大允许滑点数。
stoploss   -   止损水平。
takeprofit   -   赢利水平。
comment   -   注解文本。
magic   -   定单指定码。可以作为用户指定识别码使用。
expiration   -   定单有效时间(只限挂单)。
arrow_color   -   图表上箭头颜色。如果参量丢失或存在CLR_NONE价格值不会在图表中画出

平仓函数:
bool OrderClose( int ticket, double lots, double price, int slippage, void Color)
对定单进行平仓操作。如果函数成功,返回的值是真实的。如果函数失败,返回的值是假的。获得详细错误信息,请查看GetLastError()函数。
参量:
ticket   -   定单编号。
lots   -   手数。
price   -   收盘价格。
slippage   -   最高划点数。
Color   -   图表中标记颜色。如果参量丢失,CLR_NONE值将不会在图表中画出。

定单修改函数:
bool OrderModify( int ticket, double price, double stoploss, double takeprofit, datetime expiration, void arrow_color)
对于先前的开仓或挂单进行特性修改。如果函数成功,返回的值为 TRUE。如果函数失败,返回的值为FALSE。 获得详细的错误信息,查看 GetLastError()函数。

参量:
ticket   -   定单编号。
price   -   收盘价格
stoploss   -   新止损水平。
takeprofit   -   新赢利水平。
expiration   -   挂单有效时间。
arrow_color   -   在图表中允许对止损/赢利颜色进行修改。如果参量丢失或存在CLR_NONE 值,在图表中将不会显示。

程序代码分析
   参看代码中的相关注释
//+------------------------------------------------------------------+
//|                                                   modifiedEA.mq4 |
//|                       Copyright ?2008, MetaQuotes Software Corp. |
//|                               [email]yyy999@people.com.cn[/email]  QQ:806935610 |
//+------------------------------------------------------------------+
#property copyright "Copyright ?2008, lin Ge QQ:806935610"
#property link      "yyy999@people.com.cn  QQ:806935610"
//---- input parameters
extern double TakeProfit = 20;
extern double StopLoss = 30;
extern double Lots = 2;
extern double TrailingStop = 50;
extern int ShortEma = 5;
extern int LongEma = 60;
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----

//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----

//----
   return(0);
  }

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
    int cnt, ticket, total;
    double SEma, LEma;
//----
    if(Bars < 100)
      {
        Print("bars less than 100");
        return(0);  
      }
//----
    if(TakeProfit < 10)
      {
        Print("TakeProfit less than 10");
        return(0);  // check TakeProfit
      }
//----
    SEma = iMA(NULL, 0, ShortEma, 0, MODE_EMA, PRICE_CLOSE, 0);
    LEma = iMA(NULL, 0, LongEma, 0, MODE_EMA, PRICE_CLOSE, 0);
//----
    static int isCrossed  = 0;
    isCrossed = Crossed (LEma, SEma);
//----
    total  = OrdersTotal();
    if(total < 1)
      {
        if(isCrossed == 1)       // 满足空仓条件,开空仓
          {
            ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, 3, Bid + StopLoss*Point,
                               Bid - TakeProfit*Point, "EMA_CROSS", 12345, 0, Green);
            if(ticket > 0)
              {
                if(OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES))
                    Print("SELL order opened : ",OrderOpenPrice());
              }
            else
                Print("Error opening SELL order : ", GetLastError());
            return(0);
          }
        if(isCrossed == 2)       // 满足多仓条件,开多仓
          {
            ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 3, Ask - StopLoss*Point,
                               Ask + TakeProfit*Point, "EMA_CROSS", 12345, 0, Red);
            if(ticket > 0)
              {
                if(OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES))
                    Print("BUY order opened : ", OrderOpenPrice());
              }
            else
                Print("Error opening BUY order : ",GetLastError());
            return(0);
          }
        return(0);
      }
//----订单修改,实现动态止盈止损跟踪
    for(cnt = 0; cnt < total; cnt++)
      {
        OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
        if(OrderType() <= OP_SELL && OrderSymbol() == Symbol())
          {
            if(OrderType() == OP_SELL)   // long position is opened
              {
                // check for trailing stop
                if(TrailingStop > 0)  
                  {               
                    if(Bid - OrderOpenPrice() > Point*TrailingStop)
                      {
                        if(OrderStopLoss() < Bid - Point*TrailingStop)
                          {
                            OrderModify(OrderTicket(), OrderOpenPrice(),
                                        Bid - Point*TrailingStop,
                                        OrderTakeProfit(), 0, Green);
                            return(0);
                          }
                      }
                  }
              }
            else // go to short position
              {
                // check for trailing stop
                if(TrailingStop > 0)  
                  {               
                    if((OrderOpenPrice() - Ask) > (Point*TrailingStop))
                      {
                        if((OrderStopLoss() > (Ask + Point*TrailingStop)) )
                          {
                            OrderModify(OrderTicket(), OrderOpenPrice(),
                                        Ask + Point*TrailingStop,
                                        OrderTakeProfit(), 0, Red);
                            return(0);
                          }
                      }
                  }
              }
          }
      }
//----
    return(0);
  }
//+------------------------------------------------------------------+
// 移动平均线多空条件判断,
int Crossed (double line1 , double line2)
  {
    static int last_direction = 0;
    static int current_direction = 0;
    //Don't work in the first load, wait for the first cross!
    static bool first_time = true;
    if(first_time == true)
      {
        first_time = false;
        return (0);
      }
//----
    if(line1 > line2)
        current_direction = 2;  //up 多头市场 上穿做多
    if(line1 < line2)
        current_direction = 1;  //down 空头市场 下穿做空
//----
    if(current_direction != last_direction)  //changed 多空换位
      {
        last_direction = current_direction;
        return(last_direction);
      }
    else
      {
        return (0);  //not changed
      }
  }

页: [1]