你好楼主能不能把这个转换成EA 一下 谢谢+------------------------------------------------------------------+
//| ChanlunPro.mq4 |
//| Copyright 2024, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "2.00"
#property strict
#property indicator_chart_window
// 输入参数
input int MaxBars = 2000; // 最大分析柱数
input int SegmentBars = 5; // 波段最小K线数
input double MinHeight = 0.0003; // 中枢最小高度(点)
input double OverlapRatio = 0.5; // 波段重叠比例(0-1)
input int FractalBars = 2; // 分型验证K线数
input color ZS1Color = clrGray; // 一级中枢颜色
input color ZS2Color = C'100,100,255'; // 二级中枢颜色
input color Buy1Color = clrLime; // 一买颜色
input color Buy2Color = clrDodgerBlue; // 二买颜色
input color Buy3Color = clrCyan; // 三买颜色
input color Sell1Color = clrRed; // 一卖颜色
input color Sell2Color = C'255,100,0'; // 二卖颜色
input color Sell3Color = clrMagenta;// 三卖颜色
input int ArrowSize = 2; // 箭头尺寸
input bool ShowLabels = true; // 显示中枢标签
// 全局变量
struct ZhongShu { double high,low; datetime start,end; int level; };
ZhongShu zsArray[]; // 中枢存储数组
int lastProcessedBar = 0; // 最后处理K线索引
//+------------------------------------------------------------------+
//| 初始化指标 |
//+------------------------------------------------------------------+
int OnInit()
{
IndicatorBuffers(0);
ArrayResize(zsArray, 100);
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[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
// 设置系列数组
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(time, true);
// 确定计算范围
int startBar = (prev_calculated == 0) ?
MathMin(rates_total-1, MaxBars-1) :
MathMin(rates_total - prev_calculated + 5, rates_total-1);
// 删除新K线范围内的旧对象
DeleteObjectsInRange(time[startBar]);
// 识别中枢和买卖点
for(int i = startBar; i >= SegmentBars*3+1; i--)
{
ZhongShu newZS;
if(FindZhongshu(i, high, low, time, newZS))
{
// 检查是否新中枢
bool isNew = true;
for(int j = 0; j < ArraySize(zsArray); j++)
{
if(zsArray[j].start == newZS.start &&
zsArray[j].end == newZS.end)
{
isNew = false;
break;
}
}
if(isNew)
{
// 保存中枢并绘制
SaveAndDrawZS(newZS, time);
}
}
// 识别买卖点
IdentifyPoints(i, high, low, close, time);
}
lastProcessedBar = rates_total - 1;
return(rates_total);
}
//+------------------------------------------------------------------+
//| 删除指定时间后的对象 |
//+------------------------------------------------------------------+
void DeleteObjectsInRange(datetime afterTime)
{
for(int i = ObjectsTotal()-1; i >= 0; i--)
{
string name = ObjectName(i);
datetime objTime = (datetime)ObjectGetInteger(0, name, OBJPROP_TIME);
if(StringFind(name, "ZS_") == 0 ||
StringFind(name, "B") == 0 ||
StringFind(name, "S") == 0)
{
if(objTime >= afterTime) ObjectDelete(name);
}
}
}
//+------------------------------------------------------------------+
//| 识别中枢(增强版) |
//+------------------------------------------------------------------+
bool FindZhongshu(int startIdx, const double &high[], const double &low[],
const datetime &time[], ZhongShu &outZS)
{
// 查找三个波段
int peaks[6];
peaks[0] = FindPeak(startIdx, MODE_HIGH, SegmentBars, high, low); // 第一段高点
peaks[1] = FindPeak(peaks[0], MODE_LOW, SegmentBars, high, low); // 第一段低点
peaks[2] = FindPeak(peaks[1], MODE_HIGH, SegmentBars, high, low); // 第二段高点
peaks[3] = FindPeak(peaks[2], MODE_LOW, SegmentBars, high, low); // 第二段低点
peaks[4] = FindPeak(peaks[3], MODE_HIGH, SegmentBars, high, low); // 第三段高点
peaks[5] = FindPeak(peaks[4], MODE_LOW, SegmentBars, high, low); // 第三段低点
// 验证所有极点有效
for(int i = 0; i < 6; i++)
if(peaks[i] < 0) return false;
// 计算波段区间
double segHigh[3], segLow[3];
segHigh[0] = HighMax(peaks[0], peaks[1], high);
segLow[0] = LowMin(peaks[0], peaks[1], low);
segHigh[1] = HighMax(peaks[2], peaks[3], high);
segLow[1] = LowMin(peaks[2], peaks[3], low);
segHigh[2] = HighMax(peaks[4], peaks[5], high);
segLow[2] = LowMin(peaks[4], peaks[5], low);
// 计算中枢区间
double zsHigh = MathMin(segHigh[0], MathMin(segHigh[1], segHigh[2]));
double zsLow = MathMax(segLow[0], MathMax(segLow[1], segLow[2]));
// 验证中枢有效性
if(zsHigh <= zsLow) return false;
if((zsHigh - zsLow) < MinHeight * Point) return false;
// 验证重叠比例
double overlap1 = (MathMin(segHigh[0], segHigh[1]) - MathMax(segLow[0], segLow[1]));
double overlap2 = (MathMin(segHigh[1], segHigh[2]) - MathMax(segLow[1], segLow[2]));
double minRange = MathMin(zsHigh - zsLow, MathMin(segHigh[0]-segLow[0], segHigh[1]-segLow[1]));
if(overlap1/minRange < OverlapRatio || overlap2/minRange < OverlapRatio)
return false;
// 确定中枢级别(基于持续时间)
int duration = (int)((time[peaks[0]] - time[peaks[5]]) / PeriodSeconds());
outZS.level = (duration > SegmentBars*20) ? 2 : 1;
outZS.high = zsHigh;
outZS.low = zsLow;
outZS.start = time[peaks[5]];
outZS.end = time[peaks[0]];
return true;
}
//+------------------------------------------------------------------+
//| 保存并绘制中枢 |
//+------------------------------------------------------------------+
void SaveAndDrawZS(ZhongShu &zs, const datetime &time[])
{
// 保存到数组
int size = ArraySize(zsArray);
for(int i = 0; i < size; i++)
{
if(zsArray[i].start == 0)
{
zsArray[i] = zs;
break;
}
}
// 绘制中枢
string zsName = "ZS_" + IntegerToString(zs.start) + "_" + IntegerToString(zs.end);
color zsColor = (zs.level == 1) ? ZS1Color : ZS2Color;
ObjectCreate(0, zsName, OBJ_RECTANGLE, 0, zs.start, zs.low, zs.end, zs.high);
ObjectSetInteger(0, zsName, OBJPROP_COLOR, zsColor);
ObjectSetInteger(0, zsName, OBJPROP_BACK, true);
ObjectSetInteger(0, zsName, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, zsName, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, zsName, OBJPROP_FILL, true);
ObjectSetInteger(0, zsName, OBJPROP_SELECTABLE, false);
// 添加中枢标签
if(ShowLabels)
{
string labelName = "LBL_" + zsName;
string text = StringFormat("ZS#%d\n%.5f-%.5f", zs.level, zs.low, zs.high);
datetime labelTime = zs.start + (zs.end - zs.start)/2;
double labelPrice = (zs.low + zs.high)/2;
ObjectCreate(0, labelName, OBJ_TEXT, 0, labelTime, labelPrice);
ObjectSetString(0, labelName, OBJPROP_TEXT, text);
ObjectSetInteger(0, labelName, OBJPROP_COLOR, clrWhite);
ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 8);
ObjectSetInteger(0, labelName, OBJPROP_BACK, true);
}
}
//+------------------------------------------------------------------+
//| 识别全系列买卖点 |
//+------------------------------------------------------------------+
void IdentifyPoints(int idx, const double &high[], const double &low[],
const double &close[], const datetime &time[])
{
// 查找有效中枢
for(int i = 0; i < ArraySize(zsArray); i++)
{
if(zsArray[i].start == 0) continue;
double zsHigh = zsArray[i].high;
double zsLow = zsArray[i].low;
datetime zsEnd = zsArray[i].end;
// 忽略未完成中枢
if(time[idx] < zsEnd) continue;
// 1. 一买点:中枢下方底分型
if(close[idx] < zsLow && IsBottomFractal(idx, low, FractalBars))
{
string name = "B1_" + IntegerToString(idx);
CreateArrow(name, time[idx], low[idx]-10*Point, Buy1Color, SYMBOL_ARROWUP);
}
// 2. 一卖点:中枢上方顶分型
if(close[idx] > zsHigh && IsTopFractal(idx, high, FractalBars))
{
string name = "S1_" + IntegerToString(idx);
CreateArrow(name, time[idx], high[idx]+10*Point, Sell1Color, SYMBOL_ARROWDOWN);
}
// 3. 二买点:回调不破前低
if(close[idx] > zsLow && close[idx] < zsHigh &&
IsBottomFractal(idx, low, FractalBars) &&
IsHigherLow(idx, 10, low)) // 10周期内低点抬高
{
string name = "B2_" + IntegerToString(idx);
CreateArrow(name, time[idx], low[idx]-10*Point, Buy2Color, SYMBOL_ARROWUP);
}
// 4. 二卖点:反弹不破前高
if(close[idx] < zsHigh && close[idx] > zsLow &&
IsTopFractal(idx, high, FractalBars) &&
IsLowerHigh(idx, 10, high)) // 10周期内高点降低
{
string name = "S2_" + IntegerToString(idx);
CreateArrow(name, time[idx], high[idx]+10*Point, Sell2Color, SYMBOL_ARROWDOWN);
}
// 5. 三买点:突破后回踩不破中枢
if(close[idx] > zsHigh &&
IsPullbackToZS(idx, 10, zsHigh, low) && // 回踩中枢上方
IsBottomFractal(idx, low, FractalBars))
{
string name = "B3_" + IntegerToString(idx);
CreateArrow(name, time[idx], low[idx]-10*Point, Buy3Color, SYMBOL_ARROWUP);
}
// 6. 三卖点:跌破后回抽不破中枢
if(close[idx] < zsLow &&
IsPullbackToZS(idx, 10, zsLow, high) && // 回抽中枢下方
IsTopFractal(idx, high, FractalBars))
{
string name = "S3_" + IntegerToString(idx);
CreateArrow(name, time[idx], high[idx]+10*Point, Sell3Color, SYMBOL_ARROWDOWN);
}
}
}
//+------------------------------------------------------------------+
//| 创建箭头对象 |
//+------------------------------------------------------------------+
void CreateArrow(string name, datetime time, double price, color clr, int code)
{
ObjectCreate(0, name, OBJ_ARROW, 0, time, price);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_ARROWCODE, code);
ObjectSetInteger(0, name, OBJPROP_WIDTH, ArrowSize);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
}
//+------------------------------------------------------------------+
//| 辅助函数: 查找波段极点 |
//+------------------------------------------------------------------+
int FindPeak(int startIdx, int mode, int minBars, const double &high[], const double &low[])
{
int peakIdx = startIdx;
int endIdx = MathMax(startIdx - minBars, 0);
for(int i = startIdx; i >= endIdx; i--)
{
if(mode == MODE_HIGH)
{
if(high[i] > high[peakIdx]) peakIdx = i;
}
else
{
if(low[i] < low[peakIdx]) peakIdx = i;
}
}
return peakIdx;
}
//+------------------------------------------------------------------+
//| 辅助函数: 计算区间最高价 |
//+------------------------------------------------------------------+
double HighMax(int start, int end, const double &high[])
{
double val = high[start];
int step = (start < end) ? 1 : -1;
for(int i = start; i != end; i += step)
if(high[i] > val) val = high[i];
return val;
}
//+------------------------------------------------------------------+
//| 辅助函数: 计算区间最低价 |
//+------------------------------------------------------------------+
double LowMin(int start, int end, const double &low[])
{
double val = low[start];
int step = (start < end) ? 1 : -1;
for(int i = start; i != end; i += step)
if(low[i] < val) val = low[i];
return val;
}
//+------------------------------------------------------------------+
//| 判断底分型(增强版) |
//+------------------------------------------------------------------+
bool IsBottomFractal(int idx, const double &low[], int verifyBars)
{
// 中心点必须是低点
if(low[idx] > low[idx-1] || low[idx] > low[idx+1])
return false;
// 左侧验证
for(int i = 1; i <= verifyBars; i++)
{
if(low[idx-i] < low[idx] || low[idx+i] < low[idx])
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| 判断顶分型(增强版) |
//+------------------------------------------------------------------+
bool IsTopFractal(int idx, const double &high[], int verifyBars)
{
// 中心点必须是高点
if(high[idx] < high[idx-1] || high[idx] < high[idx+1])
return false;
// 左侧验证
for(int i = 1; i <= verifyBars; i++)
{
if(high[idx-i] > high[idx] || high[idx+i] > high[idx])
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| 判断低点是否抬高 |
//+------------------------------------------------------------------+
bool IsHigherLow(int idx, int period, const double &low[])
{
double currentLow = low[idx];
for(int i = 1; i <= period; i++)
{
if(low[idx+i] < currentLow) return false;
if(low[idx-i] < currentLow) return false;
}
return true;
}
//+------------------------------------------------------------------+
//| 判断高点是否降低 |
//+------------------------------------------------------------------+
bool IsLowerHigh(int idx, int period, const double &high[])
{
double currentHigh = high[idx];
for(int i = 1; i <= period; i++)
{
if(high[idx+i] > currentHigh) return false;
if(high[idx-i] > currentHigh) return false;
}
return true;
}
//+------------------------------------------------------------------+
//| 判断回踩中枢支撑 |
//+------------------------------------------------------------------+
bool IsPullbackToZS(int idx, int period, double zsLevel, const double &price[])
{
for(int i = 0; i < period; i++)
{
if(price[idx-i] <= zsLevel) return true;
}
return false;
}
//+------------------------------------------------------------------+ |