N 字战法 MT4 实现[color=var(--md-box-samantha-normal-text-color) !important]N 字战法是一种基于价格形态识别的交易策略,其核心是识别价格走势中的 "N" 字形结构:上涨(第一笔)、回调(第二笔)、再上涨(第三笔)形成多头信号;反之则形成空头信号。以下是一个完整的 MT4 实现:
策略核心逻辑- [color=var(--md-box-samantha-normal-text-color) !important][color=var(--md-box-samantha-deep-text-color) !important]N 字形态识别:
- 看涨形态:低点→高点→回调低点→突破新高
- 看跌形态:高点→低点→回调高点→跌破新低
- [color=var(--md-box-samantha-normal-text-color) !important][color=var(--md-box-samantha-deep-text-color) !important]形态参数:
- 回调幅度:要求在第一笔幅度的 30%-70% 之间
- 形态长度:最小 5 根 K 线,最大 20 根 K 线
- [color=var(--md-box-samantha-normal-text-color) !important][color=var(--md-box-samantha-deep-text-color) !important]交易信号:
- 看涨信号:价格突破回调后的高点
- 看跌信号:价格跌破回调后的低点
- [color=var(--md-box-samantha-normal-text-color) !important][color=var(--md-box-samantha-deep-text-color) !important]可视化功能:
- 在图表上绘制识别出的 N 字形态
- 标注看涨 / 看跌信号
使用建议- [color=var(--md-box-samantha-normal-text-color) !important][color=var(--md-box-samantha-deep-text-color) !important]参数调整:
- 根据不同货币对和时间周期调整 MinRetracePercent 和 MaxRetracePercent
- 在波动较大的市场可以适当放宽回调幅度限制
- [color=var(--md-box-samantha-normal-text-color) !important][color=var(--md-box-samantha-deep-text-color) !important]确认条件:
- 建议结合趋势指标(如均线)确认大趋势方向
- 可添加成交量指标确认突破有效性
- [color=var(--md-box-samantha-normal-text-color) !important][color=var(--md-box-samantha-deep-text-color) !important]风险管理:
- 严格执行止损,控制单笔风险
- 可考虑使用追踪止损保护已有利润
- [color=var(--md-box-samantha-normal-text-color) !important][color=var(--md-box-samantha-deep-text-color) !important]优化方向:
- 添加时间过滤器,避免在低流动性时段交易
- 增加对 N 字形态强度的评估
- 结合其他指标(如 MACD、RSI)进行二次确认
这个 EA 提供了 N 字战法的基本实现,你可以根据自己的交易经验和市场特点进行个性化调整。//+------------------------------------------------------------------+
//| N字战法交易策略 |
//+------------------------------------------------------------------+
#property copyright "DoubaoAssistant"
#property link ""
#property version "1.00"
#property strict
// 输入参数
input int MinBars = 5; // 最小N字结构柱数
input int MaxBars = 20; // 最大N字结构柱数
input double MinRetracePercent = 30.0; // 最小回调百分比(相对于第一笔)
input double MaxRetracePercent = 70.0; // 最大回调百分比(相对于第一笔)
input double LotSize = 0.1; // 交易手数
input int StopLoss = 50; // 止损点数
input int TakeProfit = 100; // 止盈点数
input bool Alerts = true; // 启用警报
input bool EmailAlert = false; // 启用邮件警报
input bool PushAlert = false; // 启用推送通知
// 全局变量
enum PatternType { NONE, BULLISH, BEARISH };
PatternType currentPattern = NONE;
int patternStartBar = 0;
int patternPeakBar = 0;
int patternEndBar = 0;
double patternPeakPrice = 0;
double patternStartPrice = 0;
double patternEndPrice = 0;
//+------------------------------------------------------------------+
//| EA初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| EA主函数 |
//+------------------------------------------------------------------+
void OnTick()
{
// 识别N字形态
IdentifyPattern();
// 检查交易信号
CheckTradeSignal();
// 绘制形态
DrawPattern();
}
//+------------------------------------------------------------------+
//| 识别N字形态 |
//+------------------------------------------------------------------+
void IdentifyPattern()
{
// 重置当前形态
currentPattern = NONE;
// 从当前柱向前寻找可能的N字形态
for(int i = MinBars; i <= MaxBars; i++)
{
// 寻找看涨N字形态
if(IdentifyBullishPattern(i))
{
currentPattern = BULLISH;
break;
}
// 寻找看跌N字形态
if(IdentifyBearishPattern(i))
{
currentPattern = BEARISH;
break;
}
}
}
//+------------------------------------------------------------------+
//| 识别看涨N字形态 |
//+------------------------------------------------------------------+
bool IdentifyBullishPattern(int barsAgo)
{
// 寻找第一个高点(峰)
int peakBar = FindPeakBar(barsAgo, MODE_HIGH);
if(peakBar == 0) return false;
// 寻找起点(峰前的低点)
int startBar = FindTroughBar(peakBar - 1, MODE_LOW);
if(startBar == 0 || startBar >= peakBar) return false;
// 寻找终点(峰后的低点)
int endBar = FindTroughBar(peakBar + 1, MODE_LOW);
if(endBar == 0 || endBar <= peakBar) return false;
// 计算第一笔涨幅
double firstLeg = High[peakBar] - Low[startBar];
if(firstLeg <= 0) return false;
// 计算回调幅度
double retrace = High[peakBar] - Low[endBar];
double retracePercent = (retrace / firstLeg) * 100;
// 检查回调是否在合理范围内
if(retracePercent < MinRetracePercent || retracePercent > MaxRetracePercent) return false;
// 检查回调后是否有足够的上涨动能
double currentPrice = Close[0];
double breakout = currentPrice - Low[endBar];
if(breakout <= 0) return false;
// 保存形态信息
patternStartBar = startBar;
patternPeakBar = peakBar;
patternEndBar = endBar;
patternStartPrice = Low[startBar];
patternPeakPrice = High[peakBar];
patternEndPrice = Low[endBar];
return true;
}
//+------------------------------------------------------------------+
//| 识别看跌N字形态 |
//+------------------------------------------------------------------+
bool IdentifyBearishPattern(int barsAgo)
{
// 寻找第一个低点(谷)
int troughBar = FindTroughBar(barsAgo, MODE_LOW);
if(troughBar == 0) return false;
// 寻找起点(谷前的高点)
int startBar = FindPeakBar(troughBar - 1, MODE_HIGH);
if(startBar == 0 || startBar >= troughBar) return false;
// 寻找终点(谷后的高点)
int endBar = FindPeakBar(troughBar + 1, MODE_HIGH);
if(endBar == 0 || endBar <= troughBar) return false;
// 计算第一笔跌幅
double firstLeg = High[startBar] - Low[troughBar];
if(firstLeg <= 0) return false;
// 计算回调幅度
double retrace = High[endBar] - Low[troughBar];
double retracePercent = (retrace / firstLeg) * 100;
// 检查回调是否在合理范围内
if(retracePercent < MinRetracePercent || retracePercent > MaxRetracePercent) return false;
// 检查回调后是否有足够的下跌动能
double currentPrice = Close[0];
double breakout = High[endBar] - currentPrice;
if(breakout <= 0) return false;
// 保存形态信息
patternStartBar = startBar;
patternPeakBar = troughBar; // 看跌形态中,第一个低点是峰
patternEndBar = endBar;
patternStartPrice = High[startBar];
patternPeakPrice = Low[troughBar];
patternEndPrice = High[endBar];
return true;
}
//+------------------------------------------------------------------+
//| 寻找峰值柱 |
//+------------------------------------------------------------------+
int FindPeakBar(int startBar, int priceType)
{
double peakPrice = (priceType == MODE_HIGH) ? High[startBar] : Low[startBar];
int peakBar = startBar;
// 向前查找
for(int i = startBar; i >= 0; i--)
{
double currentPrice = (priceType == MODE_HIGH) ? High : Low;
if(currentPrice > peakPrice)
{
peakPrice = currentPrice;
peakBar = i;
}
else if(currentPrice < peakPrice)
{
break;
}
}
// 向后查找
for(int i = startBar + 1; i < Bars; i++)
{
double currentPrice = (priceType == MODE_HIGH) ? High : Low;
if(currentPrice > peakPrice)
{
return 0; // 不是峰值
}
else if(currentPrice < peakPrice)
{
break;
}
}
return peakBar;
}
//+------------------------------------------------------------------+
//| 寻找谷值柱 |
//+------------------------------------------------------------------+
int FindTroughBar(int startBar, int priceType)
{
double troughPrice = (priceType == MODE_HIGH) ? High[startBar] : Low[startBar];
int troughBar = startBar;
// 向前查找
for(int i = startBar; i >= 0; i--)
{
double currentPrice = (priceType == MODE_HIGH) ? High : Low;
if(currentPrice < troughPrice)
{
troughPrice = currentPrice;
troughBar = i;
}
else if(currentPrice > troughPrice)
{
break;
}
}
// 向后查找
for(int i = startBar + 1; i < Bars; i++)
{
double currentPrice = (priceType == MODE_HIGH) ? High : Low;
if(currentPrice < troughPrice)
{
return 0; // 不是谷值
}
else if(currentPrice > troughPrice)
{
break;
}
}
return troughBar;
}
//+------------------------------------------------------------------+
//| 检查交易信号 |
//+------------------------------------------------------------------+
void CheckTradeSignal()
{
// 检查是否有未平仓订单
if(HasOpenOrders()) return;
// 看涨N字信号
if(currentPattern == BULLISH)
{
// 价格突破回调后的高点
if(Close[0] > High[patternEndBar])
{
OpenBuyOrder();
if(Alerts)
{
string alertMsg = Symbol() + " N字看涨信号 @" + TimeToStr(TimeCurrent(), TIME_SECONDS);
Print(alertMsg);
if(EmailAlert) SendMail("N字战法警报", alertMsg);
if(PushAlert) SendNotification(alertMsg);
}
}
}
// 看跌N字信号
else if(currentPattern == BEARISH)
{
// 价格跌破回调后的低点
if(Close[0] < Low[patternEndBar])
{
OpenSellOrder();
if(Alerts)
{
string alertMsg = Symbol() + " N字看跌信号 @" + TimeToStr(TimeCurrent(), TIME_SECONDS);
Print(alertMsg);
if(EmailAlert) SendMail("N字战法警报", alertMsg);
if(PushAlert) SendNotification(alertMsg);
}
}
}
}
//+------------------------------------------------------------------+
//| 绘制N字形态 |
//+------------------------------------------------------------------+
void DrawPattern()
{
// 清除旧标记
ObjectsDeleteAll(0, "NPattern_");
if(currentPattern == NONE) return;
string prefix = "NPattern_" + IntegerToString(patternStartBar);
color patternColor = (currentPattern == BULLISH) ? clrGreen : clrRed;
// 绘制N字形态
ObjectCreate(prefix + "_L1", OBJ_TREND, 0, Time[patternStartBar], patternStartPrice, Time[patternPeakBar], patternPeakPrice);
ObjectSet(prefix + "_L1", OBJPROP_COLOR, patternColor);
ObjectSet(prefix + "_L1", OBJPROP_WIDTH, 2);
ObjectCreate(prefix + "_L2", OBJ_TREND, 0, Time[patternPeakBar], patternPeakPrice, Time[patternEndBar], patternEndPrice);
ObjectSet(prefix + "_L2", OBJPROP_COLOR, patternColor);
ObjectSet(prefix + "_L2", OBJPROP_WIDTH, 2);
// 添加标签
string label = (currentPattern == BULLISH) ? "Bullish N" : "Bearish N";
ObjectCreate(prefix + "_Label", OBJ_TEXT, 0, Time[patternEndBar], patternEndPrice);
ObjectSetText(prefix + "_Label", label, 8, "Arial", patternColor);
}
//+------------------------------------------------------------------+
//| 检查是否有未平仓订单 |
//+------------------------------------------------------------------+
bool HasOpenOrders()
{
for(int i = 0; i < OrdersTotal(); i++) {
if(OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == Symbol()) {
return true;
}
}
return false;
}
//+------------------------------------------------------------------+
//| 开多单 |
//+------------------------------------------------------------------+
void OpenBuyOrder()
{
int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, 3, Ask - StopLoss * Point,
Ask + TakeProfit * Point, "N Pattern Buy", 0, 0, clrGreen);
if(ticket > 0) {
Print("买入订单执行成功,单号: ", ticket);
} else {
Print("买入订单执行失败,错误码: ", GetLastError());
}
}
//+------------------------------------------------------------------+
//| 开空单 |
//+------------------------------------------------------------------+
void OpenSellOrder()
{
int ticket = OrderSend(Symbol(), OP_SELL, LotSize, Bid, 3, Bid + StopLoss * Point,
Bid - TakeProfit * Point, "N Pattern Sell", 0, 0, clrRed);
if(ticket > 0) {
Print("卖出订单执行成功,单号: ", ticket);
} else {
Print("卖出订单执行失败,错误码: ", GetLastError());
}
}
|