自己写的一个EA大家自己拿去测试

| 发表于 前天 19:42 | 显示全部楼层 |复制链接
  1. //+------------------------------------------------------------------+
  2. //| 金手指 v7 稳定版                                                  |
  3. //| H1方向 + M5入场 + 缓冲止损 + 1:2半平 + 微利推保                    |
  4. //+------------------------------------------------------------------+
  5. #property version   "7.2"
  6. #property strict
  7. #include <Trade/Trade.mqh>
  8. CTrade trade;
  9. //==== 参数 ====
  10. input double LotSize            = 0.01;
  11. input int    MA_Period          = 20;
  12. input double RR_Ratio           = 2.0;
  13. input int    MagicNumber        = 888888;
  14. input int    MaxSpread          = 50;
  15. input int    Slippage           = 10;
  16. input double SL_Buffer          = 50;
  17. input double Trail_Profit_Level = 0.3;
  18. input bool   Use_ADX_Filter     = true;
  19. input int    ADX_Period         = 14;
  20. input double ADX_Level          = 25;
  21. //==== 指标句柄 ====
  22. int hMA_H1 = INVALID_HANDLE;
  23. int hMA_M5 = INVALID_HANDLE;
  24. int hADX   = INVALID_HANDLE;
  25. //==== 新K线门控 ====
  26. datetime g_lastM5BarTime = 0;
  27. //+------------------------------------------------------------------+
  28. int OnInit()
  29. {
  30.    trade.SetExpertMagicNumber(MagicNumber);
  31.    trade.SetDeviationInPoints(Slippage);
  32.    hMA_H1 = iMA(_Symbol, PERIOD_H1, MA_Period, 0, MODE_SMA, PRICE_CLOSE);
  33.    hMA_M5 = iMA(_Symbol, PERIOD_M5, MA_Period, 0, MODE_SMA, PRICE_CLOSE);
  34.    hADX   = iADX(_Symbol, PERIOD_H1, ADX_Period);
  35.    if(hMA_H1 == INVALID_HANDLE || hMA_M5 == INVALID_HANDLE || (Use_ADX_Filter && hADX == INVALID_HANDLE))
  36.    {
  37.       Print("指标句柄创建失败");
  38.       return INIT_FAILED;
  39.    }
  40.    MqlRates r[];
  41.    ArraySetAsSeries(r, true);
  42.    if(CopyRates(_Symbol, PERIOD_M5, 0, 1, r) > 0)
  43.       g_lastM5BarTime = r[0].time;
  44.    Print("金手指 v7.2 初始化成功");
  45.    return INIT_SUCCEEDED;
  46. }
  47. //+------------------------------------------------------------------+
  48. void OnDeinit(const int reason)
  49. {
  50.    if(hMA_H1 != INVALID_HANDLE) IndicatorRelease(hMA_H1);
  51.    if(hMA_M5 != INVALID_HANDLE) IndicatorRelease(hMA_M5);
  52.    if(hADX   != INVALID_HANDLE) IndicatorRelease(hADX);
  53. }
  54. //+------------------------------------------------------------------+
  55. // 安全的K线数据获取:返回 true 表示成功取到
  56. bool GetOHLC(ENUM_TIMEFRAMES tf, int shift, MqlRates &out[])
  57. {
  58.    ArraySetAsSeries(out, true);
  59.    return (CopyRates(_Symbol, tf, shift, 1, out) > 0);
  60. }
  61. // 取单值指标缓冲
  62. bool GetIndicatorValue(int handle, double &value)
  63. {
  64.    double buf[1];
  65.    ArraySetAsSeries(buf, true);
  66.    if(CopyBuffer(handle, 0, 0, 1, buf) <= 0)
  67.       return false;
  68.    value = buf[0];
  69.    return true;
  70. }
  71. bool IsNewM5Bar()
  72. {
  73.    MqlRates r[];
  74.    if(!GetOHLC(PERIOD_M5, 0, r)) return false;
  75.    if(r[0].time != g_lastM5BarTime)
  76.    {
  77.       g_lastM5BarTime = r[0].time;
  78.       return true;
  79.    }
  80.    return false;
  81. }
  82. //+------------------------------------------------------------------+
  83. void OnTick()
  84. {
  85.    if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) return;
  86.    if(!MQLInfoInteger(MQL_TRADE_ALLOWED)) return;
  87.    long spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
  88.    if(spread > MaxSpread) return;
  89.    ManagePositions();
  90.    if(PositionsTotal() == 0 && IsNewM5Bar())
  91.       CheckOpen();
  92. }
  93. //+------------------------------------------------------------------+
  94. void CheckOpen()
  95. {
  96.    double maH1, maM5;
  97.    if(!GetIndicatorValue(hMA_H1, maH1)) return;
  98.    if(!GetIndicatorValue(hMA_M5, maM5)) return;
  99.    if(Use_ADX_Filter)
  100.    {
  101.       double adx;
  102.       if(!GetIndicatorValue(hADX, adx)) return;
  103.       if(adx < ADX_Level) return;
  104.    }
  105.    MqlRates h1[], m5[];
  106.    if(!GetOHLC(PERIOD_H1, 1, h1)) return;
  107.    if(!GetOHLC(PERIOD_M5, 1, m5)) return;
  108.    double h1_close = h1[0].close;
  109.    double m5_close = m5[0].close;
  110.    double vol = NormalizeLot(LotSize);
  111.    long stopsLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
  112.    double minDist = (double)stopsLevel * _Point;
  113.    // 多
  114.    if(h1_close > maH1 && m5_close > maM5)
  115.    {
  116.       double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
  117.       double sl  = h1[0].low - SL_Buffer * _Point;
  118.       if(ask - sl < minDist) sl = ask - minDist;
  119.       double risk = ask - sl;
  120.       double tp   = ask + risk * RR_Ratio;
  121.       trade.Buy(vol, _Symbol, ask, sl, tp, "JF_Long");
  122.       Print("开多 retcode=", trade.ResultRetcode());
  123.    }
  124.    // 空
  125.    else if(h1_close < maH1 && m5_close < maM5)
  126.    {
  127.       double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
  128.       double sl  = h1[0].high + SL_Buffer * _Point;
  129.       if(sl - bid < minDist) sl = bid + minDist;
  130.       double risk = sl - bid;
  131.       double tp   = bid - risk * RR_Ratio;
  132.       trade.Sell(vol, _Symbol, bid, sl, tp, "JF_Short");
  133.       Print("开空 retcode=", trade.ResultRetcode());
  134.    }
  135. }
  136. //+------------------------------------------------------------------+
  137. void ManagePositions()
  138. {
  139.    for(int i = PositionsTotal() - 1; i >= 0; i--)
  140.    {
  141.       ulong ticket = PositionGetTicket(i);
  142.       if(ticket == 0) continue;
  143.       if(!PositionSelectByTicket(ticket)) continue;
  144.       if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
  145.       if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
  146.       long   pos_type   = PositionGetInteger(POSITION_TYPE);
  147.       double open_price = PositionGetDouble(POSITION_PRICE_OPEN);
  148.       double sl_now     = PositionGetDouble(POSITION_SL);
  149.       double tp_now     = PositionGetDouble(POSITION_TP);
  150.       double vol_now    = PositionGetDouble(POSITION_VOLUME);
  151.       double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
  152.       double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
  153.       if(tp_now > 0)
  154.       {
  155.          bool hit = false;
  156.          if(pos_type == POSITION_TYPE_BUY  && ask >= tp_now) hit = true;
  157.          if(pos_type == POSITION_TYPE_SELL && bid <= tp_now) hit = true;
  158.          if(hit)
  159.          {
  160.             double half_vol = NormalizeLot(vol_now / 2.0);
  161.             double volMin = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
  162.             if(half_vol < volMin) half_vol = volMin;
  163.             double risk = (pos_type == POSITION_TYPE_BUY) ? (open_price - sl_now) : (sl_now - open_price);
  164.             double lock = risk * Trail_Profit_Level;
  165.             double new_sl = (pos_type == POSITION_TYPE_BUY) ? (open_price + lock) : (open_price - lock);
  166.             long stopsLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
  167.             double minDist = (double)stopsLevel * _Point;
  168.             if(pos_type == POSITION_TYPE_BUY  && (ask - new_sl) < minDist) new_sl = ask - minDist;
  169.             if(pos_type == POSITION_TYPE_SELL && (new_sl - bid) < minDist) new_sl = bid + minDist;
  170.             trade.PositionModify(ticket, new_sl, 0);
  171.             trade.PositionClosePartial(ticket, half_vol);
  172.             Print("1.5R达成,半平并推保");
  173.          }
  174.       }
  175.    }
  176. }
  177. //+------------------------------------------------------------------+
  178. double NormalizeLot(double lot)
  179. {
  180.    double vMin  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
  181.    double vMax  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
  182.    double vStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
  183.    lot = MathMax(lot, vMin);
  184.    lot = MathMin(lot, vMax);
  185.    if(vStep > 0) lot = MathRound(lot / vStep) * vStep;
  186.    return lot;
  187. }
  188. //+------------------------------------------------------------------+
复制代码
image.png
image.png
举报

评论 使用道具

精彩评论1

yb300300
D
| 发表于 前天 19:55 | 显示全部楼层
馬丁嗎?????能扛單邊嗎????單會多嗎???
举报

点赞 评论 使用道具

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