//+------------------------------------------------------------------+
//| KLinePatterns.mq4 |
//| |
//| |
//+------------------------------------------------------------------+
#property copyright ""
#property link ""
#property version "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 8
#property indicator_plots 8
//--- 输入参数
input bool ShowPinBar = true; // 显示Pin Bar
input bool ShowEngulfing = true; // 显示吞没形态
input bool ShowHammer = true; // 显示锤子线
input bool ShowShootingStar = true; // 显示射击之星
input bool ShowThreeSoldiers = true; // 显示红三兵
input bool ShowThreeCrows = true; // 显示三只乌鸦
input bool ShowDoji = true; // 显示十字星
input bool ShowHarami = true; // 显示孕线
input int MinBodySizePoints = 30; // 最小实体大小(点)
input int LookbackBars = 100; // 检查的K线数量
//--- 缓冲区
double PinBarBuffer[];
double EngulfingBuffer[];
double HammerBuffer[];
double ShootingStarBuffer[];
double ThreeSoldiersBuffer[];
double ThreeCrowsBuffer[];
double DojiBuffer[];
double HaramiBuffer[];
//+------------------------------------------------------------------+
//| 自定义初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- 设置指标缓冲区
SetIndexBuffer(0, PinBarBuffer);
SetIndexBuffer(1, EngulfingBuffer);
SetIndexBuffer(2, HammerBuffer);
SetIndexBuffer(3, ShootingStarBuffer);
SetIndexBuffer(4, ThreeSoldiersBuffer);
SetIndexBuffer(5, ThreeCrowsBuffer);
SetIndexBuffer(6, DojiBuffer);
SetIndexBuffer(7, HaramiBuffer);
//--- 设置指标线属性
SetIndexStyle(0, DRAW_ARROW, EMPTY, 2, clrYellow);
SetIndexArrow(0, 108);
SetIndexLabel(0, "Pin Bar");
SetIndexStyle(1, DRAW_ARROW, EMPTY, 2, clrBlue);
SetIndexArrow(1, 110);
SetIndexLabel(1, "Engulfing");
SetIndexStyle(2, DRAW_ARROW, EMPTY, 2, clrGreen);
SetIndexArrow(2, 115);
SetIndexLabel(2, "Hammer");
SetIndexStyle(3, DRAW_ARROW, EMPTY, 2, clrRed);
SetIndexArrow(3, 116);
SetIndexLabel(3, "Shooting Star");
SetIndexStyle(4, DRAW_ARROW, EMPTY, 2, clrLime);
SetIndexArrow(4, 118);
SetIndexLabel(4, "Three Soldiers");
SetIndexStyle(5, DRAW_ARROW, EMPTY, 2, clrMaroon);
SetIndexArrow(5, 119);
SetIndexLabel(5, "Three Crows");
SetIndexStyle(6, DRAW_ARROW, EMPTY, 2, clrGray);
SetIndexArrow(6, 120);
SetIndexLabel(6, "Doji");
SetIndexStyle(7, DRAW_ARROW, EMPTY, 2, clrPurple);
SetIndexArrow(7, 121);
SetIndexLabel(7, "Harami");
//--- 初始化缓冲区
ArrayInitialize(PinBarBuffer, EMPTY_VALUE);
ArrayInitialize(EngulfingBuffer, EMPTY_VALUE);
ArrayInitialize(HammerBuffer, EMPTY_VALUE);
ArrayInitialize(ShootingStarBuffer, EMPTY_VALUE);
ArrayInitialize(ThreeSoldiersBuffer, EMPTY_VALUE);
ArrayInitialize(ThreeCrowsBuffer, EMPTY_VALUE);
ArrayInitialize(DojiBuffer, EMPTY_VALUE);
ArrayInitialize(HaramiBuffer, EMPTY_VALUE);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| 自定义指标迭代函数 |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[])
{
int limit = rates_total - prev_calculated;
if(prev_calculated > 0)
limit++;
limit = MathMin(limit, LookbackBars);
for(int i = limit - 1; i >= 0; i--)
{
// 清除当前值
PinBarBuffer[i] = EMPTY_VALUE;
EngulfingBuffer[i] = EMPTY_VALUE;
HammerBuffer[i] = EMPTY_VALUE;
ShootingStarBuffer[i] = EMPTY_VALUE;
ThreeSoldiersBuffer[i] = EMPTY_VALUE;
ThreeCrowsBuffer[i] = EMPTY_VALUE;
DojiBuffer[i] = EMPTY_VALUE;
HaramiBuffer[i] = EMPTY_VALUE;
// 检查各种形态
if(ShowPinBar && IsPinBar(i, open, high, low, close))
PinBarBuffer[i] = low[i] - 10 * Point;
if(ShowEngulfing && IsEngulfing(i, open, high, low, close))
EngulfingBuffer[i] = high[i] + 10 * Point;
if(ShowHammer && IsHammer(i, open, high, low, close))
HammerBuffer[i] = low[i] - 10 * Point;
if(ShowShootingStar && IsShootingStar(i, open, high, low, close))
ShootingStarBuffer[i] = high[i] + 10 * Point;
if(ShowThreeSoldiers && IsThreeSoldiers(i, open, high, low, close))
ThreeSoldiersBuffer[i] = low[i] - 15 * Point;
if(ShowThreeCrows && IsThreeCrows(i, open, high, low, close))
ThreeCrowsBuffer[i] = high[i] + 15 * Point;
if(ShowDoji && IsDoji(i, open, high, low, close))
DojiBuffer[i] = close[i];
if(ShowHarami && IsHarami(i, open, high, low, close))
HaramiBuffer[i] = high[i] + 10 * Point;
}
return(rates_total);
}
//+------------------------------------------------------------------+
//| 判断是否为Pin Bar |
//+------------------------------------------------------------------+
bool IsPinBar(int idx, const double &open[], const double &high[], const double &low[], const double &close[])
{
double body = MathAbs(close[idx] - open[idx]);
double upperShadow = high[idx] - MathMax(open[idx], close[idx]);
double lowerShadow = MathMin(open[idx], close[idx]) - low[idx]);
double totalRange = high[idx] - low[idx];
if(totalRange == 0) return false;
// Pin Bar特征:长影线,小实体
double bodyRatio = body / totalRange;
double shadowRatio = (upperShadow > lowerShadow) ? upperShadow/totalRange : lowerShadow/totalRange;
return (bodyRatio < 0.3 && shadowRatio > 0.6);
}
//+------------------------------------------------------------------+
//| 判断是否为吞没形态 |
//+------------------------------------------------------------------+
bool IsEngulfing(int idx, const double &open[], const double &high[], const double &low[], const double &close[])
{
if(idx + 1 >= ArraySize(open)) return false;
double currentBody = close[idx] - open[idx];
double prevBody = close[idx+1] - open[idx+1];
// 看涨吞没:前一根阴线,当前阳线完全吞没前一根
if(currentBody > 0 && prevBody < 0)
{
if(close[idx] > open[idx+1] && open[idx] < close[idx+1])
return true;
}
// 看跌吞没:前一根阳线,当前阴线完全吞没前一根
else if(currentBody < 0 && prevBody > 0)
{
if(open[idx] > close[idx+1] && close[idx] < open[idx+1])
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| 判断是否为锤子线 |
//+------------------------------------------------------------------+
bool IsHammer(int idx, const double &open[], const double &high[], const double &low[], const double &close[])
{
double body = MathAbs(close[idx] - open[idx]);
double upperShadow = high[idx] - MathMax(open[idx], close[idx]);
double lowerShadow = MathMin(open[idx], close[idx]) - low[idx]);
double totalRange = high[idx] - low[idx];
if(totalRange == 0) return false;
// 锤子线特征:长下影线,短上影线,小实体
bool isSmallBody = (body / totalRange) < 0.3;
bool isLongLowerShadow = (lowerShadow / totalRange) > 0.6;
bool isShortUpperShadow = (upperShadow / totalRange) < 0.1;
return (isSmallBody && isLongLowerShadow && isShortUpperShadow);
}
//+------------------------------------------------------------------+
//| 判断是否为射击之星 |
//+------------------------------------------------------------------+
bool IsShootingStar(int idx, const double &open[], const double &high[], const double &low[], const double &close[])
{
double body = MathAbs(close[idx] - open[idx]);
double upperShadow = high[idx] - MathMax(open[idx], close[idx]);
double lowerShadow = MathMin(open[idx], close[idx]) - low[idx]);
double totalRange = high[idx] - low[idx];
if(totalRange == 0) return false;
// 射击之星特征:长上影线,短下影线,小实体
bool isSmallBody = (body / totalRange) < 0.3;
bool isLongUpperShadow = (upperShadow / totalRange) > 0.6;
bool isShortLowerShadow = (lowerShadow / totalRange) < 0.1;
return (isSmallBody && isLongUpperShadow && isShortLowerShadow);
}
//+------------------------------------------------------------------+
//| 判断是否为红三兵 |
//+------------------------------------------------------------------+
bool IsThreeSoldiers(int idx, const double &open[], const double &high[], const double &low[], const double &close[])
{
if(idx + 2 >= ArraySize(open)) return false;
// 连续三根阳线
bool threeBullish = (close[idx] > open[idx]) &&
(close[idx+1] > open[idx+1]) &&
(close[idx+2] > open[idx+2]);
if(!threeBullish) return false;
// 每根K线的收盘价都高于前一根的收盘价
bool ascendingCloses = (close[idx] > close[idx+1]) &&
(close[idx+1] > close[idx+2]);
// 每根K线都有明显的实体
bool significantBodies = (MathAbs(close[idx] - open[idx]) > MinBodySizePoints * Point) &&
(MathAbs(close[idx+1] - open[idx+1]) > MinBodySizePoints * Point) &&
(MathAbs(close[idx+2] - open[idx+2]) > MinBodySizePoints * Point);
return (ascendingCloses && significantBodies);
}
//+------------------------------------------------------------------+
//| 判断是否为三只乌鸦 |
//+------------------------------------------------------------------+
bool IsThreeCrows(int idx, const double &open[], const double &high[], const double &low[], const double &close[])
{
if(idx + 2 >= ArraySize(open)) return false;
// 连续三根阴线
bool threeBearish = (close[idx] < open[idx]) &&
(close[idx+1] < open[idx+1]) &&
(close[idx+2] < open[idx+2]);
if(!threeBearish) return false;
// 每根K线的收盘价都低于前一根的收盘价
bool descendingCloses = (close[idx] < close[idx+1]) &&
(close[idx+1] < close[idx+2]);
// 每根K线都有明显的实体
bool significantBodies = (MathAbs(close[idx] - open[idx]) > MinBodySizePoints * Point) &&
(MathAbs(close[idx+1] - open[idx+1]) > MinBodySizePoints * Point) &&
(MathAbs(close[idx+2] - open[idx+2]) > MinBodySizePoints * Point);
return (descendingCloses && significantBodies);
}
//+------------------------------------------------------------------+
//| 判断是否为十字星 |
//+------------------------------------------------------------------+
bool IsDoji(int idx, const double &open[], const double &high[], const double &low[], const double &close[])
{
double body = MathAbs(close[idx] - open[idx]);
double totalRange = high[idx] - low[idx];
if(totalRange == 0) return false;
// 十字星特征:实体非常小
return (body / totalRange < 0.1);
}
//+------------------------------------------------------------------+
//| 判断是否为孕线 |
//+------------------------------------------------------------------+
bool IsHarami(int idx, const double &open[], const double &high[], const double &low[], const double &close[])
{
if(idx + 1 >= ArraySize(open)) return false;
double currentBody = MathAbs(close[idx] - open[idx]);
double prevBody = MathAbs(close[idx+1] - open[idx+1]);
// 当前K线的实体完全包含在前一根K线的实体范围内
bool bodyContained = (MathMax(open[idx], close[idx]) < MathMax(open[idx+1], close[idx+1])) &&
(MathMin(open[idx], close[idx]) > MathMin(open[idx+1], close[idx+1]));
return (bodyContained && (currentBody < prevBody));
}
|