Summary: 黄金K线稳定器EA是一款专为XAUUSD设计的MQL4智能交易系统。识别孕线形态、动量K线和假突破拒绝信号,适合H1周期稳定运行。
黄金K线稳定器EA专注于纯K线分析,不使用传统指标。它识别孕线(窄幅盘整)、动量K线(实体大、影线小)以及假突破拒绝信号(价格刺穿区间但收盘回归)。EA等待压缩形态(孕线)出现,随后动量K线突破区间,在价格回踩确认时入场。基于孕线区间的动态止损和风险控制的盈利目标确保了稳定性。
推荐加载周期: H1
策略核心逻辑:
1. 孕线检测:当前K线最高价 ≤ 前一根K线最高价,且最低价 ≥ 前一根K线最低价。
2. 压缩确认:要求孕线实体的体幅比 > 0.6(强盘整)。
3. 动量信号:下一根K线收盘价高于孕线高点(做多)或低于孕线低点(做空),且实体 > 2倍影线。
4. 回踩入场:等待价格回测被突破的区间边界(50%-80%回撤幅度)再入场。
5. 风险管理:止损设在孕线区间另一侧,止盈为2倍孕线区间,盈利达到1倍区间后启动追踪止损。
```mql4
//+------------------------------------------------------------------+
//| GoldKBarStabilizer.mq4 |
//+------------------------------------------------------------------+
#property copyright ""
#property link ""
#property version "1.00"
#property strict
//--- 输入参数及注释
input double LotSize = 0.01; // 固定交易手数(黄金0.01手)
input double BodyToRangeMinRatio = 0.6; // 孕线实体最小体幅比(强盘整要求)
input double MomentumBodyWickRatio = 2.0; // 动量K线实体/影线最小比例
input double RetracementMinPercent = 0.5; // 最小回撤百分比(突破区间的50%)
input double RetracementMaxPercent = 0.8; // 最大回撤百分比(突破区间的80%)
input double StopLossMultiplier = 1.0; // 止损倍数(孕线区间的倍数)
input double TakeProfitMultiplier = 2.0; // 止盈倍数(孕线区间的倍数)
input double TrailingActivate = 1.0; // 追踪止损启动(盈利达到x倍孕线区间)
input double TrailingStep = 0.5; // 追踪步长(孕线区间倍数)
input int MagicNumber = 202418; // EA魔术号
input int MaxSpread = 35; // 最大允许点差(黄金单位:点)
input double DailyLossLimit = 5.0; // 每日亏损限额(账户余额百分比)
input bool UseFridayClose = true; // 周五21:00 GMT前平仓
//--- 全局变量
double dailyStartBalance = 0;
datetime lastBarTime = 0;
bool fridayCloseExecuted = false;
double insideBarHigh = 0;
double insideBarLow = 0;
double insideBarRange = 0;
double breakoutPrice = 0;
int breakoutDirection = 0; // 1=做多, -1=做空
datetime insideBarTime = 0;
//+------------------------------------------------------------------+
//| EA初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
dailyStartBalance = AccountBalance();
lastBarTime = 0;
fridayCloseExecuted = false;
insideBarHigh = 0;
insideBarLow = 0;
breakoutDirection = 0;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| EA退出函数 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}
//+------------------------------------------------------------------+
//| 计算K线实体与区间比例 |
//+------------------------------------------------------------------+
double BodyToRangeRatio(int shift)
{
double open = iOpen(Symbol(), PERIOD_H1, shift);
double close = iClose(Symbol(), PERIOD_H1, shift);
double high = iHigh(Symbol(), PERIOD_H1, shift);
double low = iLow(Symbol(), PERIOD_H1, shift);
double body = MathAbs(close - open);
double range = high - low;
if(range <= 0) return 0;
return body / range;
}
//+------------------------------------------------------------------+
//| 检测孕线形态 |
//+------------------------------------------------------------------+
bool IsInsideBar(int shift)
{
double currHigh = iHigh(Symbol(), PERIOD_H1, shift);
double currLow = iLow(Symbol(), PERIOD_H1, shift);
double prevHigh = iHigh(Symbol(), PERIOD_H1, shift + 1);
double prevLow = iLow(Symbol(), PERIOD_H1, shift + 1);
return (currHigh <= prevHigh && currLow >= prevLow);
}
//+------------------------------------------------------------------+
//| 检测动量K线(实体大,影线小) |
//+------------------------------------------------------------------+
bool IsMomentumCandle(int shift, int direction)
{
double open = iOpen(Symbol(), PERIOD_H1, shift);
double close = iClose(Symbol(), PERIOD_H1, shift);
double high = iHigh(Symbol(), PERIOD_H1, shift);
double low = iLow(Symbol(), PERIOD_H1, shift);
double body = MathAbs(close - open);
double upperWick = high - MathMax(open, close);
double lowerWick = MathMin(open, close) - low;
double maxWick = MathMax(upperWick, lowerWick);
if(maxWick <= 0) return false;
if(body / maxWick < MomentumBodyWickRatio) return false;
if(direction == 1) // 看涨动量
return (close > open && close > insideBarHigh);
else if(direction == -1) // 看跌动量
return (close < open && close < insideBarLow);
return false;
}
//+------------------------------------------------------------------+
//| 检查回撤入场机会 |
//+------------------------------------------------------------------+
bool CheckRetracementEntry(int &cmd, double &entryPrice, double &stopLoss, double &takeProfit)
{
if(breakoutDirection == 0) return false;
if(insideBarRange <= 0) return false;
double currentPrice = (breakoutDirection == 1) ? Bid : Ask;
double breakoutHigh = insideBarHigh;
double breakoutLow = insideBarLow;
double retraceLow = breakoutHigh - (insideBarRange * RetracementMaxPercent);
double retraceHigh = breakoutLow + (insideBarRange * RetracementMaxPercent);
if(breakoutDirection == 1) // 做多:价格突破孕线高点,现在回撤
{
if(currentPrice <= breakoutHigh && currentPrice >= retraceLow)
{
cmd = OP_BUY;
entryPrice = Ask;
stopLoss = insideBarLow - (insideBarRange * StopLossMultiplier * 0.3);
takeProfit = insideBarHigh + (insideBarRange * TakeProfitMultiplier);
return true;
}
}
else if(breakoutDirection == -1) // 做空:价格跌破孕线低点,现在回抽
{
if(currentPrice >= breakoutLow && currentPrice <= retraceHigh)
{
cmd = OP_SELL;
entryPrice = Bid;
stopLoss = insideBarHigh + (insideBarRange * StopLossMultiplier * 0.3);
takeProfit = insideBarLow - (insideBarRange * TakeProfitMultiplier);
return true;
}
}
return false;
}
//+------------------------------------------------------------------+
//| 管理追踪止损 |
//+------------------------------------------------------------------+
void ManageTrailing()
{
if(insideBarRange <= 0) return;
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
double activateLevel = insideBarRange * TrailingActivate;
double step = insideBarRange * TrailingStep;
double newSL = 0;
if(OrderType() == OP_BUY)
{
double profit = Bid - OrderOpenPrice();
if(profit >= activateLevel)
{
newSL = Bid - step;
if(newSL > OrderStopLoss())
OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE);
}
}
else if(OrderType() == OP_SELL)
{
double profit = OrderOpenPrice() - Ask;
if(profit >= activateLevel)
{
newSL = Ask + step;
if(newSL < OrderStopLoss() || OrderStopLoss() == 0)
OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE);
}
}
break;
}
}
}
}
//+------------------------------------------------------------------+
//| EA主循环函数(每Tick执行) |
//+------------------------------------------------------------------+
void OnTick()
{
// 每日净值保护
double currentEquity = AccountEquity();
double lossPercent = (dailyStartBalance - currentEquity) / dailyStartBalance * 100;
if(lossPercent >= DailyLossLimit)
{
Comment("已达每日亏损上限,停止开新仓");
return;
}
// 周五收盘前平仓(规避周末跳空)
if(UseFridayClose && !fridayCloseExecuted)
{
datetime currentTime = TimeCurrent();
if(TimeDayOfWeek(currentTime) == 5 && TimeHour(currentTime) >= 21)
{
CloseAllOrders();
fridayCloseExecuted = true;
return;
}
if(TimeDayOfWeek(currentTime) != 5)
fridayCloseExecuted = false;
}
// 点差过滤
if(MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread)
{
Comment("当前点差过大:", MarketInfo(Symbol(), MODE_SPREAD));
return;
}
// 仅在新K线开始时检测入场(H1)
if(Time[0] == lastBarTime)
return;
lastBarTime = Time[0];
// 管理现有持仓
if(CountPositions() > 0)
{
ManageTrailing();
return;
}
// 如果孕线时间超过5根K线,重置突破状态
if(insideBarTime > 0 && TimeCurrent() - insideBarTime > 5 * 3600)
{
breakoutDirection = 0;
insideBarHigh = 0;
insideBarLow = 0;
insideBarRange = 0;
}
// 步骤1:检测前一根K线(shift=1)是否为孕线
if(IsInsideBar(1))
{
double ratio = BodyToRangeRatio(1);
if(ratio >= BodyToRangeMinRatio)
{
insideBarHigh = iHigh(Symbol(), PERIOD_H1, 1);
insideBarLow = iLow(Symbol(), PERIOD_H1, 1);
insideBarRange = insideBarHigh - insideBarLow;
insideBarTime = iTime(Symbol(), PERIOD_H1, 1);
breakoutDirection = 0;
}
}
// 步骤2:孕线检测后,检查当前K线(shift=0)是否有动量突破
if(insideBarRange > 0 && breakoutDirection == 0)
{
if(IsMomentumCandle(0, 1))
{
breakoutDirection = 1;
breakoutPrice = iClose(Symbol(), PERIOD_H1, 0);
}
else if(IsMomentumCandle(0, -1))
{
breakoutDirection = -1;
breakoutPrice = iClose(Symbol(), PERIOD_H1, 0);
}
}
// 步骤3:突破后,等待回撤并入场
if(breakoutDirection != 0 && CountPositions() == 0)
{
int cmd = -1;
double entryPrice = 0, sl = 0, tp = 0;
if(CheckRetracementEntry(cmd, entryPrice, sl, tp))
{
int ticket = OrderSend(Symbol(), cmd, LotSize, entryPrice, 5, sl, tp, "Gold K-Bar", MagicNumber, 0, clrNONE);
if(ticket < 0)
{
Print("开仓失败,错误码:", GetLastError());
}
else
{
Print("回撤入场成功,方向:", cmd==OP_BUY?"买入":"卖出");
// 重置以避免同一形态重复入场
breakoutDirection = 0;
}
}
}
}
//+------------------------------------------------------------------+
//| 统计当前魔术号的持仓数量 |
//+------------------------------------------------------------------+
int CountPositions()
{
int count = 0;
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
count++;
}
}
return count;
}
//+------------------------------------------------------------------+
//| 平仓当前品种下所有属于该EA的订单 |
//+------------------------------------------------------------------+
void CloseAllOrders()
{
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
if(OrderType() == OP_BUY)
OrderClose(OrderTicket(), OrderLots(), Bid, 5, clrNONE);
else if(OrderType() == OP_SELL)
OrderClose(OrderTicket(), OrderLots(), Ask, 5, clrNONE);
}
}
}
}
//+------------------------------------------------------------------+
```
参考来源: 原创MQL4代码,仅供学习参考。
免责声明: 黄金交易因高波动性和杠杆具有重大风险。本EA按“原样”提供,不保证盈利。实盘交易前请在模拟账户测试至少1个月。历史表现不代表未来结果。
```