一、为什么条件判断语句在EA开发中如此重要
条件判断语句是任何智能交易系统(EA)的决策核心。它们让你的EA能够评估市场条件并根据评估结果选择不同的行动方案。没有条件判断语句,EA每次都会执行相同的指令,无法适应不断变化的市场环境。
二、条件判断语句完整速查表
| 语句类型 | 语法格式 | 适用场景 | 执行说明 |
|----------|----------|----------|----------|
| if | if(条件) { 代码 } | 单条件检查 | 仅当条件为真时执行 |
| if-else | if(条件) { 代码1 } else { 代码2 } | 双向分支 | 条件真执行代码1,假执行代码2 |
| else-if | if(条件1) { 代码1 } else if(条件2) { 代码2 } | 多向分支 | 执行第一个为真的条件块 |
| switch | switch(表达式) { case 值: 代码; break; } | 多离散值匹配 | 跳转到匹配的case值执行 |
三、if语句 - 单条件测试
if语句是最基础的条件判断语句。它仅当指定条件为真时执行代码块。
```mql4
// 基础if语句语法
if(条件) {
// 仅当条件为真时执行的代码
}
// 实用EA示例 - 简单交易信号
void CheckBuySignal() {
double rsi = iRSI(NULL, 0, 14, PRICE_CLOSE, 1);
if(rsi < 30) {
// RSI显示超卖状态 - 潜在的买入机会
double lotSize = 0.1;
int ticket = OrderSend(Symbol(), OP_BUY, lotSize, Ask, 30, 0, 0, "RSI买入", magicNumber, 0, clrGreen);
if(ticket > 0) {
Print("买入订单已成功执行,价格:", Ask);
}
}
}
// 多个独立的if语句
void CheckMultipleConditions() {
double maFast = iMA(NULL, 0, 10, 0, MODE_SMA, PRICE_CLOSE, 1);
double maSlow = iMA(NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 1);
double rsi = iRSI(NULL, 0, 14, PRICE_CLOSE, 1);
if(maFast > maSlow) {
Print("检测到上涨趋势");
}
if(rsi < 30) {
Print("检测到超卖状态");
}
if(rsi > 70) {
Print("检测到超买状态");
}
}
// 嵌套if语句
void CheckWithConfirmation() {
double maFast = iMA(NULL, 0, 10, 0, MODE_SMA, PRICE_CLOSE, 1);
double maSlow = iMA(NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 1);
double rsi = iRSI(NULL, 0, 14, PRICE_CLOSE, 1);
if(maFast > maSlow) {
// 主条件满足 - 检查次级条件
if(rsi < 30) {
// 两个条件都满足 - 强买入信号
Print("强买入信号:上涨趋势 + RSI超卖");
OpenBuyOrder();
}
else if(rsi < 40) {
// 中等条件
Print("中等买入信号:上涨趋势 + RSI低于40");
}
}
}
```
四、if-else语句 - 双向分支
if-else语句提供两个执行路径:一个在条件为真时执行,另一个在条件为假时执行。
```mql4
// 基础if-else语法
if(条件) {
// 条件为真时执行
} else {
// 条件为假时执行
}
// 实用EA示例 - 买入或卖出决策
void DetermineTradeDirection() {
double maFast = iMA(NULL, 0, 10, 0, MODE_SMA, PRICE_CLOSE, 1);
double maSlow = iMA(NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 1);
if(maFast > maSlow) {
// 上涨趋势 - 考虑买入
Print("上涨趋势 - 评估买入条件");
if(ConfirmBuyConditions()) {
OpenBuyOrder();
}
} else {
// 下跌或横盘 - 考虑卖出
Print("下跌趋势 - 评估卖出条件");
if(ConfirmSellConditions()) {
OpenSellOrder();
}
}
}
// 使用if-else的持仓管理
void ManageOpenPosition(double entryPrice, double currentPrice) {
double profitPoints = (currentPrice - entryPrice) / Point();
if(profitPoints >= 50) {
// 移动止损至保本
ModifyStopLoss(entryPrice);
Print("止损已移至保本位");
} else {
// 保持原有止损
Print("利润不足,暂不调整止损");
}
}
// 使用if-else的交易验证
bool ValidateTrade() {
double spread = MarketInfo(Symbol(), MODE_SPREAD);
int orderCount = CountOrders(magicNumber);
if(spread <= 30 && orderCount == 0) {
Print("交易验证通过:点差=", spread, " 订单数=", orderCount);
return true;
} else {
Print("交易验证失败:点差=", spread, " 订单数=", orderCount);
return false;
}
}
```
五、else-if语句 - 多向分支
else-if链允许你按顺序测试多个条件。第一个为真的条件执行其对应的代码块。
```mql4
// 基础else-if语法
if(条件1) {
// 条件1为真时执行
} else if(条件2) {
// 条件1为假且条件2为真时执行
} else if(条件3) {
// 条件1和条件2为假且条件3为真时执行
} else {
// 所有条件都为假时执行
}
// 实用EA示例 - RSI信号强度分类
int ClassifyRSISignal(double rsiValue) {
if(rsiValue < 20) {
Print("极端超卖 - 强买入信号");
return SIGNAL_STRONG_BUY;
} else if(rsiValue < 30) {
Print("超卖 - 中等买入信号");
return SIGNAL_BUY;
} else if(rsiValue > 80) {
Print("极端超买 - 强卖出信号");
return SIGNAL_STRONG_SELL;
} else if(rsiValue > 70) {
Print("超买 - 中等卖出信号");
return SIGNAL_SELL;
} else {
Print("中性区域 - 无信号");
return SIGNAL_NEUTRAL;
}
}
// 多条件交易策略
void ExecuteMultiConditionStrategy() {
double maFast = iMA(NULL, 0, 10, 0, MODE_SMA, PRICE_CLOSE, 1);
double maSlow = iMA(NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 1);
double rsi = iRSI(NULL, 0, 14, PRICE_CLOSE, 1);
double macd = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1);
int orderCount = CountOrders(magicNumber);
if(orderCount > 0) {
// 已有持仓 - 管理持仓
ManageExistingPositions();
}
else if(maFast > maSlow && rsi < 30 && macd < 0) {
// 强买入信号 - 所有指标一致
Print("检测到强买入信号");
OpenBuyOrder(CalculateLotSize(2, 50));
}
else if(maFast > maSlow && rsi < 40) {
// 中等买入信号 - 上涨趋势 + RSI未超卖
Print("检测到中等买入信号");
OpenBuyOrder(CalculateLotSize(1, 50));
}
else if(maFast < maSlow && rsi > 70 && macd > 0) {
// 强卖出信号 - 所有指标一致
Print("检测到强卖出信号");
OpenSellOrder(CalculateLotSize(2, 50));
}
else if(maFast < maSlow && rsi > 60) {
// 中等卖出信号
Print("检测到中等卖出信号");
OpenSellOrder(CalculateLotSize(1, 50));
}
else {
// 无明确信号 - 等待
Comment("当前无交易信号");
}
}
// 基于时间的策略选择
void SelectTimeBasedStrategy() {
MqlDateTime timeStruct;
TimeToStruct(TimeCurrent(), timeStruct);
int hour = timeStruct.hour;
if(hour >= 2 && hour < 6) {
Print("亚洲时段 - 使用区间交易策略");
ExecuteRangeStrategy();
}
else if(hour >= 6 && hour < 12) {
Print("伦敦时段 - 使用突破策略");
ExecuteBreakoutStrategy();
}
else if(hour >= 12 && hour < 18) {
Print("纽约时段 - 使用动量策略");
ExecuteMomentumStrategy();
}
else if(hour >= 18 && hour < 22) {
Print("重叠时段 - 使用剥头皮策略");
ExecuteScalpStrategy();
}
else {
Print("低流动性时段 - 仅监控");
MonitorOnly();
}
}
```
六、switch语句 - 多离散值分支
当需要根据单个整数或枚举变量的值进行分支时,switch语句是理想选择。
```mql4
// 基础switch语法
switch(表达式) {
case 值1:
// 当表达式 == 值1时执行
break;
case 值2:
// 当表达式 == 值2时执行
break;
default:
// 当没有case匹配时执行
break;
}
// 实用EA示例 - 订单类型处理
string GetOrderTypeName(int orderType) {
switch(orderType) {
case OP_BUY:
return "买入";
case OP_SELL:
return "卖出";
case OP_BUYLIMIT:
return "买入限价";
case OP_SELLLIMIT:
return "卖出限价";
case OP_BUYSTOP:
return "买入止损";
case OP_SELLSTOP:
return "卖出止损";
default:
return "未知";
}
}
// 使用switch处理信号
void ProcessSignal(int signalType) {
switch(signalType) {
case SIGNAL_STRONG_BUY:
OpenBuyOrder(0.2);
SendAlert("强买入信号 - 开仓0.2手");
break;
case SIGNAL_BUY:
OpenBuyOrder(0.1);
SendAlert("买入信号 - 开仓0.1手");
break;
case SIGNAL_STRONG_SELL:
OpenSellOrder(0.2);
SendAlert("强卖出信号 - 开仓0.2手");
break;
case SIGNAL_SELL:
OpenSellOrder(0.1);
SendAlert("卖出信号 - 开仓0.1手");
break;
case SIGNAL_CLOSE_ALL:
CloseAllPositions();
SendAlert("平仓信号 - 关闭所有持仓");
break;
default:
Print("未知信号类型:", signalType);
break;
}
}
// 使用switch处理错误码
void HandleOrderSendError(int errorCode) {
switch(errorCode) {
case 130:
Print("错误130:无效止损 - 检查距离要求");
AdjustStopLossDistance();
break;
case 134:
Print("错误134:资金不足 - 减少手数");
ReduceLotSize();
break;
case 146:
Print("错误146:交易上下文繁忙 - 重试");
Sleep(1000);
break;
case 148:
Print("错误148:订单过多 - 先关闭部分持仓");
CloseOldestPosition();
break;
default:
Print("未知错误:", errorCode);
break;
}
}
```
七、完整EA模板(使用所有条件判断语句)
```mql4
//+------------------------------------------------------------------+
//| ConditionalEA.mq4 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024"
#property version "1.00"
#property strict
input double InpLotSize = 0.1;
input int InpMagic = 12345;
input int InpMaxSpread = 30;
input int InpMaxDailyTrades = 5;
input bool InpUseTimeFilter = true;
input int InpStartHour = 8;
input int InpEndHour = 17;
int g_dailyTradeCount = 0;
double g_dailyProfit = 0;
datetime g_lastReset = 0;
// 信号常量定义
#define SIGNAL_NONE 0
#define SIGNAL_BUY 1#define SIGNAL_SELL 2
#define SIGNAL_STRONG_BUY 3
#define SIGNAL_STRONG_SELL 4
//+------------------------------------------------------------------+
//| EA初始化函数 |
//+------------------------------------------------------------------+
int OnInit() {
g_lastReset = GetMidnight();
Print("条件判断EA已初始化");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| EA主执行函数 |
//+------------------------------------------------------------------+
void OnTick() {
static datetime lastBarTime = 0;
// 新K线检测
if(Time[0] == lastBarTime) return;
lastBarTime = Time[0];
// 午夜重置每日计数器
ResetDailyIfNeeded();
// 使用if语句检查交易条件
if(!IsTradeAllowed()) {
Comment("自动交易未开启");
return;
}
if(IsMaxTradesReached()) {
Comment("每日交易限额已达:", g_dailyTradeCount, "/", InpMaxDailyTrades);
return;
}
if(InpUseTimeFilter && !IsTradingHours()) {
Comment("非交易时段");
return;
}
// 使用else-if链的主交易逻辑
ExecuteTradingStrategy();
}
//+------------------------------------------------------------------+
//| 重置每日计数器 |
//+------------------------------------------------------------------+
void ResetDailyIfNeeded() {
datetime midnight = GetMidnight();
if(midnight != g_lastReset) {
g_dailyTradeCount = 0;
g_dailyProfit = 0;
g_lastReset = midnight;
Print("每日计数器已重置");
}
}
//+------------------------------------------------------------------+
//| 使用else-if的主交易策略 |
//+------------------------------------------------------------------+
void ExecuteTradingStrategy() {
// 计算指标值
double maFast = iMA(NULL, 0, 10, 0, MODE_SMA, PRICE_CLOSE, 1);
double maSlow = iMA(NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 1);
double rsi = iRSI(NULL, 0, 14, PRICE_CLOSE, 1);
double macd = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1);
double spread = MarketInfo(Symbol(), MODE_SPREAD);
int currentOrders = CountOrders(InpMagic);
// 使用if验证点差
if(spread > InpMaxSpread) {
Comment("点差过高:", spread);
return;
}
// 使用if-else管理持仓
if(currentOrders > 0) {
ManageOpenPositions();
return;
}
// 使用else-if链生成信号
int signal = SIGNAL_NONE;
if(maFast > maSlow && rsi < 30 && macd < 0) {
signal = SIGNAL_STRONG_BUY;
}
else if(maFast > maSlow && rsi < 40) {
signal = SIGNAL_BUY;
}
else if(maFast < maSlow && rsi > 70 && macd > 0) {
signal = SIGNAL_STRONG_SELL;
}
else if(maFast < maSlow && rsi > 60) {
signal = SIGNAL_SELL;
}
// 使用switch根据信号执行交易
switch(signal) {
case SIGNAL_STRONG_BUY:
OpenTrade(OP_BUY, InpLotSize * 1.5);
break;
case SIGNAL_BUY:
OpenTrade(OP_BUY, InpLotSize);
break;
case SIGNAL_STRONG_SELL:
OpenTrade(OP_SELL, InpLotSize * 1.5);
break;
case SIGNAL_SELL:
OpenTrade(OP_SELL, InpLotSize);
break;
default:
// 嵌套if用于不同市场状态
if(maFast > maSlow) {
Comment("上涨趋势但无入场条件");
} else if(maFast < maSlow) {
Comment("下跌趋势但无入场条件");
} else {
Comment("横盘市场 - 等待");
}
break;
}
}
//+------------------------------------------------------------------+
//| 管理持仓 |
//+------------------------------------------------------------------+
void ManageOpenPositions() {
for(int i = 0; i < OrdersTotal(); i++) {
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
if(OrderMagicNumber() == InpMagic && OrderSymbol() == Symbol()) {
double profit = OrderProfit();
double currentPrice = (OrderType() == OP_BUY) ? Bid : Ask;
double profitPoints = 0;
if(OrderType() == OP_BUY) {
profitPoints = (currentPrice - OrderOpenPrice()) / Point();
} else {
profitPoints = (OrderOpenPrice() - currentPrice) / Point();
}
// 使用else-if实现移动止损逻辑
if(profitPoints >= 50) {
// 移动至保本
double newStop = OrderOpenPrice();
if(ModifyStopLoss(OrderTicket(), newStop)) {
Print("止损已移至保本位");
}
}
else if(profitPoints >= 30) {
// 部分移动
double newStop = OrderOpenPrice() + (OrderType() == OP_BUY ? 10 * Point() : -10 * Point());
ModifyStopLoss(OrderTicket(), newStop);
}
else {
// 仅监控
Comment("监控持仓中:盈利=", profitPoints, "点");
}
}
}
}
}
```
八、条件判断语句最佳实践清单
参考来源:
9. 下一步
第9篇将讲解MQL4循环结构(for/while/do-while) – 批量处理订单、数组遍历和重复任务的完整指南,附带实际EA代码示例。