MetaTrader5
懒人交易机器人MT5:日内突破EA的使用与设置
1. 输入参数
输入参数设置
// 导入外部类
#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)
//--- 输入参数
input string EASettings = "---------------------------------------------"; //-------- <EA 设置> --------
input int InpMagicNumber = 123456; // 魔法数字
input string InpBotName = "LazyBot_V1"; // 机器人名称
input string TradingSettings = "---------------------------------------------"; //-------- <交易设置> --------
input double Inpuser_lot = 0.01; // 手数
input double Inpuser_SL = 5.0; // 止损(点数)
input double InpAddPrice_pip = 0; // 从[最高]、[最低]到开盘价的距离(点数)
input int Inpuser_SLippage = 3; // 最大允许滑点(点数)
input double InpMax_spread = 0; // 最大允许点差(点数)(0 = 浮动)
input string TimeSettings = "---------------------------------------------"; //-------- <交易时间设置> --------
input bool isTradingTime = true; // 允许交易时间
input int InpStartHour = 7; // 开始小时
input int InpEndHour = 22; // 结束小时
input string MoneyManagementSettings = "---------------------------------------------"; //-------- <资金设置> --------
input bool isVolume_Percent = false; // 允许按百分比计算交易量
input double InpRisk = 1; // 风险百分比
2. 本地变量初始化
// 本地参数
datetime last;
int totalBars;
int Pips2Points; // 滑点 3点 3=点数 30=点数
double Pips2Double; // 止损 15点 0.015 0.0150
double slippage;
double acSpread;
string strComment = "";
CPositionInfo m_position; // 交易头寸对象
CTrade m_trade; // 交易对象
CSymbolInfo m_symbol; // 交易品种信息对象
CAccountInfo m_account; // 账户信息包装
COrderInfo m_order; // 待处理订单对象
3. 主代码
本策略每天会删除所有旧订单,并找到前一个日内K线的最高和最低值,发送两个挂单“BUY_STOP”、“SELL_STOP”。(无止盈)
3.1 专家初始化函数
int OnInit()
{
//---
// 检测3位或5位小数
// 点和滑点
if(_Digits % 2 == 1)
{
Pips2Double = _Point * 10;
Pips2Points = 10;
slippage = 10 * Inpuser_SLippage;
}
else
{
Pips2Double = _Point;
Pips2Points = 1;
slippage = Inpuser_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);
}
3.2 专家按钮信息
void OnTick()
{
if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) == false)
{
Comment("LazyBot\n交易不被允许。");
return;
}
// 获取交易时间
// 开盘时间段
// 伦敦 14h - 23h GMT 越南
// 纽约 19h - 04h GMT 越南
MqlDateTime timeLocal;
MqlDateTime timeServer;
TimeLocal(timeLocal);
TimeCurrent(timeServer);
// 节假日不进行交易
if(timeServer.day_of_week == 0 || timeServer.day_of_week == 6)
return;
int hourLocal = timeLocal.hour;
int hourCurrent = timeServer.hour;
acSpread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
strComment = "\n本地时间 = " + hourLocal;
strComment += "\n当前时间 = " + hourCurrent;
strComment += "\n点差 = " + (string)acSpread;
strComment += "\n总K线数 = " + (string)totalBars;
Comment(strComment);
// 检查跟踪止损
TrailingSL();
if(last != iTime(m_symbol.Name(), PERIOD_D1, 0))
{
// 检查交易时间
if(isTradingTime)
{
if(hourCurrent >= InpStartHour)
{
DeleteOldOrds();
// 发送订单BUY_STOP和SELL_STOP
OpenOrder();
last = iTime(m_symbol.Name(), PERIOD_D1, 0);
}
}
else
{
DeleteOldOrds();
// 发送订单BUY_STOP和SELL_STOP
OpenOrder();
last = iTime(m_symbol.Name(), PERIOD_D1, 0);
}
}
}
4. 计算信号并发送订单
void OpenOrder()
{
// 初始化买卖止损价格
double TP_Buy = 0, TP_Sell = 0;
double SL_Buy = 0, SL_Sell = 0;
// 检查最大点差
if(InpMax_spread != 0){
if(acSpread > InpMax_spread){
Print(__FUNCTION__, " > 当前点差大于用户设置的点差!...");
return;
}
}
// 获取前一个日内的最高和最低
double Bar1High = m_symbol.NormalizePrice(iHigh(m_symbol.Name(), PERIOD_D1, 1));
double Bar1Low = m_symbol.NormalizePrice(iLow(m_symbol.Name(), PERIOD_D1, 1));
// 计算手数
double lot1 = CalculateVolume();
// 设置开盘价
double OpenPrice = m_symbol.NormalizePrice(Bar1High + InpAddPrice_pip * Pips2Double);
// 处理BUY_STOP
TP_Buy = 0;
SL_Buy = m_symbol.NormalizePrice(OpenPrice - Inpuser_SL * Pips2Double);
// 获取总K线数量
总K线数 = iBars(m_symbol.Name(), PERIOD_D1);
string comment = InpBotName + ";" + m_symbol.Name() + ";" + totalBars;
// 检查交易条件并执行BUY_STOP
if(CheckVolumeValue(lot1)
&& CheckOrderForFREEZE_LEVEL(ORDER_TYPE_BUY_STOP, OpenPrice)
&& CheckMoneyForTrade(m_symbol.Name(), lot1, ORDER_TYPE_BUY)
&& CheckStopLoss(OpenPrice, SL_Buy))
{
if(!m_trade.BuyStop(lot1, OpenPrice, m_symbol.Name(), SL_Buy, TP_Buy, ORDER_TIME_GTC, 0, comment))
Print(__FUNCTION__, "--> 买入错误");
}
// 处理SELL_STOP
OpenPrice = m_symbol.NormalizePrice(Bar1Low - InpAddPrice_pip * Pips2Double);
TP_Sell = 0;
SL_Sell = m_symbol.NormalizePrice(OpenPrice + Inpuser_SL * Pips2Double);
// 检查交易条件并执行SELL_STOP
if(CheckVolumeValue(lot1)
&& CheckOrderForFREEZE_LEVEL(ORDER_TYPE_SELL_STOP, OpenPrice)
&& CheckMoneyForTrade(m_symbol.Name(), lot1, ORDER_TYPE_SELL)
&& CheckStopLoss(OpenPrice, SL_Sell))
{
if(!m_trade.SellStop(lot1, OpenPrice, m_symbol.Name(), SL_Sell, TP_Sell, ORDER_TIME_GTC, 0, comment))
Print(__FUNCTION__, "--> 卖出错误");
}
}
5. 删除旧订单
void DeleteOldOrds()
{
string sep=";"; // 分隔符
ushort u_sep; // 分隔符字符代码
string result[]; // 数组用于获取字符串
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(m_order.SelectByIndex(i))
{
// 获取分隔符代码
u_sep = StringGetCharacter(sep, 0);
string Ordcomment = m_order.Comment();
// 分割OrderComment(EAName;Symbol;totalBar)获取订单符号
int k = StringSplit(Ordcomment, u_sep, result);
if(k > 2)
{
string sym = m_symbol.Name();
if((m_order.Magic() == InpMagicNumber) && (sym == result[1]))
{
m_trade.OrderDelete(m_order.Ticket());
}
}
}
}
6. 跟踪止损
void TrailingSL()
{
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 > Inpuser_SL)
{
m_position.StopLoss() = NormalizeDouble(Bid - (Inpuser_SL * Pips2Double), _Digits);
m_trade.PositionModify(m_position.Ticket(), m_position.StopLoss(), m_position.TakeProfit());
}
}
// 处理卖出订单
if(m_position.PositionType() == POSITION_TYPE_SELL)
{
SL_in_Pip = NormalizeDouble((m_position.StopLoss() - Ask), _Digits) / Pips2Double;
if(SL_in_Pip > Inpuser_SL)
{
m_position.StopLoss() = NormalizeDouble(Ask + (Inpuser_SL * Pips2Double), _Digits);
m_trade.PositionModify(m_position.Ticket(), m_position.StopLoss(), m_position.TakeProfit());
}
}
}
}
}
想了解更多关于MQL4和MQL5的内容,可以查看下面的视频:
视频 MQL4:
视频 MQL5:
2022.12.14