#property description "和谐形态交易策略 - Harmonic Patterns (Gartley, Butterfly, Crab, Bat, Cypher)"
//注意,不同的品种,一手的数量和止损要根据情况进行调整,外汇杠杆高,手数要小,股票杠杆低,可以稍大,波动止盈止损也可以根据情况调整,否则会出现成交不了的情况。
- //--- 包含标准交易库
- #include <Trade\Trade.mqh>
-
- //--- 输入参数
- input group "=== 和谐形态识别设置 ==="
- input bool EnableGartley = true; // 启用Gartley形态
- input bool EnableButterfly = true; // 启用Butterfly形态
- input bool EnableCrab = true; // 启用Crab形态
- input bool EnableBat = true; // 启用Bat形态
- input bool EnableCypher = true; // 启用Cypher形态
- input int PatternLookback = 100; // 形态识别回看周期
- input double FibTolerance = 0.05; // 斐波那契比例容差 (5%)
-
- input group "=== 斐波那契比例设置 ==="
- input double Fib236 = 0.236; // 23.6%回撤
- input double Fib382 = 0.382; // 38.2%回撤
- input double Fib500 = 0.500; // 50%回撤
- input double Fib618 = 0.618; // 61.8%回撤
- input double Fib786 = 0.786; // 78.6%回撤
- input double Fib886 = 0.886; // 88.6%回撤
- input double Fib1272 = 1.272; // 127.2%扩展
- input double Fib1618 = 1.618; // 161.8%扩展
-
- input group "=== 形态验证设置 ==="
- input bool RequirePRZConfirmation = true; // 需要潜在反转区确认
- input double PRZWidthPercent = 2.0; // PRZ宽度百分比
- input bool RequireRSIDivergence = true; // 需要RSI背离确认
- input int RSIPeriod = 14; // RSI周期
- input bool RequireVolumeSpike = true; // 需要成交量放量确认
- input double VolumeMultiplier = 1.5; // 成交量倍数
-
- input group "=== 交易管理设置 ==="
- input double RiskRewardRatio = 2.0; // 风险收益比
- input bool UsePatternStops = true; // 使用形态止损
- input bool UseFibTargets = true; // 使用斐波那契目标
- input int MaxConcurrentTrades = 3; // 最大同时交易数
- input bool TradeOnlyPerfectPatterns = false; // 只交易完美形态
-
- input group "=== 风险管理 ==="
- input double RiskPercent = 1.5; // 风险百分比
- input double InpLotSize = 1.0; // 交易手数
- input double MaxStopLossPips = 100.0; // 最大止损点数
- input double MinRiskReward = 1.5; // 最小风险收益比
- input bool UseTrailingStop = true; // 使用跟踪止损
- input double TrailingStopPips = 40.0; // 跟踪止损点数
-
- input group "=== 其他设置 ==="
- input int InpMagicNumber = 20250819; // 魔术号码
- input string TradeComment = "HarmonicEA"; // 交易注释
- input bool ShowPatterns = true; // 显示形态
- input bool ShowFibLevels = true; // 显示斐波那契水平
- input color PatternColor = clrLimeGreen; // 形态颜色
- input color FibColor = clrGold; // 斐波那契颜色
-
- //--- 形态结构
- enum ENUM_PATTERN_TYPE {
- PATTERN_GARTLEY = 0,
- PATTERN_BUTTERFLY = 1,
- PATTERN_CRAB = 2,
- PATTERN_BAT = 3,
- PATTERN_CYPHER = 4
- };
-
- struct SHarmonicPattern {
- ENUM_PATTERN_TYPE pattern_type;
- bool is_bullish;
- datetime formation_time;
- double X, A, B, C, D; // 5个关键点
- int X_bar, A_bar, B_bar, C_bar, D_bar; // 对应K线索引
- double XA, AB, BC, CD; // 波段距离
- double AB_XA_ratio, BC_AB_ratio, CD_BC_ratio, AD_XA_ratio; // 斐波那契比例
- double prz_low, prz_high; // 潜在反转区
- double entry_price; // 入场价格
- double stop_loss; // 止损价格
- double take_profit1, take_profit2, take_profit3; // 三个止盈目标
- bool is_valid; // 形态有效性
- double pattern_quality; // 形态质量评分
- };
-
- //--- 全局变量
- SHarmonicPattern g_current_patterns[20];
- int g_pattern_count = 0;
-
- double g_swing_highs[200];
- double g_swing_lows[200];
- int g_swing_high_bars[200];
- int g_swing_low_bars[200];
- int g_high_count = 0, g_low_count = 0;
-
- int g_rsi_handle = INVALID_HANDLE;
- double g_rsi_buffer[];
-
- //--- 交易对象
- CTrade g_trade;
-
- //+------------------------------------------------------------------+
- //| 专家初始化函数 |
- //+------------------------------------------------------------------+
- int OnInit()
- {
- Print("和谐形态策略 EA 启动");
-
- // 初始化交易库
- g_trade.SetExpertMagicNumber(InpMagicNumber);
- g_trade.SetMarginMode();
- g_trade.SetTypeFillingBySymbol(_Symbol);
- g_trade.SetDeviationInPoints(10);
-
- // 初始化RSI指标
- g_rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, RSIPeriod, PRICE_CLOSE);
- if(g_rsi_handle == INVALID_HANDLE) {
- Print("RSI指标初始化失败");
- return INIT_FAILED;
- }
-
- ArraySetAsSeries(g_rsi_buffer, true);
-
- // 初始化摆动点数据
- if(!FindSwingPoints()) {
- Print("摆动点初始化失败");
- return INIT_FAILED;
- }
-
- return INIT_SUCCEEDED;
- }
-
- //+------------------------------------------------------------------+
- //| 寻找摆动高低点 |
- //+------------------------------------------------------------------+
- bool FindSwingPoints()
- {
- int swing_period = 5; // 摆动点识别周期
- g_high_count = 0;
- g_low_count = 0;
-
- for(int i = swing_period; i < PatternLookback - swing_period; i++) {
- double high = iHigh(_Symbol, PERIOD_CURRENT, i);
- double low = iLow(_Symbol, PERIOD_CURRENT, i);
-
- // 识别摆动高点
- bool is_swing_high = true;
- for(int j = 1; j <= swing_period; j++) {
- if(iHigh(_Symbol, PERIOD_CURRENT, i - j) >= high ||
- iHigh(_Symbol, PERIOD_CURRENT, i + j) >= high) {
- is_swing_high = false;
- break;
- }
- }
-
- if(is_swing_high && g_high_count < 200) {
- g_swing_highs[g_high_count] = high;
- g_swing_high_bars[g_high_count] = i;
- g_high_count++;
- }
-
- // 识别摆动低点
- bool is_swing_low = true;
- for(int j = 1; j <= swing_period; j++) {
- if(iLow(_Symbol, PERIOD_CURRENT, i - j) <= low ||
- iLow(_Symbol, PERIOD_CURRENT, i + j) <= low) {
- is_swing_low = false;
- break;
- }
- }
-
- if(is_swing_low && g_low_count < 200) {
- g_swing_lows[g_low_count] = low;
- g_swing_low_bars[g_low_count] = i;
- g_low_count++;
- }
- }
-
- Print("找到摆动高点: ", g_high_count, ", 摆动低点: ", g_low_count);
- return (g_high_count >= 5 && g_low_count >= 5);
- }
-
- //+------------------------------------------------------------------+
- //| 专家tick函数 |
- //+------------------------------------------------------------------+
- void OnTick()
- {
- // 更新技术指标
- if(CopyBuffer(g_rsi_handle, 0, 0, 50, g_rsi_buffer) < 50) return;
-
- // 重新扫描摆动点
- static datetime last_scan_time = 0;
- if(TimeCurrent() - last_scan_time > 3600) { // 每小时扫描一次
- FindSwingPoints();
- last_scan_time = TimeCurrent();
- }
-
- // 识别和谐形态
- ScanForHarmonicPatterns();
-
- // 检查交易信号
- CheckHarmonicSignals();
-
- // 管理现有持仓
- ManagePositions();
-
- // 更新图形显示
- if(ShowPatterns || ShowFibLevels) {
- UpdateChartObjects();
- }
- }
-
- //+------------------------------------------------------------------+
- //| 扫描和谐形态 |
- //+------------------------------------------------------------------+
- void ScanForHarmonicPatterns()
- {
- g_pattern_count = 0;
-
- // 扫描看涨形态
- if(g_low_count >= 3 && g_high_count >= 2) {
- ScanBullishPatterns();
- }
-
- // 扫描看跌形态
- if(g_high_count >= 3 && g_low_count >= 2) {
- ScanBearishPatterns();
- }
-
- // 验证和评分形态
- for(int i = 0; i < g_pattern_count; i++) {
- ValidatePattern(g_current_patterns);
- }
- }
-
- //+------------------------------------------------------------------+
- //| 扫描看涨形态 |
- //+------------------------------------------------------------------+
- void ScanBullishPatterns()
- {
- // 寻找 X-A-B-C-D 结构 (低-高-低-高-低)
- for(int x = 0; x < g_low_count - 2; x++) {
- for(int a = 0; a < g_high_count - 1; a++) {
- if(g_swing_high_bars[a] <= g_swing_low_bars[x]) continue;
-
- for(int b = x + 1; b < g_low_count - 1; b++) {
- if(g_swing_low_bars <= g_swing_high_bars[a]) continue;
-
- for(int c = a + 1; c < g_high_count; c++) {
- if(g_swing_high_bars[c] <= g_swing_low_bars) continue;
-
- for(int d = b + 1; d < g_low_count; d++) {
- if(g_swing_low_bars[d] <= g_swing_high_bars[c]) continue;
- if(g_swing_low_bars[d] < 10) continue; // 太接近当前价格
-
- // 构建潜在形态
- SHarmonicPattern pattern = {};
- pattern.is_bullish = true;
- pattern.X = g_swing_lows[x];
- pattern.A = g_swing_highs[a];
- pattern.B = g_swing_lows;
- pattern.C = g_swing_highs[c];
- pattern.D = g_swing_lows[d];
- pattern.X_bar = g_swing_low_bars[x];
- pattern.A_bar = g_swing_high_bars[a];
- pattern.B_bar = g_swing_low_bars;
- pattern.C_bar = g_swing_high_bars[c];
- pattern.D_bar = g_swing_low_bars[d];
-
- // 计算比例
- CalculatePatternRatios(pattern);
-
- // 识别形态类型
- if(IdentifyPatternType(pattern) && g_pattern_count < 20) {
- g_current_patterns[g_pattern_count] = pattern;
- g_pattern_count++;
- }
- }
- }
- }
- }
- }
- }
-
- //+------------------------------------------------------------------+
- //| 扫描看跌形态 |
- //+------------------------------------------------------------------+
- void ScanBearishPatterns()
- {
- // 寻找 X-A-B-C-D 结构 (高-低-高-低-高)
- for(int x = 0; x < g_high_count - 2; x++) {
- for(int a = 0; a < g_low_count - 1; a++) {
- if(g_swing_low_bars[a] <= g_swing_high_bars[x]) continue;
-
- for(int b = x + 1; b < g_high_count - 1; b++) {
- if(g_swing_high_bars <= g_swing_low_bars[a]) continue;
-
- for(int c = a + 1; c < g_low_count; c++) {
- if(g_swing_low_bars[c] <= g_swing_high_bars) continue;
-
- for(int d = b + 1; d < g_high_count; d++) {
- if(g_swing_high_bars[d] <= g_swing_low_bars[c]) continue;
- if(g_swing_high_bars[d] < 10) continue; // 太接近当前价格
-
- // 构建潜在形态
- SHarmonicPattern pattern = {};
- pattern.is_bullish = false;
- pattern.X = g_swing_highs[x];
- pattern.A = g_swing_lows[a];
- pattern.B = g_swing_highs;
- pattern.C = g_swing_lows[c];
- pattern.D = g_swing_highs[d];
- pattern.X_bar = g_swing_high_bars[x];
- pattern.A_bar = g_swing_low_bars[a];
- pattern.B_bar = g_swing_high_bars;
- pattern.C_bar = g_swing_low_bars[c];
- pattern.D_bar = g_swing_high_bars[d];
-
- // 计算比例
- CalculatePatternRatios(pattern);
-
- // 识别形态类型
- if(IdentifyPatternType(pattern) && g_pattern_count < 20) {
- g_current_patterns[g_pattern_count] = pattern;
- g_pattern_count++;
- }
- }
- }
- }
- }
- }
- }
-
- //+------------------------------------------------------------------+
- //| 计算形态比例 |
- //+------------------------------------------------------------------+
- void CalculatePatternRatios(SHarmonicPattern &pattern)
- {
- pattern.XA = MathAbs(pattern.A - pattern.X);
- pattern.AB = MathAbs(pattern.B - pattern.A);
- pattern.BC = MathAbs(pattern.C - pattern.B);
- pattern.CD = MathAbs(pattern.D - pattern.C);
-
- if(pattern.XA > 0) {
- pattern.AB_XA_ratio = pattern.AB / pattern.XA;
- pattern.AD_XA_ratio = MathAbs(pattern.D - pattern.A) / pattern.XA;
- }
-
- if(pattern.AB > 0) {
- pattern.BC_AB_ratio = pattern.BC / pattern.AB;
- }
-
- if(pattern.BC > 0) {
- pattern.CD_BC_ratio = pattern.CD / pattern.BC;
- }
- }
-
- //+------------------------------------------------------------------+
- //| 识别形态类型 |
- //+------------------------------------------------------------------+
- bool IdentifyPatternType(SHarmonicPattern &pattern)
- {
- double tolerance = FibTolerance;
-
- // Gartley形态 (AB=61.8%XA, BC=38.2%-88.6%AB, CD=127.2%BC, AD=78.6%XA)
- if(EnableGartley && CheckRatio(pattern.AB_XA_ratio, Fib618, tolerance) &&
- CheckRatio(pattern.BC_AB_ratio, 0.382, tolerance, 0.886) &&
- CheckRatio(pattern.CD_BC_ratio, Fib1272, tolerance) &&
- CheckRatio(pattern.AD_XA_ratio, Fib786, tolerance)) {
- pattern.pattern_type = PATTERN_GARTLEY;
- return true;
- }
-
- // Butterfly形态 (AB=78.6%XA, BC=38.2%-88.6%AB, CD=161.8%BC, AD=127.2%-161.8%XA)
- if(EnableButterfly && CheckRatio(pattern.AB_XA_ratio, Fib786, tolerance) &&
- CheckRatio(pattern.BC_AB_ratio, 0.382, tolerance, 0.886) &&
- CheckRatio(pattern.CD_BC_ratio, Fib1618, tolerance) &&
- CheckRatio(pattern.AD_XA_ratio, 1.272, tolerance, 1.618)) {
- pattern.pattern_type = PATTERN_BUTTERFLY;
- return true;
- }
-
- // Crab形态 (AB=38.2%-61.8%XA, BC=38.2%-88.6%AB, CD=224%-361.8%BC, AD=161.8%XA)
- if(EnableCrab && CheckRatio(pattern.AB_XA_ratio, 0.382, tolerance, 0.618) &&
- CheckRatio(pattern.BC_AB_ratio, 0.382, tolerance, 0.886) &&
- CheckRatio(pattern.CD_BC_ratio, 2.24, tolerance, 3.618) &&
- CheckRatio(pattern.AD_XA_ratio, Fib1618, tolerance)) {
- pattern.pattern_type = PATTERN_CRAB;
- return true;
- }
-
- // Bat形态 (AB=38.2%-50%XA, BC=38.2%-88.6%AB, CD=162%-267%BC, AD=88.6%XA)
- if(EnableBat && CheckRatio(pattern.AB_XA_ratio, 0.382, tolerance, 0.50) &&
- CheckRatio(pattern.BC_AB_ratio, 0.382, tolerance, 0.886) &&
- CheckRatio(pattern.CD_BC_ratio, 1.62, tolerance, 2.67) &&
- CheckRatio(pattern.AD_XA_ratio, Fib886, tolerance)) {
- pattern.pattern_type = PATTERN_BAT;
- return true;
- }
-
- // Cypher形态 (AB=38.2%-61.8%XA, BC=113%-141.4%AB, CD=78.6%BC, AD=78.6%XA)
- if(EnableCypher && CheckRatio(pattern.AB_XA_ratio, 0.382, tolerance, 0.618) &&
- CheckRatio(pattern.BC_AB_ratio, 1.13, tolerance, 1.414) &&
- CheckRatio(pattern.CD_BC_ratio, Fib786, tolerance) &&
- CheckRatio(pattern.AD_XA_ratio, Fib786, tolerance)) {
- pattern.pattern_type = PATTERN_CYPHER;
- return true;
- }
-
- return false;
- }
-
- //+------------------------------------------------------------------+
- //| 检查比例 |
- //+------------------------------------------------------------------+
- bool CheckRatio(double actual_ratio, double target_ratio, double tolerance, double max_ratio = 0)
- {
- double lower_bound = target_ratio * (1.0 - tolerance);
- double upper_bound = (max_ratio > 0) ? max_ratio * (1.0 + tolerance) : target_ratio * (1.0 + tolerance);
-
- return (actual_ratio >= lower_bound && actual_ratio <= upper_bound);
- }
-
- //+------------------------------------------------------------------+
- //| 验证形态 |
- //+------------------------------------------------------------------+
- void ValidatePattern(SHarmonicPattern &pattern)
- {
- pattern.is_valid = false;
- pattern.pattern_quality = 0.0;
-
- // 计算潜在反转区 (PRZ)
- CalculatePRZ(pattern);
-
- // 基础有效性检查
- if(!BasicPatternValidation(pattern)) return;
-
- // 形态质量评分
- double quality_score = 0.0;
-
- // 比例精确度评分 (40%)
- quality_score += CalculateRatioAccuracy(pattern) * 0.4;
-
- // PRZ聚合度评分 (30%)
- quality_score += CalculatePRZQuality(pattern) * 0.3;
-
- // 技术指标确认评分 (20%)
- quality_score += CalculateIndicatorConfirmation(pattern) * 0.2;
-
- // 成交量确认评分 (10%)
- quality_score += CalculateVolumeConfirmation(pattern) * 0.1;
-
- pattern.pattern_quality = quality_score;
-
- // 设置质量阈值
- double min_quality = TradeOnlyPerfectPatterns ? 0.8 : 0.6;
- pattern.is_valid = (quality_score >= min_quality);
-
- if(pattern.is_valid) {
- CalculateTradeParameters(pattern);
- }
- }
-
- //+------------------------------------------------------------------+
- //| 计算潜在反转区 |
- //+------------------------------------------------------------------+
- void CalculatePRZ(SHarmonicPattern &pattern)
- {
- double prz_width = MathAbs(pattern.A - pattern.X) * PRZWidthPercent / 100.0;
-
- if(pattern.is_bullish) {
- pattern.prz_low = pattern.D - prz_width / 2;
- pattern.prz_high = pattern.D + prz_width / 2;
- } else {
- pattern.prz_low = pattern.D - prz_width / 2;
- pattern.prz_high = pattern.D + prz_width / 2;
- }
- }
-
- //+------------------------------------------------------------------+
- //| 基础形态验证 |
- //+------------------------------------------------------------------+
- bool BasicPatternValidation(const SHarmonicPattern &pattern)
- {
- // 时间序列检查
- if(pattern.X_bar <= pattern.A_bar || pattern.A_bar <= pattern.B_bar ||
- pattern.B_bar <= pattern.C_bar || pattern.C_bar <= pattern.D_bar) {
- return false;
- }
-
- // 价格结构检查
- if(pattern.is_bullish) {
- if(pattern.X >= pattern.A || pattern.B >= pattern.A ||
- pattern.C <= pattern.B || pattern.D >= pattern.C) {
- return false;
- }
- } else {
- if(pattern.X <= pattern.A || pattern.B <= pattern.A ||
- pattern.C >= pattern.B || pattern.D <= pattern.C) {
- return false;
- }
- }
-
- return true;
- }
-
- //+------------------------------------------------------------------+
- //| 计算比例精确度 |
- //+------------------------------------------------------------------+
- double CalculateRatioAccuracy(const SHarmonicPattern &pattern)
- {
- double total_accuracy = 0.0;
- int ratio_count = 0;
-
- // 根据形态类型计算各比例的精确度
- switch(pattern.pattern_type) {
- case PATTERN_GARTLEY:
- total_accuracy += 1.0 - MathAbs(pattern.AB_XA_ratio - Fib618) / Fib618;
- total_accuracy += 1.0 - MathAbs(pattern.AD_XA_ratio - Fib786) / Fib786;
- ratio_count = 2;
- break;
- case PATTERN_BUTTERFLY:
- total_accuracy += 1.0 - MathAbs(pattern.AB_XA_ratio - Fib786) / Fib786;
- total_accuracy += 1.0 - MathAbs(pattern.CD_BC_ratio - Fib1618) / Fib1618;
- ratio_count = 2;
- break;
- case PATTERN_CRAB:
- total_accuracy += 1.0 - MathAbs(pattern.AD_XA_ratio - Fib1618) / Fib1618;
- ratio_count = 1;
- break;
- case PATTERN_BAT:
- total_accuracy += 1.0 - MathAbs(pattern.AD_XA_ratio - Fib886) / Fib886;
- ratio_count = 1;
- break;
- case PATTERN_CYPHER:
- total_accuracy += 1.0 - MathAbs(pattern.AD_XA_ratio - Fib786) / Fib786;
- ratio_count = 1;
- break;
- }
-
- return ratio_count > 0 ? MathMax(0.0, total_accuracy / ratio_count) : 0.0;
- }
-
- //+------------------------------------------------------------------+
- //| 计算PRZ质量 |
- //+------------------------------------------------------------------+
- double CalculatePRZQuality(const SHarmonicPattern &pattern)
- {
- double current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
- double prz_center = (pattern.prz_high + pattern.prz_low) / 2.0;
- double distance_to_prz = MathAbs(current_price - prz_center);
- double prz_width = pattern.prz_high - pattern.prz_low;
-
- // 价格越接近PRZ中心,质量评分越高
- return MathMax(0.0, 1.0 - (distance_to_prz / prz_width));
- }
-
- //+------------------------------------------------------------------+
- //| 计算指标确认 |
- //+------------------------------------------------------------------+
- double CalculateIndicatorConfirmation(const SHarmonicPattern &pattern)
- {
- double confirmation = 0.0;
-
- if(RequireRSIDivergence && ArraySize(g_rsi_buffer) > pattern.D_bar + 5) {
- // 检查RSI背离
- double rsi_at_d = g_rsi_buffer[pattern.D_bar];
- double rsi_current = g_rsi_buffer[0];
-
- if(pattern.is_bullish) {
- // 看涨背离:价格创新低,RSI不创新低
- if(pattern.D < pattern.B && rsi_at_d > g_rsi_buffer[pattern.B_bar]) {
- confirmation += 0.5;
- }
- // RSI超卖确认
- if(rsi_current < 30) {
- confirmation += 0.3;
- }
- } else {
- // 看跌背离:价格创新高,RSI不创新高
- if(pattern.D > pattern.B && rsi_at_d < g_rsi_buffer[pattern.B_bar]) {
- confirmation += 0.5;
- }
- // RSI超买确认
- if(rsi_current > 70) {
- confirmation += 0.3;
- }
- }
- }
-
- return MathMin(1.0, confirmation);
- }
-
- //+------------------------------------------------------------------+
- //| 计算成交量确认 |
- //+------------------------------------------------------------------+
- double CalculateVolumeConfirmation(const SHarmonicPattern &pattern)
- {
- if(!RequireVolumeSpike) return 1.0;
-
- long volume_at_d = iVolume(_Symbol, PERIOD_CURRENT, pattern.D_bar);
- long avg_volume = 0;
-
- for(int i = pattern.D_bar + 1; i <= pattern.D_bar + 20; i++) {
- avg_volume += iVolume(_Symbol, PERIOD_CURRENT, i);
- }
- avg_volume /= 20;
-
- if(avg_volume > 0) {
- double volume_ratio = (double)volume_at_d / avg_volume;
- return MathMin(1.0, volume_ratio / VolumeMultiplier);
- }
-
- return 0.5;
- }
-
- //+------------------------------------------------------------------+
- //| 计算交易参数 |
- //+------------------------------------------------------------------+
- void CalculateTradeParameters(SHarmonicPattern &pattern)
- {
- pattern.entry_price = pattern.D;
-
- // 计算止损
- if(UsePatternStops) {
- double pattern_range = MathAbs(pattern.A - pattern.X);
- double stop_distance = pattern_range * 0.1; // 10%的形态范围
-
- if(pattern.is_bullish) {
- pattern.stop_loss = pattern.D - stop_distance;
- } else {
- pattern.stop_loss = pattern.D + stop_distance;
- }
- } else {
- double stop_distance = MaxStopLossPips * Point();
- if(pattern.is_bullish) {
- pattern.stop_loss = pattern.D - stop_distance;
- } else {
- pattern.stop_loss = pattern.D + stop_distance;
- }
- }
-
- // 计算止盈目标
- if(UseFibTargets) {
- double cd_range = MathAbs(pattern.D - pattern.C);
-
- if(pattern.is_bullish) {
- pattern.take_profit1 = pattern.D + cd_range * Fib382;
- pattern.take_profit2 = pattern.D + cd_range * Fib618;
- pattern.take_profit3 = pattern.D + cd_range * Fib786;
- } else {
- pattern.take_profit1 = pattern.D - cd_range * Fib382;
- pattern.take_profit2 = pattern.D - cd_range * Fib618;
- pattern.take_profit3 = pattern.D - cd_range * Fib786;
- }
- } else {
- double stop_distance = MathAbs(pattern.entry_price - pattern.stop_loss);
-
- if(pattern.is_bullish) {
- pattern.take_profit1 = pattern.entry_price + stop_distance * RiskRewardRatio;
- pattern.take_profit2 = pattern.entry_price + stop_distance * RiskRewardRatio * 1.5;
- pattern.take_profit3 = pattern.entry_price + stop_distance * RiskRewardRatio * 2.0;
- } else {
- pattern.take_profit1 = pattern.entry_price - stop_distance * RiskRewardRatio;
- pattern.take_profit2 = pattern.entry_price - stop_distance * RiskRewardRatio * 1.5;
- pattern.take_profit3 = pattern.entry_price - stop_distance * RiskRewardRatio * 2.0;
- }
- }
- }
-
- //+------------------------------------------------------------------+
- //| 检查和谐信号 |
- //+------------------------------------------------------------------+
- void CheckHarmonicSignals()
- {
- double current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
-
- for(int i = 0; i < g_pattern_count; i++) {
- if(!g_current_patterns.is_valid) continue;
- if(g_current_patterns.D_bar > 5) continue; // 只交易最新的形态
-
- // 检查价格是否到达D点附近
- double distance_to_d = MathAbs(current_price - g_current_patterns.D);
- double entry_tolerance = Point() * 10;
-
- if(distance_to_d <= entry_tolerance && PositionsTotal() < MaxConcurrentTrades) {
- // 最后确认
- if(RequirePRZConfirmation) {
- if(current_price < g_current_patterns.prz_low ||
- current_price > g_current_patterns.prz_high) {
- continue;
- }
- }
-
- ExecuteHarmonicTrade(g_current_patterns);
- }
- }
- }
-
- //+------------------------------------------------------------------+
- //| 执行和谐交易 |
- //+------------------------------------------------------------------+
- void ExecuteHarmonicTrade(const SHarmonicPattern &pattern)
- {
- double volume = CalculateLotSize(pattern);
- double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
- double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
-
- // 规范化交易量
- double min_vol = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
- double max_vol = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
- double vol_step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
-
- // 确保交易量符合要求
- volume = MathMax(volume, min_vol);
- volume = MathMin(volume, max_vol);
- volume = MathRound(volume / vol_step) * vol_step;
-
- string pattern_name = GetPatternName(pattern.pattern_type);
- Print("交易量信息: 输入=", InpLotSize, " 最小=", min_vol, " 最大=", max_vol, " 步长=", vol_step, " 最终=", volume);
-
- string comment = TradeComment + " " + pattern_name + (pattern.is_bullish ? " Buy" : " Sell");
-
- bool trade_result = false;
- if(pattern.is_bullish) {
- trade_result = g_trade.Buy(volume, _Symbol, ask, pattern.stop_loss, pattern.take_profit1, comment);
- } else {
- trade_result = g_trade.Sell(volume, _Symbol, bid, pattern.stop_loss, pattern.take_profit1, comment);
- }
-
- if(trade_result) {
- Print("和谐形态交易执行成功: ", pattern_name, " 质量评分: ", pattern.pattern_quality, " 交易量: ", volume);
- } else {
- Print("和谐形态交易执行失败: ", g_trade.ResultRetcode(), " - ", g_trade.ResultComment());
- }
- }
-
- //+------------------------------------------------------------------+
- //| 获取形态名称 |
- //+------------------------------------------------------------------+
- string GetPatternName(ENUM_PATTERN_TYPE pattern_type)
- {
- switch(pattern_type) {
- case PATTERN_GARTLEY: return "Gartley";
- case PATTERN_BUTTERFLY: return "Butterfly";
- case PATTERN_CRAB: return "Crab";
- case PATTERN_BAT: return "Bat";
- case PATTERN_CYPHER: return "Cypher";
- default: return "Unknown";
- }
- }
-
- //+------------------------------------------------------------------+
- //| 计算仓位大小 |
- //+------------------------------------------------------------------+
- double CalculateLotSize(const SHarmonicPattern &pattern)
- {
- // 使用固定交易量与风险管理结合
- double base_volume = InpLotSize;
-
- // 根据风险管理调整
- if(RiskPercent > 0) {
- double account_balance = AccountInfoDouble(ACCOUNT_BALANCE);
- double risk_amount = account_balance * RiskPercent / 100.0;
- double stop_distance = MathAbs(pattern.entry_price - pattern.stop_loss);
- double pip_value = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
-
- if(pip_value > 0 && stop_distance > 0) {
- double pips_at_risk = stop_distance / Point();
- double calculated_size = risk_amount / (pips_at_risk * pip_value);
- base_volume = MathMin(base_volume, calculated_size);
- }
- }
-
- return MathMax(0.01, NormalizeDouble(base_volume, 2));
- }
-
- //+------------------------------------------------------------------+
- //| 管理现有持仓 |
- //+------------------------------------------------------------------+
- void ManagePositions()
- {
- for(int i = 0; i < PositionsTotal(); i++) {
- ulong ticket = PositionGetTicket(i);
- if(ticket == 0 || PositionGetInteger(POSITION_MAGIC) != InpMagicNumber) continue;
-
- if(UseTrailingStop) {
- UpdateTrailingStop(ticket);
- }
-
- // 检查部分止盈
- CheckPartialProfitTarget(ticket);
- }
- }
-
- //+------------------------------------------------------------------+
- //| 更新跟踪止损 |
- //+------------------------------------------------------------------+
- void UpdateTrailingStop(ulong ticket)
- {
- if(!PositionSelectByTicket(ticket)) return;
-
- double position_open_price = PositionGetDouble(POSITION_PRICE_OPEN);
- double current_sl = PositionGetDouble(POSITION_SL);
- long position_type = PositionGetInteger(POSITION_TYPE);
- double current_price = position_type == POSITION_TYPE_BUY ?
- SymbolInfoDouble(_Symbol, SYMBOL_BID) :
- SymbolInfoDouble(_Symbol, SYMBOL_ASK);
-
- double trailing_distance = TrailingStopPips * Point();
- double new_sl = 0;
-
- if(position_type == POSITION_TYPE_BUY) {
- new_sl = current_price - trailing_distance;
- if(new_sl > current_sl && new_sl > position_open_price) {
- ModifyPosition(ticket, new_sl, PositionGetDouble(POSITION_TP));
- }
- } else {
- new_sl = current_price + trailing_distance;
- if((current_sl == 0 || new_sl < current_sl) && new_sl < position_open_price) {
- ModifyPosition(ticket, new_sl, PositionGetDouble(POSITION_TP));
- }
- }
- }
-
- //+------------------------------------------------------------------+
- //| 检查部分止盈目标 |
- //+------------------------------------------------------------------+
- void CheckPartialProfitTarget(ulong ticket)
- {
- // 可以实现多目标止盈逻辑
- // 这里简化处理,实际可以根据形态的多个止盈目标来分批平仓
- }
-
- //+------------------------------------------------------------------+
- //| 修改持仓 |
- //+------------------------------------------------------------------+
- bool ModifyPosition(ulong ticket, double sl, double tp)
- {
- return g_trade.PositionModify(ticket, NormalizeDouble(sl, _Digits), NormalizeDouble(tp, _Digits));
- }
-
- //+------------------------------------------------------------------+
- //| 更新图表对象 |
- //+------------------------------------------------------------------+
- void UpdateChartObjects()
- {
- if(!ShowPatterns && !ShowFibLevels) return;
-
- for(int i = 0; i < g_pattern_count; i++) {
- if(!g_current_patterns.is_valid) continue;
-
- DrawHarmonicPattern(g_current_patterns, i);
- }
- }
-
- //+------------------------------------------------------------------+
- //| 绘制和谐形态 |
- //+------------------------------------------------------------------+
- void DrawHarmonicPattern(const SHarmonicPattern &pattern, int pattern_index)
- {
- string pattern_prefix = "Harmonic_" + IntegerToString(pattern_index) + "_";
- color line_color = pattern.is_bullish ? clrLimeGreen : clrRed;
-
- // 绘制XABCD连线
- datetime x_time = iTime(_Symbol, PERIOD_CURRENT, pattern.X_bar);
- datetime a_time = iTime(_Symbol, PERIOD_CURRENT, pattern.A_bar);
- datetime b_time = iTime(_Symbol, PERIOD_CURRENT, pattern.B_bar);
- datetime c_time = iTime(_Symbol, PERIOD_CURRENT, pattern.C_bar);
- datetime d_time = iTime(_Symbol, PERIOD_CURRENT, pattern.D_bar);
-
- // XA线
- ObjectDelete(0, pattern_prefix + "XA");
- ObjectCreate(0, pattern_prefix + "XA", OBJ_TREND, 0, x_time, pattern.X, a_time, pattern.A);
- ObjectSetInteger(0, pattern_prefix + "XA", OBJPROP_COLOR, line_color);
- ObjectSetInteger(0, pattern_prefix + "XA", OBJPROP_WIDTH, 2);
-
- // AB线
- ObjectDelete(0, pattern_prefix + "AB");
- ObjectCreate(0, pattern_prefix + "AB", OBJ_TREND, 0, a_time, pattern.A, b_time, pattern.B);
- ObjectSetInteger(0, pattern_prefix + "AB", OBJPROP_COLOR, line_color);
- ObjectSetInteger(0, pattern_prefix + "AB", OBJPROP_WIDTH, 2);
-
- // BC线
- ObjectDelete(0, pattern_prefix + "BC");
- ObjectCreate(0, pattern_prefix + "BC", OBJ_TREND, 0, b_time, pattern.B, c_time, pattern.C);
- ObjectSetInteger(0, pattern_prefix + "BC", OBJPROP_COLOR, line_color);
- ObjectSetInteger(0, pattern_prefix + "BC", OBJPROP_WIDTH, 2);
-
- // CD线
- ObjectDelete(0, pattern_prefix + "CD");
- ObjectCreate(0, pattern_prefix + "CD", OBJ_TREND, 0, c_time, pattern.C, d_time, pattern.D);
- ObjectSetInteger(0, pattern_prefix + "CD", OBJPROP_COLOR, line_color);
- ObjectSetInteger(0, pattern_prefix + "CD", OBJPROP_WIDTH, 2);
-
- // 对角线XB和AC
- ObjectDelete(0, pattern_prefix + "XB");
- ObjectCreate(0, pattern_prefix + "XB", OBJ_TREND, 0, x_time, pattern.X, b_time, pattern.B);
- ObjectSetInteger(0, pattern_prefix + "XB", OBJPROP_COLOR, line_color);
- ObjectSetInteger(0, pattern_prefix + "XB", OBJPROP_STYLE, STYLE_DOT);
-
- ObjectDelete(0, pattern_prefix + "AC");
- ObjectCreate(0, pattern_prefix + "AC", OBJ_TREND, 0, a_time, pattern.A, c_time, pattern.C);
- ObjectSetInteger(0, pattern_prefix + "AC", OBJPROP_COLOR, line_color);
- ObjectSetInteger(0, pattern_prefix + "AC", OBJPROP_STYLE, STYLE_DOT);
-
- // 绘制PRZ区域
- ObjectDelete(0, pattern_prefix + "PRZ");
- ObjectCreate(0, pattern_prefix + "PRZ", OBJ_RECTANGLE, 0,
- d_time, pattern.prz_low, TimeCurrent() + 3600, pattern.prz_high);
- ObjectSetInteger(0, pattern_prefix + "PRZ", OBJPROP_COLOR, clrYellow);
- ObjectSetInteger(0, pattern_prefix + "PRZ", OBJPROP_STYLE, STYLE_SOLID);
- ObjectSetInteger(0, pattern_prefix + "PRZ", OBJPROP_FILL, true);
- ObjectSetInteger(0, pattern_prefix + "PRZ", OBJPROP_BACK, true);
-
- // 添加文本标签
- string pattern_name = GetPatternName(pattern.pattern_type);
- string label_text = pattern_name + (pattern.is_bullish ? " 看涨" : " 看跌") +
- " 质量: " + DoubleToString(pattern.pattern_quality, 2);
-
- ObjectDelete(0, pattern_prefix + "Label");
- ObjectCreate(0, pattern_prefix + "Label", OBJ_TEXT, 0, d_time, pattern.D);
- ObjectSetString(0, pattern_prefix + "Label", OBJPROP_TEXT, label_text);
- ObjectSetInteger(0, pattern_prefix + "Label", OBJPROP_COLOR, line_color);
- ObjectSetInteger(0, pattern_prefix + "Label", OBJPROP_FONTSIZE, 8);
- }
-
- //+------------------------------------------------------------------+
- //| 专家反初始化函数 |
- //+------------------------------------------------------------------+
- void OnDeinit(const int reason)
- {
- // 释放指标句柄
- if(g_rsi_handle != INVALID_HANDLE) {
- IndicatorRelease(g_rsi_handle);
- }
-
- // 清理图表对象
- ObjectsDeleteAll(0, "Harmonic_");
-
- Print("和谐形态策略 EA 已停止,原因代码: ", reason);
- }
复制代码
|