外汇邦外汇论坛 - 中国最大的外汇投资论坛,全球华人外汇交易者交流平台!

 找回密码
 立即注册
查看: 4626|回复: 1
打印 上一主题 下一主题

MT4自带EA(MA)源码解析

[复制链接]

397

主题

458

帖子

5637

积分

论坛元老

Rank: 8Rank: 8

积分
5637
跳转到指定楼层
楼主
发表于 2015-12-9 10:12:09 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
一、均线穿越交易系统EA详解
MT4平台自带了一个自动交易的EA指标,那就是Moving Average ,下面我们详细解释该系统每条语句的功能说明,以便深入认识EA的编程内核。我想对初学者有一定的帮助。
//+------------------------------------------------------------------+
//|                          Moving Average.mq4  |
//|        Copyright ?2005, MetaQuotes Software Corp. |
//|     //+------------------------------------------------------------------+
#define MAGICMA   20050610
//定义本EA操作的订单的唯一标识号码,由此可以实现在同一账户上多系统操作,各操作EA的订单标识码不同,就不会互相误操作。凡是EA皆不可缺少,非常非常重要!
extern double Lots              = 0.1; //每单的交易量
extern double MaximumRisk      = 0.02;//本系统最大风险系数,即可以动用总资金的2%
extern double DecreaseFactor      = 3;   //下跌因素个数
extern double MovingPeriod       = 12;  //均线的计算周期=12根K线;
extern double MovingShift         = 6;   //均线在K线图中向右的偏移量=6根K线;
//extern 确定从外部程序输入的变量, 会直接显现输入数据窗口。数列本身不能作为外部变量。
注意:iMA中的MovingShift(均线偏移量)是指均线指标在图上绘制时向左、右移动的K线个数,主要为了使图中结果更好看,并不会对MA的计算数值产生变化。其中,该参数为正时,代表向右移动;为负值,则代表向左移动。
//+------------------------------------------------------------------+
//| Calculate open positions
自定义函数(返回-整数型数据) 仓单查询与统计 |
//+------------------------------------------------------------------+
int CalculateCurrentOrders(string symbol)//函数作用,计算当前持仓单的数量
{
int buys=0,sells=0;
//定义两个局部变量,整数型,buys——多单数,sells——空单数,用于订单的统计
//----
for(int i=0;i<OrdersTotal();i++)
//计次循环(i=0至订单数目,i=i+1)-循环检测当前的订单队列
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false)  break;
//如果 没有本系统交易的仓单类型,则跳出循环
if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
//如果 仓单货币对是当前货币对 且 仓单编号是本系统编号 时
(判断这个订单是不是当前EA操作的,避免EA误操作其他程序控制的持仓单)
{
if(OrderType()==OP_BUY)   buys++;
//如果 仓单类型=多单,则:在多单数上加1;
if(OrderType()==OP_SELL) sells++;
//如果 仓单类型=空单,则,在空单数上加1。
}
}
//---- return orders volume-返回订单数目
if(buys>0) return(buys);
//如果 多单>0,则返回(多单数)
else    return(-sells);
//否则,返回(-空单数)
//本函数返回查询计算结束时的持仓单的个数.这种模式返回是假设不存在锁单的。
}
//+------------------------------------------------------------------+
//| Calculate optimal lot size
自定义函数(返回-小数型数据)   资金管理     |
//+------------------------------------------------------------------+
double LotsOptimized()//开仓量计算函数(根据要求计算出订单交易量,小数型)
{
double lot=Lots(=0.1); //定义局部变量los 小数型
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);
//计算 开仓下单量=帐户可用资金*最大风险系数(=2%)/1000.0,并将结果保留小数点1位
(通过风险系数的计算获得当前入场单应该采用的交易量,除以1000是因为大多货币对汇价都在这个附近。)
//---- calcuulate number of losses orders without a break-计算亏损单数目
if(DecreaseFactor(=3)>0) //如果 下跌因素个数(=3)>0
{
for(int i=orders-1;i>=0;i--)
//计次循环(i=历史平仓单数-1,到i=0, 递减1)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) { Print("Error in history!");
break; }
//如果 没有本系统交易记录,输出“无交易历史!”
if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue;
//如果 订单的货币对不是当前货币对,或者 订单类型为挂单时,继续运行
//订单类型为整数型,0-BUY,1-SELL,2-BUYLIMT,3-BUYSTOP,4-SELLLIMT,5-SELLSTOP,其中“>OP_SELL”代表挂单
if(OrderProfit()>0) break;
如果 盈利单数目>0,跳出循环
if(OrderProfit()<0) losses++;
//如果 盈利单数目<0,则在:亏损单数上加1
}
if(losses>1)  lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);
//如果 亏损单数>1时,则 重新计算下单量,并保留小数点后1位,其计算公式为:
下单量=(lot-lot*losses/DecreaseFactor(=3))。
}
//---- return lot size-返回下单量
if(lot<0.1)  lot=0.1;/
/如果 算出的交易量小于0.1手,则 取交易量为0.1手
return(lot);//返回(下单量)
}
//+------------------------------------------------------------------+
//| Check for open order conditions
//自定义函数(无返回值)    开仓策略         |
//+------------------------------------------------------------------+
void CheckForOpen()//开仓检查(判断开仓条件及其处理)
{
double ma; //定义局部变量ma为小数型
int res;    //定义局部变量res为整数型
//---- go trading only for first tiks of new bar,
//只有在新K线的首次报价时执行
if(Volume[0]>1) return;
//如果当前K线的成交价次数大于1时,返回
(不是K线的开盘时间点,即当前k线还没收盘确定,则直接返回;否则,如果是K线第一个成交价,则向下继续运行)
//---- get Moving Average –获取均线数值
ma=iMA(NULL,0,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE,0);
//获取当前以收盘价为基准计算出的均线数值
  iMA(NULL,0,12,6,MOD_SMA,PRICE_CLOSE,0)
//---- sell conditions-卖出条件
if(Open[1]>ma && Close[1]<ma)
//如果前1根K线下穿均线(即K线的开盘价大于均线值、收盘价小于均线值)
{
res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,0,"",MAGICMA,0,Red);
//发送仓单(当前货币对,卖出方向,开仓量计算(),买价,滑点=3,无止损,无止赢,订单编号,标上红色箭头)
return; //返回
}
//---- buy conditions-买入条件
if(Open[1]<ma && Close[1]>ma)
//如果前1根K线上穿均线(即K线的开盘价小于均线值、收盘价大于均线值)
{
res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,0,"",MAGICMA,0,Blue);
//发送仓单(当前货币对,买入方向,开仓量计算(),卖价,滑点=3,无止损,无止赢,订单编号,标上蓝色箭头)
return;//返回
}
//----
}
//+------------------------------------------------------------------+
//| Check for close order conditions
//自定义函数(无返回值)    平仓策略         |
//+------------------------------------------------------------------+
void CheckForClose()//平仓检查(判断平仓条件及其处理)
{
double ma;//定义局部变量ma小数型
//---- 只在一个k收盘另一个新出现时交易
if(Volume[0]>1) return;//如果当前K线的成交价次数>1时,则返回
//---- get Moving Average //获取均线数值
ma=iMA(NULL,0,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE,0);
//获取当前以收盘价为基准计算出的均线数值
for(int i=0;i<OrdersTotal();i++) //计次循环(变量i=1至定单总数,每次递增1)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
//如果 没有本系统所交易的仓单时,跳出循环
if(OrderMagicNumber()!=MAGICMA || OrderSymbol()!=Symbol()) continue;
//如果 仓单编号不是本系统编号,或者 仓单货币对不是当前货币对时,继续选择
if(OrderType()==OP_BUY)
//如果是多单
{
if(Open[1]>ma && Close[1]<ma) OrderClose(OrderTicket(),OrderLots(),Bid,3,White);
//如果第1根K线开盘价下穿均线时(即开盘价高于均价而收盘价低于均价时),
则进行多头平仓(仓单编号,持仓数量,买价,滑点=3,用白色箭头显示)
break;//跳出循环
}
if(OrderType()==OP_SELL)
//如果是空单
{
if(Open[1]<ma && Close[1]>ma) OrderClose(OrderTicket(),OrderLots(),Ask,3,White););
//如果第1根K线开盘价上穿均线时(即开盘价低于均价而收盘价高于均价时),
则进行空头平仓(仓单编号,持仓数量,卖价,滑点=3,用白色箭头显示)
break;//跳出循环
}
}
//----
}
//+------------------------------------------------------------------+
//| Start function                                  |
//+------------------------------------------------------------------+
void start()//主程序—-每次成交价所驱动的运算过程
{
//---- check for history and trading—对交易历史进行检查
if(Bars<100 || IsTradeAllowed()==false) return;
//如果K线数少于100根,或者 如果允许智能交易交易=假时,返回
//---- calculate open orders by current symbol-计算当前货币对的开仓订单
if(CalculateCurrentOrders(Symbol())==0) CheckForOpen();
//如果 计算出当前货币对开仓订单数=0 (即没有仓单),则进行开仓检查。
else  CheckForClose();
//否则(即当前已经有仓单时),则进行平仓检查。
//----
}

二、本EA策略分析
根据本EA系统的源代码可以分析出:它使用的策略如下:
1、技术指标:12周期均线系统;
2、滑点数:3个点;
3、开平仓法则:K线上穿均线时,无仓,则开多仓;有空仓时,则平空仓;
               K线下穿均线时,无仓,则开空仓;有多仓时,则平多仓。
4、图上标识:开多仓时,在图中标示红色箭头;平仓时,则标示白色箭头;
             开空仓时,在图中标未蓝色箭头;平仓时,则标示白色箭头。

三、该系统在模拟交易中的结果分析

以上对该EA系统进行了详细的解析,从中可以看出EA系统的基本结构与相关策略。下面是该EA在模拟盘中1分钟K线图EURUSD(欧元对美元)中的开仓、平仓结果图。
在该系统的模拟交易过程中,基本上体现了本策略的操作思想,其中四个下单中,两个空单和两个多单,如下图所示。

 

回复

使用道具 举报

3

主题

25

帖子

575

积分

高级会员

Rank: 4

积分
575
沙发
发表于 2016-1-2 23:25:11 | 只看该作者
谢谢,收藏了

 

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


联系我们|外汇邦外汇论坛

GMT+8, 2022-10-10 08:59

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表