找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
首页论坛EAHub 外汇论坛
查看: 14|回复: 0

双均线EA

[复制链接]

4万

主题

54

回帖

4万

积分

管理员

积分
45954
发表于 2026-8-26 07:12:00 | 显示全部楼层 |阅读模式
//+-----------------------------------------------------------------------------+

//|                                                                 Moving Average.mq4 |

//|                    Copyright 2005-2014, MetaQuotes Software Corp. |

//|                                                                http://www.mql4.com |

//+-----------------------------------------------------------------------------+

#property copyright   "2005-2014, MetaQuotes Software Corp."

#property link             "http://www.mql4.com"

#property description "Moving Average sample expert advisor"


#define MAGICMA 20131111


// 宏定义命令#define用法,定义本EA操作的订单的唯一标识号码,由此可以实现在同一账户上多系统操作,各操作EA的订单标识码不同,就不会互相误操作。凡是EA皆不可缺少,非常非常重要!


//--- Inputs

input double Lots                 =0.1;    // 每单的交易量

input double MaximumRisk   =0.02; // 本系统最大风险系数,即可以动用总资金的2%

input double DecreaseFactor=3;     // 下跌因子

input int       MovingPeriod   =12;   // 均线的计算周期=12,为MA必须的参数之一

input int       MovingShift      =6;    // 均线转移量=6,为MA必须的参数之一


// input 确定从外部程序输入的变量, 会直接显现输入数据窗口。数列本身不能作为外部变量。


注意: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;   // 定义局部变量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>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)

          {

           if(!OrderClose(OrderTicket(),OrderLots(),Bid,3,White));

// 如果第1根K线开盘价下穿均线(即开盘价高于均价而收盘价低于均价),则进行多头平仓(仓单编号,持仓数量,买价,滑点=3,用白色箭头显示)

               Print("OrderClose error ",GetLastError());

          }

        break;   // 跳出循环

      }

      

       if(OrderType()==OP_SELL)   // 如果是空单

        {

         if(Open[1]<ma && Close[1]>ma)

          {

            if(!OrderClose(OrderTicket(),OrderLots(),Ask,3,White))

// 如果第1根K线开盘价上穿均线(即开盘价低于均价而收盘价高于均价),则进行空头平仓(仓单编号,持仓数量,卖价,滑点=3,用白色箭头显示)

               Print("OrderClose error ",GetLastError());

          }

        break;   // 跳出循环

        }

      }

//----

   }


//+------------------------------------------------------------------+

//|  OnTick function                                                          |

//+------------------------------------------------------------------+

void OnTick()   //主程序—-每次成交价所驱动的运算过程

   {

//--- 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();   // 否则(即当前已经有仓单时),则进行平仓检查。

//---

   }

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

本版积分规则

QQ|Archiver|手机版|小黑屋|EAHub外汇论坛

GMT+8, 2026-10-11 05:41 , Processed in 0.105723 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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