本节展示的EA交易程序同样基于函数化设计,但采用的是挂单方式进行交易。
// ===== 预处理指令 =====
#property copyright "Andrew Young"
#include <IncludeExample.mqh>
// ===== 外部输入参数 =====
extern bool DynamicLotSize = true;
extern double EquityPercent = 2;
extern double FixedLotSize = 0.1;
extern double StopLoss = 50;
extern double TakeProfit = 100;
extern int TrailingStop = 50;
extern int MinimumProfit = 50;
extern int PendingPips = 1; // 挂单距离当前价格的点数 (例如,距离High/Low 1个点)
extern int Slippage = 5;
extern int MagicNumber = 123;
extern int FastMAPeriod = 10;
extern int SlowMAPeriod = 20;
extern bool CheckOncePerBar = true;
// ===== 全局变量 =====
int BuyTicket;
int SellTicket;
double UsePoint;
int UseSlippage;
datetime CurrentTimeStamp;
// ===== 初始化函数 =====
int OnInit()
{
UsePoint = PipPoint(Symbol());
UseSlippage = GetSlippage(Symbol(), Slippage);
CurrentTimeStamp = Time[0]; // 初始化时间戳,用于“每K线一次”逻辑
return(0);
}
// ===== 主体逻辑函数 =====
void OnTick()
{
bool NewBar;
int BarShift;
// --- 实现“每K线仅执行一次”的逻辑 ---
if(CheckOncePerBar == true)
{
BarShift = 1;
if(CurrentTimeStamp != Time[0])
{
CurrentTimeStamp = Time[0];
NewBar = true;
}
else
{
NewBar = false;
}
}
else
{
NewBar = true;
BarShift = 0;
}
// --- 计算移动平均线 ---
double FastMA = iMA(NULL, 0, FastMAPeriod, 0, 0, 0, BarShift);
double SlowMA = iMA(NULL, 0, SlowMAPeriod, 0, 0, 0, BarShift);
// 注意:此挂单版本示例中,没有使用LastFastMA/LastSlowMA进行穿越确认,
// 而是直接用当前(或上一K线)的MA状态,并结合检查现有订单数量。
// --- 计算交易手数 ---
double LotSize = CalcLotSize(DynamicLotSize, EquityPercent, StopLoss, FixedLotSize);
LotSize = VerifyLotSize(LotSize);
// --- 主要交易逻辑块 (仅在新K线形成时执行) ---
if(NewBar == true)
{
// -- 买入挂单信号判断与执行 --
// 条件: MA金叉,且当前无本EA的买单、市价买单或买入挂单
if(FastMA > SlowMA && BuyTicket == 0 && BuyMarketCount(Symbol(), MagicNumber) == 0 &&
BuyStopCount(Symbol(), MagicNumber) == 0) // BuyStopCount 函数来自包含文件
{
// 如果存在反向的市价卖单,则先平仓
if(SellMarketCount(Symbol(), MagicNumber) > 0)
{
CloseAllSellOrders(Symbol(), MagicNumber, UseSlippage);
}
// 如果存在反向的卖出挂单,则先删除
if(SellStopCount(Symbol(), MagicNumber) > 0) // SellStopCount 函数来自包含文件
{
CloseAllSellStopOrders(Symbol(), MagicNumber); // CloseAllSellStopOrders 函数来自包含文件
}
SellTicket = 0; // 重置卖单追踪号
// 计算并调整挂单价格
double PendingPrice = High[BarShift] + (PendingPips * UsePoint); // 挂单价设置在上一K线最高点之上
PendingPrice = AdjustAboveStopLevel(Symbol(), PendingPrice, 5); // 调整以避开最小止损点位
// 计算止损价和止盈价 (基于挂单价格)
double BuyStopLoss = CalcBuyStopLoss(Symbol(), StopLoss, PendingPrice);
// Adjust... 函数的第三个参数 (min_dist_pips) 和第四个参数 (base_price_for_adjust) 需要与包含文件中的定义匹配
if(BuyStopLoss > 0) BuyStopLoss = AdjustBelowStopLevel(Symbol(), BuyStopLoss, 5, PendingPrice);
double BuyTakeProfit = CalcBuyTakeProfit(Symbol(), TakeProfit, PendingPrice);
if(BuyTakeProfit > 0) BuyTakeProfit = AdjustAboveStopLevel(Symbol(), BuyTakeProfit, 5, PendingPrice);
// 开立新的买入停止单 (Buy Stop Order)
BuyTicket = OpenBuyStopOrder(Symbol(), LotSize, PendingPrice, BuyStopLoss,
BuyTakeProfit, UseSlippage, MagicNumber); // OpenBuyStopOrder 函数来自包含文件
}
// -- 卖出挂单信号判断与执行 --
// 条件: MA死叉,且当前无本EA的卖单、市价卖单或卖出挂单
if(FastMA < SlowMA && SellTicket == 0 &&
SellMarketCount(Symbol(), MagicNumber) == 0 &&
SellStopCount(Symbol(), MagicNumber) == 0)
{
// 如果存在反向的市价买单,则先平仓
if(BuyMarketCount(Symbol(), MagicNumber) > 0)
{
CloseAllBuyOrders(Symbol(), MagicNumber, UseSlippage);
}
// 如果存在反向的买入挂单,则先删除
if(BuyStopCount(Symbol(), MagicNumber) > 0)
{
CloseAllBuyStopOrders(Symbol(), MagicNumber);
}
BuyTicket = 0; // 重置买单追踪号
// 计算并调整挂单价格
double SellPendingPrice = Low[BarShift] - (PendingPips * UsePoint); // 挂单价设置在上一K线最低点之下
SellPendingPrice = AdjustBelowStopLevel(Symbol(), SellPendingPrice, 5);
// 计算止损价和止盈价
double SellStopLoss = CalcSellStopLoss(Symbol(), StopLoss, SellPendingPrice);
if(SellStopLoss > 0) SellStopLoss = AdjustAboveStopLevel(Symbol(), SellStopLoss, 5, SellPendingPrice);
double SellTakeProfit = CalcSellTakeProfit(Symbol(), TakeProfit, SellPendingPrice);
if(SellTakeProfit > 0) SellTakeProfit = AdjustBelowStopLevel(Symbol(), SellTakeProfit, 5, SellPendingPrice);
// 开立新的卖出停止单 (Sell Stop Order)
SellTicket = OpenSellStopOrder(Symbol(), LotSize, SellPendingPrice, SellStopLoss,
SellTakeProfit, UseSlippage, MagicNumber);
}
} // --- 结束交易逻辑块 ---
// --- 追踪止损逻辑 (仅对已成交的市价单生效) ---
if(BuyMarketCount(Symbol(), MagicNumber) > 0 && TrailingStop > 0)
{
BuyTrailingStop(Symbol(), TrailingStop, MinimumProfit, MagicNumber);
}
if(SellMarketCount(Symbol(), MagicNumber) > 0 && TrailingStop > 0)
{
SellTrailingStop(Symbol(), TrailingStop, MinimumProfit, MagicNumber);
}
}