设为首页 收藏本站 切换语言
| 发表于 9 小时前 | 显示全部楼层 |复制链接
#property description "和谐形态交易策略 - Harmonic Patterns (Gartley, Butterfly, Crab, Bat, Cypher)"
//注意,不同的品种,一手的数量和止损要根据情况进行调整,外汇杠杆高,手数要小,股票杠杆低,可以稍大,波动止盈止损也可以根据情况调整,否则会出现成交不了的情况。
image.png
image.png
  1. //--- 包含标准交易库
  2. #include <Trade\Trade.mqh>
  3. //--- 输入参数
  4. input group "=== 和谐形态识别设置 ==="
  5. input bool     EnableGartley = true;                    // 启用Gartley形态
  6. input bool     EnableButterfly = true;                  // 启用Butterfly形态
  7. input bool     EnableCrab = true;                       // 启用Crab形态
  8. input bool     EnableBat = true;                        // 启用Bat形态
  9. input bool     EnableCypher = true;                     // 启用Cypher形态
  10. input int      PatternLookback = 100;                   // 形态识别回看周期
  11. input double   FibTolerance = 0.05;                     // 斐波那契比例容差 (5%)
  12. input group "=== 斐波那契比例设置 ==="
  13. input double   Fib236 = 0.236;                          // 23.6%回撤
  14. input double   Fib382 = 0.382;                          // 38.2%回撤  
  15. input double   Fib500 = 0.500;                          // 50%回撤
  16. input double   Fib618 = 0.618;                          // 61.8%回撤
  17. input double   Fib786 = 0.786;                          // 78.6%回撤
  18. input double   Fib886 = 0.886;                          // 88.6%回撤
  19. input double   Fib1272 = 1.272;                         // 127.2%扩展
  20. input double   Fib1618 = 1.618;                         // 161.8%扩展
  21. input group "=== 形态验证设置 ==="
  22. input bool     RequirePRZConfirmation = true;           // 需要潜在反转区确认
  23. input double   PRZWidthPercent = 2.0;                   // PRZ宽度百分比
  24. input bool     RequireRSIDivergence = true;             // 需要RSI背离确认
  25. input int      RSIPeriod = 14;                          // RSI周期
  26. input bool     RequireVolumeSpike = true;               // 需要成交量放量确认
  27. input double   VolumeMultiplier = 1.5;                  // 成交量倍数
  28. input group "=== 交易管理设置 ==="
  29. input double   RiskRewardRatio = 2.0;                   // 风险收益比
  30. input bool     UsePatternStops = true;                  // 使用形态止损
  31. input bool     UseFibTargets = true;                    // 使用斐波那契目标
  32. input int      MaxConcurrentTrades = 3;                 // 最大同时交易数
  33. input bool     TradeOnlyPerfectPatterns = false;        // 只交易完美形态
  34. input group "=== 风险管理 ==="
  35. input double   RiskPercent = 1.5;                       // 风险百分比
  36. input double   InpLotSize = 1.0;                        // 交易手数
  37. input double   MaxStopLossPips = 100.0;                 // 最大止损点数
  38. input double   MinRiskReward = 1.5;                     // 最小风险收益比
  39. input bool     UseTrailingStop = true;                  // 使用跟踪止损
  40. input double   TrailingStopPips = 40.0;                 // 跟踪止损点数
  41. input group "=== 其他设置 ==="
  42. input int      InpMagicNumber = 20250819;               // 魔术号码
  43. input string   TradeComment = "HarmonicEA";             // 交易注释
  44. input bool     ShowPatterns = true;                     // 显示形态
  45. input bool     ShowFibLevels = true;                    // 显示斐波那契水平
  46. input color    PatternColor = clrLimeGreen;             // 形态颜色
  47. input color    FibColor = clrGold;                      // 斐波那契颜色
  48. //--- 形态结构
  49. enum ENUM_PATTERN_TYPE {
  50.     PATTERN_GARTLEY = 0,
  51.     PATTERN_BUTTERFLY = 1,
  52.     PATTERN_CRAB = 2,
  53.     PATTERN_BAT = 3,
  54.     PATTERN_CYPHER = 4
  55. };
  56. struct SHarmonicPattern {
  57.     ENUM_PATTERN_TYPE pattern_type;
  58.     bool is_bullish;
  59.     datetime formation_time;
  60.     double X, A, B, C, D;                               // 5个关键点
  61.     int X_bar, A_bar, B_bar, C_bar, D_bar;             // 对应K线索引
  62.     double XA, AB, BC, CD;                              // 波段距离
  63.     double AB_XA_ratio, BC_AB_ratio, CD_BC_ratio, AD_XA_ratio; // 斐波那契比例
  64.     double prz_low, prz_high;                           // 潜在反转区
  65.     double entry_price;                                 // 入场价格
  66.     double stop_loss;                                   // 止损价格
  67.     double take_profit1, take_profit2, take_profit3;    // 三个止盈目标
  68.     bool is_valid;                                      // 形态有效性
  69.     double pattern_quality;                             // 形态质量评分
  70. };
  71. //--- 全局变量
  72. SHarmonicPattern g_current_patterns[20];
  73. int g_pattern_count = 0;
  74. double g_swing_highs[200];
  75. double g_swing_lows[200];
  76. int g_swing_high_bars[200];
  77. int g_swing_low_bars[200];
  78. int g_high_count = 0, g_low_count = 0;
  79. int g_rsi_handle = INVALID_HANDLE;
  80. double g_rsi_buffer[];
  81. //--- 交易对象
  82. CTrade g_trade;
  83. //+------------------------------------------------------------------+
  84. //| 专家初始化函数                                                      |
  85. //+------------------------------------------------------------------+
  86. int OnInit()
  87. {
  88.     Print("和谐形态策略 EA 启动");
  89.     // 初始化交易库
  90.     g_trade.SetExpertMagicNumber(InpMagicNumber);
  91.     g_trade.SetMarginMode();
  92.     g_trade.SetTypeFillingBySymbol(_Symbol);
  93.     g_trade.SetDeviationInPoints(10);
  94.     // 初始化RSI指标
  95.     g_rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, RSIPeriod, PRICE_CLOSE);
  96.     if(g_rsi_handle == INVALID_HANDLE) {
  97.         Print("RSI指标初始化失败");
  98.         return INIT_FAILED;
  99.     }
  100.     ArraySetAsSeries(g_rsi_buffer, true);
  101.     // 初始化摆动点数据
  102.     if(!FindSwingPoints()) {
  103.         Print("摆动点初始化失败");
  104.         return INIT_FAILED;
  105.     }
  106.     return INIT_SUCCEEDED;
  107. }
  108. //+------------------------------------------------------------------+
  109. //| 寻找摆动高低点                                                      |
  110. //+------------------------------------------------------------------+
  111. bool FindSwingPoints()
  112. {
  113.     int swing_period = 5; // 摆动点识别周期
  114.     g_high_count = 0;
  115.     g_low_count = 0;
  116.     for(int i = swing_period; i < PatternLookback - swing_period; i++) {
  117.         double high = iHigh(_Symbol, PERIOD_CURRENT, i);
  118.         double low = iLow(_Symbol, PERIOD_CURRENT, i);
  119.         // 识别摆动高点
  120.         bool is_swing_high = true;
  121.         for(int j = 1; j <= swing_period; j++) {
  122.             if(iHigh(_Symbol, PERIOD_CURRENT, i - j) >= high ||
  123.                iHigh(_Symbol, PERIOD_CURRENT, i + j) >= high) {
  124.                 is_swing_high = false;
  125.                 break;
  126.             }
  127.         }
  128.         if(is_swing_high && g_high_count < 200) {
  129.             g_swing_highs[g_high_count] = high;
  130.             g_swing_high_bars[g_high_count] = i;
  131.             g_high_count++;
  132.         }
  133.         // 识别摆动低点
  134.         bool is_swing_low = true;
  135.         for(int j = 1; j <= swing_period; j++) {
  136.             if(iLow(_Symbol, PERIOD_CURRENT, i - j) <= low ||
  137.                iLow(_Symbol, PERIOD_CURRENT, i + j) <= low) {
  138.                 is_swing_low = false;
  139.                 break;
  140.             }
  141.         }
  142.         if(is_swing_low && g_low_count < 200) {
  143.             g_swing_lows[g_low_count] = low;
  144.             g_swing_low_bars[g_low_count] = i;
  145.             g_low_count++;
  146.         }
  147.     }
  148.     Print("找到摆动高点: ", g_high_count, ", 摆动低点: ", g_low_count);
  149.     return (g_high_count >= 5 && g_low_count >= 5);
  150. }
  151. //+------------------------------------------------------------------+
  152. //| 专家tick函数                                                       |
  153. //+------------------------------------------------------------------+
  154. void OnTick()
  155. {
  156.     // 更新技术指标
  157.     if(CopyBuffer(g_rsi_handle, 0, 0, 50, g_rsi_buffer) < 50) return;
  158.     // 重新扫描摆动点
  159.     static datetime last_scan_time = 0;
  160.     if(TimeCurrent() - last_scan_time > 3600) { // 每小时扫描一次
  161.         FindSwingPoints();
  162.         last_scan_time = TimeCurrent();
  163.     }
  164.     // 识别和谐形态
  165.     ScanForHarmonicPatterns();
  166.     // 检查交易信号
  167.     CheckHarmonicSignals();
  168.     // 管理现有持仓
  169.     ManagePositions();
  170.     // 更新图形显示
  171.     if(ShowPatterns || ShowFibLevels) {
  172.         UpdateChartObjects();
  173.     }
  174. }
  175. //+------------------------------------------------------------------+
  176. //| 扫描和谐形态                                                        |
  177. //+------------------------------------------------------------------+
  178. void ScanForHarmonicPatterns()
  179. {
  180.     g_pattern_count = 0;
  181.     // 扫描看涨形态
  182.     if(g_low_count >= 3 && g_high_count >= 2) {
  183.         ScanBullishPatterns();
  184.     }
  185.     // 扫描看跌形态
  186.     if(g_high_count >= 3 && g_low_count >= 2) {
  187.         ScanBearishPatterns();
  188.     }
  189.     // 验证和评分形态
  190.     for(int i = 0; i < g_pattern_count; i++) {
  191.         ValidatePattern(g_current_patterns);
  192.     }
  193. }
  194. //+------------------------------------------------------------------+
  195. //| 扫描看涨形态                                                        |
  196. //+------------------------------------------------------------------+
  197. void ScanBullishPatterns()
  198. {
  199.     // 寻找 X-A-B-C-D 结构 (低-高-低-高-低)
  200.     for(int x = 0; x < g_low_count - 2; x++) {
  201.         for(int a = 0; a < g_high_count - 1; a++) {
  202.             if(g_swing_high_bars[a] <= g_swing_low_bars[x]) continue;
  203.             for(int b = x + 1; b < g_low_count - 1; b++) {
  204.                 if(g_swing_low_bars <= g_swing_high_bars[a]) continue;
  205.                 for(int c = a + 1; c < g_high_count; c++) {
  206.                     if(g_swing_high_bars[c] <= g_swing_low_bars) continue;
  207.                     for(int d = b + 1; d < g_low_count; d++) {
  208.                         if(g_swing_low_bars[d] <= g_swing_high_bars[c]) continue;
  209.                         if(g_swing_low_bars[d] < 10) continue; // 太接近当前价格
  210.                         // 构建潜在形态
  211.                         SHarmonicPattern pattern = {};
  212.                         pattern.is_bullish = true;
  213.                         pattern.X = g_swing_lows[x];
  214.                         pattern.A = g_swing_highs[a];
  215.                         pattern.B = g_swing_lows;
  216.                         pattern.C = g_swing_highs[c];
  217.                         pattern.D = g_swing_lows[d];
  218.                         pattern.X_bar = g_swing_low_bars[x];
  219.                         pattern.A_bar = g_swing_high_bars[a];
  220.                         pattern.B_bar = g_swing_low_bars;
  221.                         pattern.C_bar = g_swing_high_bars[c];
  222.                         pattern.D_bar = g_swing_low_bars[d];
  223.                         // 计算比例
  224.                         CalculatePatternRatios(pattern);
  225.                         // 识别形态类型
  226.                         if(IdentifyPatternType(pattern) && g_pattern_count < 20) {
  227.                             g_current_patterns[g_pattern_count] = pattern;
  228.                             g_pattern_count++;
  229.                         }
  230.                     }
  231.                 }
  232.             }
  233.         }
  234.     }
  235. }
  236. //+------------------------------------------------------------------+
  237. //| 扫描看跌形态                                                        |
  238. //+------------------------------------------------------------------+
  239. void ScanBearishPatterns()
  240. {
  241.     // 寻找 X-A-B-C-D 结构 (高-低-高-低-高)
  242.     for(int x = 0; x < g_high_count - 2; x++) {
  243.         for(int a = 0; a < g_low_count - 1; a++) {
  244.             if(g_swing_low_bars[a] <= g_swing_high_bars[x]) continue;
  245.             for(int b = x + 1; b < g_high_count - 1; b++) {
  246.                 if(g_swing_high_bars <= g_swing_low_bars[a]) continue;
  247.                 for(int c = a + 1; c < g_low_count; c++) {
  248.                     if(g_swing_low_bars[c] <= g_swing_high_bars) continue;
  249.                     for(int d = b + 1; d < g_high_count; d++) {
  250.                         if(g_swing_high_bars[d] <= g_swing_low_bars[c]) continue;
  251.                         if(g_swing_high_bars[d] < 10) continue; // 太接近当前价格
  252.                         // 构建潜在形态
  253.                         SHarmonicPattern pattern = {};
  254.                         pattern.is_bullish = false;
  255.                         pattern.X = g_swing_highs[x];
  256.                         pattern.A = g_swing_lows[a];
  257.                         pattern.B = g_swing_highs;
  258.                         pattern.C = g_swing_lows[c];
  259.                         pattern.D = g_swing_highs[d];
  260.                         pattern.X_bar = g_swing_high_bars[x];
  261.                         pattern.A_bar = g_swing_low_bars[a];
  262.                         pattern.B_bar = g_swing_high_bars;
  263.                         pattern.C_bar = g_swing_low_bars[c];
  264.                         pattern.D_bar = g_swing_high_bars[d];
  265.                         // 计算比例
  266.                         CalculatePatternRatios(pattern);
  267.                         // 识别形态类型
  268.                         if(IdentifyPatternType(pattern) && g_pattern_count < 20) {
  269.                             g_current_patterns[g_pattern_count] = pattern;
  270.                             g_pattern_count++;
  271.                         }
  272.                     }
  273.                 }
  274.             }
  275.         }
  276.     }
  277. }
  278. //+------------------------------------------------------------------+
  279. //| 计算形态比例                                                        |
  280. //+------------------------------------------------------------------+
  281. void CalculatePatternRatios(SHarmonicPattern &pattern)
  282. {
  283.     pattern.XA = MathAbs(pattern.A - pattern.X);
  284.     pattern.AB = MathAbs(pattern.B - pattern.A);
  285.     pattern.BC = MathAbs(pattern.C - pattern.B);
  286.     pattern.CD = MathAbs(pattern.D - pattern.C);
  287.     if(pattern.XA > 0) {
  288.         pattern.AB_XA_ratio = pattern.AB / pattern.XA;
  289.         pattern.AD_XA_ratio = MathAbs(pattern.D - pattern.A) / pattern.XA;
  290.     }
  291.     if(pattern.AB > 0) {
  292.         pattern.BC_AB_ratio = pattern.BC / pattern.AB;
  293.     }
  294.     if(pattern.BC > 0) {
  295.         pattern.CD_BC_ratio = pattern.CD / pattern.BC;
  296.     }
  297. }
  298. //+------------------------------------------------------------------+
  299. //| 识别形态类型                                                        |
  300. //+------------------------------------------------------------------+
  301. bool IdentifyPatternType(SHarmonicPattern &pattern)
  302. {
  303.     double tolerance = FibTolerance;
  304.     // Gartley形态 (AB=61.8%XA, BC=38.2%-88.6%AB, CD=127.2%BC, AD=78.6%XA)
  305.     if(EnableGartley && CheckRatio(pattern.AB_XA_ratio, Fib618, tolerance) &&
  306.        CheckRatio(pattern.BC_AB_ratio, 0.382, tolerance, 0.886) &&
  307.        CheckRatio(pattern.CD_BC_ratio, Fib1272, tolerance) &&
  308.        CheckRatio(pattern.AD_XA_ratio, Fib786, tolerance)) {
  309.         pattern.pattern_type = PATTERN_GARTLEY;
  310.         return true;
  311.     }
  312.     // Butterfly形态 (AB=78.6%XA, BC=38.2%-88.6%AB, CD=161.8%BC, AD=127.2%-161.8%XA)
  313.     if(EnableButterfly && CheckRatio(pattern.AB_XA_ratio, Fib786, tolerance) &&
  314.        CheckRatio(pattern.BC_AB_ratio, 0.382, tolerance, 0.886) &&
  315.        CheckRatio(pattern.CD_BC_ratio, Fib1618, tolerance) &&
  316.        CheckRatio(pattern.AD_XA_ratio, 1.272, tolerance, 1.618)) {
  317.         pattern.pattern_type = PATTERN_BUTTERFLY;
  318.         return true;
  319.     }
  320.     // Crab形态 (AB=38.2%-61.8%XA, BC=38.2%-88.6%AB, CD=224%-361.8%BC, AD=161.8%XA)
  321.     if(EnableCrab && CheckRatio(pattern.AB_XA_ratio, 0.382, tolerance, 0.618) &&
  322.        CheckRatio(pattern.BC_AB_ratio, 0.382, tolerance, 0.886) &&
  323.        CheckRatio(pattern.CD_BC_ratio, 2.24, tolerance, 3.618) &&
  324.        CheckRatio(pattern.AD_XA_ratio, Fib1618, tolerance)) {
  325.         pattern.pattern_type = PATTERN_CRAB;
  326.         return true;
  327.     }
  328.     // Bat形态 (AB=38.2%-50%XA, BC=38.2%-88.6%AB, CD=162%-267%BC, AD=88.6%XA)
  329.     if(EnableBat && CheckRatio(pattern.AB_XA_ratio, 0.382, tolerance, 0.50) &&
  330.        CheckRatio(pattern.BC_AB_ratio, 0.382, tolerance, 0.886) &&
  331.        CheckRatio(pattern.CD_BC_ratio, 1.62, tolerance, 2.67) &&
  332.        CheckRatio(pattern.AD_XA_ratio, Fib886, tolerance)) {
  333.         pattern.pattern_type = PATTERN_BAT;
  334.         return true;
  335.     }
  336.     // Cypher形态 (AB=38.2%-61.8%XA, BC=113%-141.4%AB, CD=78.6%BC, AD=78.6%XA)
  337.     if(EnableCypher && CheckRatio(pattern.AB_XA_ratio, 0.382, tolerance, 0.618) &&
  338.        CheckRatio(pattern.BC_AB_ratio, 1.13, tolerance, 1.414) &&
  339.        CheckRatio(pattern.CD_BC_ratio, Fib786, tolerance) &&
  340.        CheckRatio(pattern.AD_XA_ratio, Fib786, tolerance)) {
  341.         pattern.pattern_type = PATTERN_CYPHER;
  342.         return true;
  343.     }
  344.     return false;
  345. }
  346. //+------------------------------------------------------------------+
  347. //| 检查比例                                                           |
  348. //+------------------------------------------------------------------+
  349. bool CheckRatio(double actual_ratio, double target_ratio, double tolerance, double max_ratio = 0)
  350. {
  351.     double lower_bound = target_ratio * (1.0 - tolerance);
  352.     double upper_bound = (max_ratio > 0) ? max_ratio * (1.0 + tolerance) : target_ratio * (1.0 + tolerance);
  353.     return (actual_ratio >= lower_bound && actual_ratio <= upper_bound);
  354. }
  355. //+------------------------------------------------------------------+
  356. //| 验证形态                                                           |
  357. //+------------------------------------------------------------------+
  358. void ValidatePattern(SHarmonicPattern &pattern)
  359. {
  360.     pattern.is_valid = false;
  361.     pattern.pattern_quality = 0.0;
  362.     // 计算潜在反转区 (PRZ)
  363.     CalculatePRZ(pattern);
  364.     // 基础有效性检查
  365.     if(!BasicPatternValidation(pattern)) return;
  366.     // 形态质量评分
  367.     double quality_score = 0.0;
  368.     // 比例精确度评分 (40%)
  369.     quality_score += CalculateRatioAccuracy(pattern) * 0.4;
  370.     // PRZ聚合度评分 (30%)
  371.     quality_score += CalculatePRZQuality(pattern) * 0.3;
  372.     // 技术指标确认评分 (20%)
  373.     quality_score += CalculateIndicatorConfirmation(pattern) * 0.2;
  374.     // 成交量确认评分 (10%)
  375.     quality_score += CalculateVolumeConfirmation(pattern) * 0.1;
  376.     pattern.pattern_quality = quality_score;
  377.     // 设置质量阈值
  378.     double min_quality = TradeOnlyPerfectPatterns ? 0.8 : 0.6;
  379.     pattern.is_valid = (quality_score >= min_quality);
  380.     if(pattern.is_valid) {
  381.         CalculateTradeParameters(pattern);
  382.     }
  383. }
  384. //+------------------------------------------------------------------+
  385. //| 计算潜在反转区                                                      |
  386. //+------------------------------------------------------------------+
  387. void CalculatePRZ(SHarmonicPattern &pattern)
  388. {
  389.     double prz_width = MathAbs(pattern.A - pattern.X) * PRZWidthPercent / 100.0;
  390.     if(pattern.is_bullish) {
  391.         pattern.prz_low = pattern.D - prz_width / 2;
  392.         pattern.prz_high = pattern.D + prz_width / 2;
  393.     } else {
  394.         pattern.prz_low = pattern.D - prz_width / 2;
  395.         pattern.prz_high = pattern.D + prz_width / 2;
  396.     }
  397. }
  398. //+------------------------------------------------------------------+
  399. //| 基础形态验证                                                        |
  400. //+------------------------------------------------------------------+
  401. bool BasicPatternValidation(const SHarmonicPattern &pattern)
  402. {
  403.     // 时间序列检查
  404.     if(pattern.X_bar <= pattern.A_bar || pattern.A_bar <= pattern.B_bar ||
  405.        pattern.B_bar <= pattern.C_bar || pattern.C_bar <= pattern.D_bar) {
  406.         return false;
  407.     }
  408.     // 价格结构检查
  409.     if(pattern.is_bullish) {
  410.         if(pattern.X >= pattern.A || pattern.B >= pattern.A ||
  411.            pattern.C <= pattern.B || pattern.D >= pattern.C) {
  412.             return false;
  413.         }
  414.     } else {
  415.         if(pattern.X <= pattern.A || pattern.B <= pattern.A ||
  416.            pattern.C >= pattern.B || pattern.D <= pattern.C) {
  417.             return false;
  418.         }
  419.     }
  420.     return true;
  421. }
  422. //+------------------------------------------------------------------+
  423. //| 计算比例精确度                                                      |
  424. //+------------------------------------------------------------------+
  425. double CalculateRatioAccuracy(const SHarmonicPattern &pattern)
  426. {
  427.     double total_accuracy = 0.0;
  428.     int ratio_count = 0;
  429.     // 根据形态类型计算各比例的精确度
  430.     switch(pattern.pattern_type) {
  431.         case PATTERN_GARTLEY:
  432.             total_accuracy += 1.0 - MathAbs(pattern.AB_XA_ratio - Fib618) / Fib618;
  433.             total_accuracy += 1.0 - MathAbs(pattern.AD_XA_ratio - Fib786) / Fib786;
  434.             ratio_count = 2;
  435.             break;
  436.         case PATTERN_BUTTERFLY:
  437.             total_accuracy += 1.0 - MathAbs(pattern.AB_XA_ratio - Fib786) / Fib786;
  438.             total_accuracy += 1.0 - MathAbs(pattern.CD_BC_ratio - Fib1618) / Fib1618;
  439.             ratio_count = 2;
  440.             break;
  441.         case PATTERN_CRAB:
  442.             total_accuracy += 1.0 - MathAbs(pattern.AD_XA_ratio - Fib1618) / Fib1618;
  443.             ratio_count = 1;
  444.             break;
  445.         case PATTERN_BAT:
  446.             total_accuracy += 1.0 - MathAbs(pattern.AD_XA_ratio - Fib886) / Fib886;
  447.             ratio_count = 1;
  448.             break;
  449.         case PATTERN_CYPHER:
  450.             total_accuracy += 1.0 - MathAbs(pattern.AD_XA_ratio - Fib786) / Fib786;
  451.             ratio_count = 1;
  452.             break;
  453.     }
  454.     return ratio_count > 0 ? MathMax(0.0, total_accuracy / ratio_count) : 0.0;
  455. }
  456. //+------------------------------------------------------------------+
  457. //| 计算PRZ质量                                                        |
  458. //+------------------------------------------------------------------+
  459. double CalculatePRZQuality(const SHarmonicPattern &pattern)
  460. {
  461.     double current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
  462.     double prz_center = (pattern.prz_high + pattern.prz_low) / 2.0;
  463.     double distance_to_prz = MathAbs(current_price - prz_center);
  464.     double prz_width = pattern.prz_high - pattern.prz_low;
  465.     // 价格越接近PRZ中心,质量评分越高
  466.     return MathMax(0.0, 1.0 - (distance_to_prz / prz_width));
  467. }
  468. //+------------------------------------------------------------------+
  469. //| 计算指标确认                                                        |
  470. //+------------------------------------------------------------------+
  471. double CalculateIndicatorConfirmation(const SHarmonicPattern &pattern)
  472. {
  473.     double confirmation = 0.0;
  474.     if(RequireRSIDivergence && ArraySize(g_rsi_buffer) > pattern.D_bar + 5) {
  475.         // 检查RSI背离
  476.         double rsi_at_d = g_rsi_buffer[pattern.D_bar];
  477.         double rsi_current = g_rsi_buffer[0];
  478.         if(pattern.is_bullish) {
  479.             // 看涨背离:价格创新低,RSI不创新低
  480.             if(pattern.D < pattern.B && rsi_at_d > g_rsi_buffer[pattern.B_bar]) {
  481.                 confirmation += 0.5;
  482.             }
  483.             // RSI超卖确认
  484.             if(rsi_current < 30) {
  485.                 confirmation += 0.3;
  486.             }
  487.         } else {
  488.             // 看跌背离:价格创新高,RSI不创新高
  489.             if(pattern.D > pattern.B && rsi_at_d < g_rsi_buffer[pattern.B_bar]) {
  490.                 confirmation += 0.5;
  491.             }
  492.             // RSI超买确认
  493.             if(rsi_current > 70) {
  494.                 confirmation += 0.3;
  495.             }
  496.         }
  497.     }
  498.     return MathMin(1.0, confirmation);
  499. }
  500. //+------------------------------------------------------------------+
  501. //| 计算成交量确认                                                      |
  502. //+------------------------------------------------------------------+
  503. double CalculateVolumeConfirmation(const SHarmonicPattern &pattern)
  504. {
  505.     if(!RequireVolumeSpike) return 1.0;
  506.     long volume_at_d = iVolume(_Symbol, PERIOD_CURRENT, pattern.D_bar);
  507.     long avg_volume = 0;
  508.     for(int i = pattern.D_bar + 1; i <= pattern.D_bar + 20; i++) {
  509.         avg_volume += iVolume(_Symbol, PERIOD_CURRENT, i);
  510.     }
  511.     avg_volume /= 20;
  512.     if(avg_volume > 0) {
  513.         double volume_ratio = (double)volume_at_d / avg_volume;
  514.         return MathMin(1.0, volume_ratio / VolumeMultiplier);
  515.     }
  516.     return 0.5;
  517. }
  518. //+------------------------------------------------------------------+
  519. //| 计算交易参数                                                        |
  520. //+------------------------------------------------------------------+
  521. void CalculateTradeParameters(SHarmonicPattern &pattern)
  522. {
  523.     pattern.entry_price = pattern.D;
  524.     // 计算止损
  525.     if(UsePatternStops) {
  526.         double pattern_range = MathAbs(pattern.A - pattern.X);
  527.         double stop_distance = pattern_range * 0.1; // 10%的形态范围
  528.         if(pattern.is_bullish) {
  529.             pattern.stop_loss = pattern.D - stop_distance;
  530.         } else {
  531.             pattern.stop_loss = pattern.D + stop_distance;
  532.         }
  533.     } else {
  534.         double stop_distance = MaxStopLossPips * Point();
  535.         if(pattern.is_bullish) {
  536.             pattern.stop_loss = pattern.D - stop_distance;
  537.         } else {
  538.             pattern.stop_loss = pattern.D + stop_distance;
  539.         }
  540.     }
  541.     // 计算止盈目标
  542.     if(UseFibTargets) {
  543.         double cd_range = MathAbs(pattern.D - pattern.C);
  544.         if(pattern.is_bullish) {
  545.             pattern.take_profit1 = pattern.D + cd_range * Fib382;
  546.             pattern.take_profit2 = pattern.D + cd_range * Fib618;
  547.             pattern.take_profit3 = pattern.D + cd_range * Fib786;
  548.         } else {
  549.             pattern.take_profit1 = pattern.D - cd_range * Fib382;
  550.             pattern.take_profit2 = pattern.D - cd_range * Fib618;
  551.             pattern.take_profit3 = pattern.D - cd_range * Fib786;
  552.         }
  553.     } else {
  554.         double stop_distance = MathAbs(pattern.entry_price - pattern.stop_loss);
  555.         if(pattern.is_bullish) {
  556.             pattern.take_profit1 = pattern.entry_price + stop_distance * RiskRewardRatio;
  557.             pattern.take_profit2 = pattern.entry_price + stop_distance * RiskRewardRatio * 1.5;
  558.             pattern.take_profit3 = pattern.entry_price + stop_distance * RiskRewardRatio * 2.0;
  559.         } else {
  560.             pattern.take_profit1 = pattern.entry_price - stop_distance * RiskRewardRatio;
  561.             pattern.take_profit2 = pattern.entry_price - stop_distance * RiskRewardRatio * 1.5;
  562.             pattern.take_profit3 = pattern.entry_price - stop_distance * RiskRewardRatio * 2.0;
  563.         }
  564.     }
  565. }
  566. //+------------------------------------------------------------------+
  567. //| 检查和谐信号                                                        |
  568. //+------------------------------------------------------------------+
  569. void CheckHarmonicSignals()
  570. {
  571.     double current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
  572.     for(int i = 0; i < g_pattern_count; i++) {
  573.         if(!g_current_patterns.is_valid) continue;
  574.         if(g_current_patterns.D_bar > 5) continue; // 只交易最新的形态
  575.         // 检查价格是否到达D点附近
  576.         double distance_to_d = MathAbs(current_price - g_current_patterns.D);
  577.         double entry_tolerance = Point() * 10;
  578.         if(distance_to_d <= entry_tolerance && PositionsTotal() < MaxConcurrentTrades) {
  579.             // 最后确认
  580.             if(RequirePRZConfirmation) {
  581.                 if(current_price < g_current_patterns.prz_low ||
  582.                    current_price > g_current_patterns.prz_high) {
  583.                     continue;
  584.                 }
  585.             }
  586.             ExecuteHarmonicTrade(g_current_patterns);
  587.         }
  588.     }
  589. }
  590. //+------------------------------------------------------------------+
  591. //| 执行和谐交易                                                        |
  592. //+------------------------------------------------------------------+
  593. void ExecuteHarmonicTrade(const SHarmonicPattern &pattern)
  594. {
  595.     double volume = CalculateLotSize(pattern);
  596.     double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
  597.     double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
  598.     // 规范化交易量
  599.     double min_vol = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
  600.     double max_vol = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
  601.     double vol_step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
  602.     // 确保交易量符合要求
  603.     volume = MathMax(volume, min_vol);
  604.     volume = MathMin(volume, max_vol);
  605.     volume = MathRound(volume / vol_step) * vol_step;
  606.     string pattern_name = GetPatternName(pattern.pattern_type);
  607.     Print("交易量信息: 输入=", InpLotSize, " 最小=", min_vol, " 最大=", max_vol, " 步长=", vol_step, " 最终=", volume);
  608.     string comment = TradeComment + " " + pattern_name + (pattern.is_bullish ? " Buy" : " Sell");
  609.     bool trade_result = false;
  610.     if(pattern.is_bullish) {
  611.         trade_result = g_trade.Buy(volume, _Symbol, ask, pattern.stop_loss, pattern.take_profit1, comment);
  612.     } else {
  613.         trade_result = g_trade.Sell(volume, _Symbol, bid, pattern.stop_loss, pattern.take_profit1, comment);
  614.     }
  615.     if(trade_result) {
  616.         Print("和谐形态交易执行成功: ", pattern_name, " 质量评分: ", pattern.pattern_quality, " 交易量: ", volume);
  617.     } else {
  618.         Print("和谐形态交易执行失败: ", g_trade.ResultRetcode(), " - ", g_trade.ResultComment());
  619.     }
  620. }
  621. //+------------------------------------------------------------------+
  622. //| 获取形态名称                                                        |
  623. //+------------------------------------------------------------------+
  624. string GetPatternName(ENUM_PATTERN_TYPE pattern_type)
  625. {
  626.     switch(pattern_type) {
  627.         case PATTERN_GARTLEY: return "Gartley";
  628.         case PATTERN_BUTTERFLY: return "Butterfly";
  629.         case PATTERN_CRAB: return "Crab";
  630.         case PATTERN_BAT: return "Bat";
  631.         case PATTERN_CYPHER: return "Cypher";
  632.         default: return "Unknown";
  633.     }
  634. }
  635. //+------------------------------------------------------------------+
  636. //| 计算仓位大小                                                        |
  637. //+------------------------------------------------------------------+
  638. double CalculateLotSize(const SHarmonicPattern &pattern)
  639. {
  640.     // 使用固定交易量与风险管理结合
  641.     double base_volume = InpLotSize;
  642.     // 根据风险管理调整
  643.     if(RiskPercent > 0) {
  644.         double account_balance = AccountInfoDouble(ACCOUNT_BALANCE);
  645.         double risk_amount = account_balance * RiskPercent / 100.0;
  646.         double stop_distance = MathAbs(pattern.entry_price - pattern.stop_loss);
  647.         double pip_value = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
  648.         if(pip_value > 0 && stop_distance > 0) {
  649.             double pips_at_risk = stop_distance / Point();
  650.             double calculated_size = risk_amount / (pips_at_risk * pip_value);
  651.             base_volume = MathMin(base_volume, calculated_size);
  652.         }
  653.     }
  654.     return MathMax(0.01, NormalizeDouble(base_volume, 2));
  655. }
  656. //+------------------------------------------------------------------+
  657. //| 管理现有持仓                                                        |
  658. //+------------------------------------------------------------------+
  659. void ManagePositions()
  660. {
  661.     for(int i = 0; i < PositionsTotal(); i++) {
  662.         ulong ticket = PositionGetTicket(i);
  663.         if(ticket == 0 || PositionGetInteger(POSITION_MAGIC) != InpMagicNumber) continue;
  664.         if(UseTrailingStop) {
  665.             UpdateTrailingStop(ticket);
  666.         }
  667.         // 检查部分止盈
  668.         CheckPartialProfitTarget(ticket);
  669.     }
  670. }
  671. //+------------------------------------------------------------------+
  672. //| 更新跟踪止损                                                        |
  673. //+------------------------------------------------------------------+
  674. void UpdateTrailingStop(ulong ticket)
  675. {
  676.     if(!PositionSelectByTicket(ticket)) return;
  677.     double position_open_price = PositionGetDouble(POSITION_PRICE_OPEN);
  678.     double current_sl = PositionGetDouble(POSITION_SL);
  679.     long position_type = PositionGetInteger(POSITION_TYPE);
  680.     double current_price = position_type == POSITION_TYPE_BUY ?
  681.                           SymbolInfoDouble(_Symbol, SYMBOL_BID) :
  682.                           SymbolInfoDouble(_Symbol, SYMBOL_ASK);
  683.     double trailing_distance = TrailingStopPips * Point();
  684.     double new_sl = 0;
  685.     if(position_type == POSITION_TYPE_BUY) {
  686.         new_sl = current_price - trailing_distance;
  687.         if(new_sl > current_sl && new_sl > position_open_price) {
  688.             ModifyPosition(ticket, new_sl, PositionGetDouble(POSITION_TP));
  689.         }
  690.     } else {
  691.         new_sl = current_price + trailing_distance;
  692.         if((current_sl == 0 || new_sl < current_sl) && new_sl < position_open_price) {
  693.             ModifyPosition(ticket, new_sl, PositionGetDouble(POSITION_TP));
  694.         }
  695.     }
  696. }
  697. //+------------------------------------------------------------------+
  698. //| 检查部分止盈目标                                                     |
  699. //+------------------------------------------------------------------+
  700. void CheckPartialProfitTarget(ulong ticket)
  701. {
  702.     // 可以实现多目标止盈逻辑
  703.     // 这里简化处理,实际可以根据形态的多个止盈目标来分批平仓
  704. }
  705. //+------------------------------------------------------------------+
  706. //| 修改持仓                                                           |
  707. //+------------------------------------------------------------------+
  708. bool ModifyPosition(ulong ticket, double sl, double tp)
  709. {
  710.     return g_trade.PositionModify(ticket, NormalizeDouble(sl, _Digits), NormalizeDouble(tp, _Digits));
  711. }
  712. //+------------------------------------------------------------------+
  713. //| 更新图表对象                                                        |
  714. //+------------------------------------------------------------------+
  715. void UpdateChartObjects()
  716. {
  717.     if(!ShowPatterns && !ShowFibLevels) return;
  718.     for(int i = 0; i < g_pattern_count; i++) {
  719.         if(!g_current_patterns.is_valid) continue;
  720.         DrawHarmonicPattern(g_current_patterns, i);
  721.     }
  722. }
  723. //+------------------------------------------------------------------+
  724. //| 绘制和谐形态                                                        |
  725. //+------------------------------------------------------------------+
  726. void DrawHarmonicPattern(const SHarmonicPattern &pattern, int pattern_index)
  727. {
  728.     string pattern_prefix = "Harmonic_" + IntegerToString(pattern_index) + "_";
  729.     color line_color = pattern.is_bullish ? clrLimeGreen : clrRed;
  730.     // 绘制XABCD连线
  731.     datetime x_time = iTime(_Symbol, PERIOD_CURRENT, pattern.X_bar);
  732.     datetime a_time = iTime(_Symbol, PERIOD_CURRENT, pattern.A_bar);
  733.     datetime b_time = iTime(_Symbol, PERIOD_CURRENT, pattern.B_bar);
  734.     datetime c_time = iTime(_Symbol, PERIOD_CURRENT, pattern.C_bar);
  735.     datetime d_time = iTime(_Symbol, PERIOD_CURRENT, pattern.D_bar);
  736.     // XA线
  737.     ObjectDelete(0, pattern_prefix + "XA");
  738.     ObjectCreate(0, pattern_prefix + "XA", OBJ_TREND, 0, x_time, pattern.X, a_time, pattern.A);
  739.     ObjectSetInteger(0, pattern_prefix + "XA", OBJPROP_COLOR, line_color);
  740.     ObjectSetInteger(0, pattern_prefix + "XA", OBJPROP_WIDTH, 2);
  741.     // AB线
  742.     ObjectDelete(0, pattern_prefix + "AB");
  743.     ObjectCreate(0, pattern_prefix + "AB", OBJ_TREND, 0, a_time, pattern.A, b_time, pattern.B);
  744.     ObjectSetInteger(0, pattern_prefix + "AB", OBJPROP_COLOR, line_color);
  745.     ObjectSetInteger(0, pattern_prefix + "AB", OBJPROP_WIDTH, 2);
  746.     // BC线
  747.     ObjectDelete(0, pattern_prefix + "BC");
  748.     ObjectCreate(0, pattern_prefix + "BC", OBJ_TREND, 0, b_time, pattern.B, c_time, pattern.C);
  749.     ObjectSetInteger(0, pattern_prefix + "BC", OBJPROP_COLOR, line_color);
  750.     ObjectSetInteger(0, pattern_prefix + "BC", OBJPROP_WIDTH, 2);
  751.     // CD线
  752.     ObjectDelete(0, pattern_prefix + "CD");
  753.     ObjectCreate(0, pattern_prefix + "CD", OBJ_TREND, 0, c_time, pattern.C, d_time, pattern.D);
  754.     ObjectSetInteger(0, pattern_prefix + "CD", OBJPROP_COLOR, line_color);
  755.     ObjectSetInteger(0, pattern_prefix + "CD", OBJPROP_WIDTH, 2);
  756.     // 对角线XB和AC
  757.     ObjectDelete(0, pattern_prefix + "XB");
  758.     ObjectCreate(0, pattern_prefix + "XB", OBJ_TREND, 0, x_time, pattern.X, b_time, pattern.B);
  759.     ObjectSetInteger(0, pattern_prefix + "XB", OBJPROP_COLOR, line_color);
  760.     ObjectSetInteger(0, pattern_prefix + "XB", OBJPROP_STYLE, STYLE_DOT);
  761.     ObjectDelete(0, pattern_prefix + "AC");
  762.     ObjectCreate(0, pattern_prefix + "AC", OBJ_TREND, 0, a_time, pattern.A, c_time, pattern.C);
  763.     ObjectSetInteger(0, pattern_prefix + "AC", OBJPROP_COLOR, line_color);
  764.     ObjectSetInteger(0, pattern_prefix + "AC", OBJPROP_STYLE, STYLE_DOT);
  765.     // 绘制PRZ区域
  766.     ObjectDelete(0, pattern_prefix + "PRZ");
  767.     ObjectCreate(0, pattern_prefix + "PRZ", OBJ_RECTANGLE, 0,
  768.                 d_time, pattern.prz_low, TimeCurrent() + 3600, pattern.prz_high);
  769.     ObjectSetInteger(0, pattern_prefix + "PRZ", OBJPROP_COLOR, clrYellow);
  770.     ObjectSetInteger(0, pattern_prefix + "PRZ", OBJPROP_STYLE, STYLE_SOLID);
  771.     ObjectSetInteger(0, pattern_prefix + "PRZ", OBJPROP_FILL, true);
  772.     ObjectSetInteger(0, pattern_prefix + "PRZ", OBJPROP_BACK, true);
  773.     // 添加文本标签
  774.     string pattern_name = GetPatternName(pattern.pattern_type);
  775.     string label_text = pattern_name + (pattern.is_bullish ? " 看涨" : " 看跌") +
  776.                        " 质量: " + DoubleToString(pattern.pattern_quality, 2);
  777.     ObjectDelete(0, pattern_prefix + "Label");
  778.     ObjectCreate(0, pattern_prefix + "Label", OBJ_TEXT, 0, d_time, pattern.D);
  779.     ObjectSetString(0, pattern_prefix + "Label", OBJPROP_TEXT, label_text);
  780.     ObjectSetInteger(0, pattern_prefix + "Label", OBJPROP_COLOR, line_color);
  781.     ObjectSetInteger(0, pattern_prefix + "Label", OBJPROP_FONTSIZE, 8);
  782. }
  783. //+------------------------------------------------------------------+
  784. //| 专家反初始化函数                                                     |
  785. //+------------------------------------------------------------------+
  786. void OnDeinit(const int reason)
  787. {
  788.     // 释放指标句柄
  789.     if(g_rsi_handle != INVALID_HANDLE) {
  790.         IndicatorRelease(g_rsi_handle);
  791.     }
  792.     // 清理图表对象
  793.     ObjectsDeleteAll(0, "Harmonic_");
  794.     Print("和谐形态策略 EA 已停止,原因代码: ", reason);
  795. }
复制代码
举报

评论 使用道具

精彩评论1

cobra
DD
| 发表于 5 小时前 | 显示全部楼层
和谐形态交易策略,直接上源码啊,楼主给力
举报

点赞 评论 使用道具

发新帖
EA交易
您需要登录后才可以评论 登录 | 立即注册

简体中文
繁體中文
English(英语)
日本語(日语)
Deutsch(德语)
Русский язык(俄语)
بالعربية(阿拉伯语)
Türkçe(土耳其语)
Português(葡萄牙语)
ภาษาไทย(泰国语)
한어(朝鲜语/韩语)
Français(法语)