大家好,今天来聊聊一款非常实用的交易助手——AK-47 Scalper EA,它专为MetaTrader 5平台设计,能够帮助我们有效捕捉市场机会。
1. 输入参数
#define ExtBotName "AK-47 EA"// 机器人名称#define Version "1.00"// 导入输入类#include <Trade\PositionInfo.mqh> #include <Trade\Trade.mqh> #include <Trade\SymbolInfo.mqh> #include <Trade\AccountInfo.mqh> #include <Trade\OrderInfo.mqh> //--- 定义预设变量以便于代码可读性 #define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK) #define Bid SymbolInfoDouble(_Symbol, SYMBOL_BID) //--- 输入参数inputstring EASettings = "---------------------------------------------"; //-------- <EA设置> --------inputint InpMagicNumber = 124656; //魔术数字inputstring MoneySettings = "---------------------------------------------"; //-------- <资金设置> --------inputbool isVolume_Percent = true; //允许按比例计算交易量inputdouble InpRisk = 3; //风险百分比inputstring TradingSettings = "---------------------------------------------"; //-------- <交易设置> --------inputdouble Inpuser_lot = 0.01; //交易手数inputdouble InpSL_Pips = 3.5 //止损(点数)inputdouble InpTP_Pips = 7 //止盈(点数)(0 = 无止盈)inputint InpMax_slippage = 3 //最大允许滑点inputdouble InpMax_spread = 5 //最大允许点差(0 = 浮动点差)inputstring TimeSettings = "---------------------------------------------"; //-------- <交易时间设置> --------inputbool InpTimeFilter = true; //时间过滤器inputint InpStartHour = 2; //开始小时inputint InpStartMinute = 30 //开始分钟inputint InpEndHour = 21 //结束小时inputint InpEndMinute = 0 //结束分钟
2. 本地变量初始化
//--- 变量int Pips2Points; // 滑点 3点double Pips2Double; // 止损 15点bool isOrder = false; int slippage; long acSpread; string strComment = ""; CPositionInfo m_position; // 交易位置对象 CTrade m_trade; // 交易对象 CSymbolInfo m_symbol; // 货币对信息对象 CAccountInfo m_account; // 账户信息包装类 COrderInfo m_order; // 挂单对象
3. 主代码
a/ 专家初始化函数
//+------------------------------------------------------------------+//| 专家初始化函数 |//+------------------------------------------------------------------+intOnInit() { // 检测3位或5位小数 // 点和点数 if(_Digits % 2 == 1) { Pips2Double = _Point*10; Pips2Points = <:number>10; slippage = 10* InpMax_slippage; } else { Pips2Double = _Point; Pips2Points = 1; slippage = InpMax_slippage; } if(!m_symbol.Name(Symbol())) // 设置货币对名称 return(INIT_FAILED); RefreshRates(); //--- m_trade.SetExpertMagicNumber(InpMagicNumber); m_trade.SetMarginMode(); m_trade.SetTypeFillingBySymbol(m_symbol.Name()); m_trade.SetDeviationInPoints(slippage); //--- return(INIT_SUCCEEDED); }
b/ 专家Tick函数
//+------------------------------------------------------------------+//| 专家Tick函数 |//+------------------------------------------------------------------+voidOnTick() { if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) == false) { Comment("LazyBot\n不允许交易。"); return; } MqlDateTime structTime; TimeCurrent(structTime); structTime.sec = 0; //设置开始时间 structTime.hour = InpStartHour; structTime.min = InpStartMinute; datetime timeStart = StructToTime(structTime); //设置结束时间 structTime.hour = InpEndHour; structTime.min = InpEndMinute; datetime timeEnd = StructToTime(structTime); acSpread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD); strComment = "\n" + ExtBotName + " - v." + (string)Version; strComment += "\n服务器时间 = " + TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS) + " - " + DayOfWeekDescription(structTime.day_of_week); strComment += "\n交易时间 = [" + (string)InpStartHour + "h" + (string)InpStartMinute + " --> " + (string)InpEndHour + "h" + (string)InpEndMinute + "]"; strComment += "\n当前点差 = " + (string)acSpread + " 点"; Comment(strComment); //更新值 UpdateOrders(); TrailingStop(); //根据时间过滤交易 if(InpTimeFilter) { if(TimeCurrent() >= timeStart && TimeCurrent() < timeEnd) { if(!isOrder) OpenOrder(); } } else { if(!isOrder) OpenOrder(); } } //---结束函数
3.1 计算信号以发送订单
//+------------------------------------------------------------------+//| 计算信号并发送订单 |//+------------------------------------------------------------------+void OpenOrder(){ ENUM_ORDER_TYPE OrdType = ORDER_TYPE_SELL;//-1; double TP = 0; double SL = 0; string comment = ExtBotName; //计算手数 double lot1 = CalculateVolume(); if(OrdType == ORDER_TYPE_SELL) { double OpenPrice = Bid - NormalizeDouble(InpSL_Pips/2 * Pips2Double, _Digits); TP = OpenPrice - NormalizeDouble(InpTP_Pips * Pips2Double, _Digits); SL = Ask + NormalizeDouble(InpSL_Pips/2 * Pips2Double, _Digits); if(CheckSpreadAllow() //检查点差 && CheckVolumeValue(lot1) //检查交易量 && CheckOrderForFREEZE_LEVEL(ORDER_TYPE_SELL_STOP, OpenPrice) //检查开盘价与当前Bid的距离 && CheckStopLoss(OpenPrice, SL, TP) //检查止损和止盈的距离 && CheckMoneyForTrade(m_symbol.Name(), lot1, ORDER_TYPE_SELL)) //检查资金是否满足交易 { if(!m_trade.SellStop(lot1, OpenPrice, m_symbol.Name(), SL, TP, ORDER_TIME_GTC, 0, comment)) Print(__FUNCTION__,"--> 订单发送错误 ", m_trade.ResultComment()); } } elseif(OrdType == ORDER_TYPE_BUY) { double OpenPrice = Ask + NormalizeDouble(InpSL_Pips/2 * Pips2Double, _Digits); SL = Bid - NormalizeDouble(InpSL_Pips/2 * Pips2Double, _Digits); if(CheckSpreadAllow() //检查点差 && CheckVolumeValue(lot1) //检查交易量 && CheckOrderForFREEZE_LEVEL(ORDER_TYPE_BUY_STOP, OpenPrice) //检查开盘价与当前Bid的距离 && CheckStopLoss(OpenPrice, SL, TP) //检查止损和止盈的距离 && CheckMoneyForTrade(m_symbol.Name(), lot1, ORDER_TYPE_BUY)) //检查资金是否满足交易 { if(!m_trade.BuyStop(lot1, OpenPrice, m_symbol.Name(), SL, TP, ORDER_TIME_GTC, 0, comment))// 使用"ORDER_TIME_GTC"时过期日期 = 0 Print(__FUNCTION__,"--> 订单发送错误 ", m_trade.ResultComment()); } } }
3.2 计算交易量
//+------------------------------------------------------------------+//| 计算交易量 |//+------------------------------------------------------------------+// 定义函数以计算头寸大小并返回手数。double CalculateVolume() { double LotSize = 0; if(isVolume_Percent == false) { LotSize = Inpuser_lot; } else { LotSize = (InpRisk) * m_account.FreeMargin(); LotSize = LotSize /100000; double n = MathFloor(LotSize/Inpuser_lot); //Comment((string)n); LotSize = n * Inpuser_lot; if(LotSize < Inpuser_lot) LotSize = Inpuser_lot; if(LotSize > m_symbol.LotsMax()) LotSize = m_symbol.LotsMax(); if(LotSize < m_symbol.LotsMin()) LotSize = m_symbol.LotsMin(); } //--- return(LotSize); }
3.3 EA具有“追踪止损”功能, SL会在每次价格变动时调整(下移)
//+------------------------------------------------------------------+//| 追踪止损 |//+------------------------------------------------------------------+void TrailingStop() { double SL_in_Pip = 0; for(int i = PositionsTotal() - 1; i >= 0; i--) { if(m_position.SelectByIndex(i)) { // 根据索引选择订单以便进一步访问其属性 if((m_position.Magic() == InpMagicNumber) && (m_position.Symbol() == m_symbol.Name())) { // 买单 if(m_position.PositionType() == POSITION_TYPE_BUY) { //--计算SL在价格变化时 SL_in_Pip = NormalizeDouble(Bid - m_position.StopLoss(), _Digits) / Pips2Double; if(SL_in_Pip > InpSL_Pips) { double newSL = NormalizeDouble(Bid - InpSL_Pips * Pips2Double, _Digits); if(!m_trade.PositionModify(m_position.Ticket(), newSL, m_position.TakeProfit())) { Print(__FUNCTION__,"--> 修改订单错误 ", m_trade.ResultComment()); continue } } } //卖单 elseif(m_position.PositionType() == POSITION_TYPE_SELL) { //--计算SL在价格变化时 SL_in_Pip = NormalizeDouble(m_position.StopLoss() - Bid, _Digits) / Pips2Double; if(SL_in_Pip > InpSL_Pips){ double newSL = NormalizeDouble(Bid + (InpSL_Pips) * Pips2Double, _Digits); if(!m_trade.PositionModify(m_position.Ticket(), newSL, m_position.TakeProfit())) { Print(__FUNCTION__,"--> 修改订单错误 ", m_trade.ResultComment()); //continue; } } } } } } //--- 修改挂单 for(int i=OrdersTotal()-1; i>=0; i--) {// 返回当前订单数 if(m_order.SelectByIndex(i)) { // 根据索引选择挂单以便进一步访问其属性 if(m_order.Symbol() == m_symbol.Name() && m_order.Magic()==InpMagicNumber) { if(m_order.OrderType() == ORDER_TYPE_BUY_STOP) { SL_in_Pip = NormalizeDouble(Bid - m_order.StopLoss(), _Digits) / Pips2Double; if(SL_in_Pip < InpSL_Pips/2) { double newOP = NormalizeDouble(Bid + (InpSL_Pips/2) * Pips2Double, _Digits); double newTP = NormalizeDouble(newOP + InpTP_Pips * Pips2Double, _Digits); double newSL = NormalizeDouble(Bid - (InpSL_Pips/2) * Pips2Double, _Digits); if(!m_trade.OrderModify(m_order.Ticket(), newOP, newSL, newTP, ORDER_TIME_GTC,0)) { Print(__FUNCTION__,"--> 修改挂单错误!", m_trade.ResultComment()); continue } //continue; } } elseif(m_order.OrderType() == ORDER_TYPE_SELL_STOP) { SL_in_Pip = NormalizeDouble(m_order.StopLoss() - Ask, _Digits) / Pips2Double; if(SL_in_Pip < InpSL_Pips/2){ double newOP = NormalizeDouble(Ask - (InpSL_Pips/2) * Pips2Double, _Digits); double newTP = NormalizeDouble(newOP - InpTP_Pips * Pips2Double, _Digits); double newSL = NormalizeDouble(Ask + (InpSL_Pips/2) * Pips2Double, _Digits); if(!m_trade.OrderModify(m_order.Ticket(), newOP, newSL, newTP, ORDER_TIME_GTC,0)) { Print(__FUNCTION__,"--> 修改挂单错误!", m_trade.ResultComment()); //continue; } //continue; } } } } } }

评论 0