不开仓不知道怎么回事

 
//+------------------------------------------------------------------+
//|                                                  123RulePro.mq5 |
//|                        ForexHelper.AI 增强版123法则策略           |
//|                                     Last Update: 2024-06-15      |
//+------------------------------------------------------------------+
#property copyright "ForexHelper.AI"
#property version   "3.3"
#property strict

//--- 输入参数
input double   RiskPerTrade     = 0.01;       // 单笔风险比例(0.01=1%)
input int      ATRPeriod        = 18;         // ATR周期(14-20)
input double   RewardRatio      = 3.5;        // 最小盈亏比(3:1-5:1)
input int      MaxDailyRisk     = 2;          // 最大单日风险(%)
input int      TradingStartHour = 2;          // 开始交易小时(GMT)
input int      TradingEndHour   = 20;         // 结束交易小时(GMT)
input bool     EnableTrendFilter= true;       // 启用趋势过滤
input ENUM_TIMEFRAMES TrendTF   = PERIOD_H4;  // 趋势时间框架
input double   ADXThreshold     = 18.0;       // ADX趋势强度阈值
input int      MaxSpread        = 30;         // 最大允许点差

//--- 全局变量
int handleATR, handleADX, handleMATrend;
double atrBuffer[], adxBuffer[], maTrendBuffer[];
datetime lastTradeTime;

//+------------------------------------------------------------------+
//| 初始化函数                                                      |
//+------------------------------------------------------------------+
int OnInit()
{
   handleATR = iATR(_Symbol, _Period, ATRPeriod);
   handleADX = iADX(_Symbol, TrendTF, 14);
   handleMATrend = iMA(_Symbol, TrendTF, 50, 0, MODE_SMA, PRICE_CLOSE);
   
   ArraySetAsSeries(atrBuffer, true);
   ArraySetAsSeries(adxBuffer, true);
   ArraySetAsSeries(maTrendBuffer, true);
   
   if(RiskPerTrade > 5) Alert("风险比例过高!建议不超过5%");
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| 主执行函数                                                     |
//+------------------------------------------------------------------+
void OnTick()
{
   if(!IsNewBar() || !IsTradingTime() || !VerifyMarketCondition()) return;

   if(CopyBuffer(handleATR, 0, 0, 3, atrBuffer) < 3) return;
   if(CopyBuffer(handleADX, 0, 0, 2, adxBuffer) < 2) return;
   if(CopyBuffer(handleMATrend, 0, 0, 2, maTrendBuffer) < 2) return;

   double atrValue = NormalizeDouble(atrBuffer[0], _Digits);
   double currentADX = adxBuffer[1];
   bool trendUp = maTrendBuffer[0] > maTrendBuffer[1];
   
   int signal = Check123Pattern(currentADX, trendUp, atrValue);
   if(signal == 0) return;

   if(GetDailyRisk() >= MaxDailyRisk) {
      Comment("达到单日最大风险限制!");
      return;
   }
   
   MqlTick last_tick;
   SymbolInfoTick(_Symbol, last_tick);
   
   double price = (signal == 1) ? last_tick.ask : last_tick.bid;
   double sl = CalculateSL(signal, price, atrValue);
   double tp = (signal == 1) ? price + (price - sl)*RewardRatio 
                            : price - (sl - price)*RewardRatio;
   
   double lotSize = CalculateLotSize(price, sl);
   if(lotSize <= 0) return;

   SmartOrderSend(signal, lotSize, sl, tp);
   lastTradeTime = TimeCurrent();
}

//+------------------------------------------------------------------+
//| 增强版123法则信号检测                                          |
//+------------------------------------------------------------------+
int Check123Pattern(double adxValue, bool trendUp, double atr)
{
   double high1 = iHigh(_Symbol, _Period, 1);
   double high2 = iHigh(_Symbol, _Period, 2);
   double low1 = iLow(_Symbol, _Period, 1);
   double low2 = iLow(_Symbol, _Period, 2);
   double close0 = iClose(_Symbol, _Period, 0);
   double close1 = iClose(_Symbol, _Period, 1);

   if(EnableTrendFilter && adxValue < ADXThreshold) 
      return 0;

   if(trendUp) 
   {
      if(low2 < low1 && high1 > high2)
         if(close1 > (high1 + low1)*0.6)
            if(close0 > high1 + atr*0.3)
               return 1;
   }
   else 
   {
      if(high2 > high1 && low1 < low2)
         if(close1 < (high1 + low1)*0.4)
            if(close0 < low1 - atr*0.3)
               return -1;
   }
   return 0;
}

//+------------------------------------------------------------------+
//| 智能订单发送函数                                                |
//+------------------------------------------------------------------+
void SmartOrderSend(int signal, double lots, double sl, double tp)
{
   MqlTradeRequest request;
   ZeroMemory(request);
   MqlTradeResult result;
   
   request.action = TRADE_ACTION_DEAL;
   request.symbol = _Symbol;
   request.volume = NormalizeLotSize(lots);
   request.type = (signal == 1) ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;
   request.deviation = 50;
   request.type_filling = ORDER_FILLING_FOK;

   for(int i=0; i<3; i++) 
   {
      MqlTick last_tick;
      if(!SymbolInfoTick(_Symbol, last_tick)) 
      {
         Print("获取报价失败!");
         return;
      }
      
      // 更新价格和订单参数
      request.price = (signal == 1) ? last_tick.ask : last_tick.bid;
      request.sl = sl;
      request.tp = tp;
      
      // 检查价格偏差(5点内)
      double currentPrice = (signal == 1) ? last_tick.ask : last_tick.bid;
      double priceDiff = MathAbs(request.price - currentPrice) / _Point;
      if(priceDiff > 5) 
      {
         Print("价格偏差过大:", priceDiff, "点,取消交易");
         return;
      }
      
      // 发送订单
      bool sent = OrderSend(request, result);
      if(sent) 
      {
         if(result.retcode == TRADE_RETCODE_DONE) 
         {
            Print("订单执行成功,成交价:", result.price);
            break;
         }
         else 
         {
            Print("订单发送失败,错误代码:", result.retcode);
            Sleep(500);
         }
      }
      else 
      {
         Print("OrderSend()失败,错误代码:", GetLastError());
         Sleep(500);
      }
   }
}

//+------------------------------------------------------------------+
//| 动态止损计算                                                   |
//+------------------------------------------------------------------+
double CalculateSL(int signal, double entryPrice, double atr)
{
   double baseSL = (signal == 1) ? iLow(_Symbol, _Period, 2) 
                                : iHigh(_Symbol, _Period, 2);
   double atrSL = (signal == 1) ? entryPrice - 1.5*atr 
                               : entryPrice + 1.5*atr;
   return (signal == 1) ? MathMin(baseSL, atrSL) : MathMax(baseSL, atrSL);
}

//+------------------------------------------------------------------+
//| 精确手数计算                                                   |
//+------------------------------------------------------------------+
double CalculateLotSize(double entry, double sl)
{
   double riskAmount = AccountInfoDouble(ACCOUNT_EQUITY) * RiskPerTrade/100;
   double riskPoints = MathAbs(entry - sl)/_Point;
   double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   
   if(riskPoints == 0 || tickValue == 0) return 0;
   
   return NormalizeLotSize(riskAmount / (riskPoints * tickValue));
}

//+------------------------------------------------------------------+
//|                       辅助函数实现区                            |
//+------------------------------------------------------------------+
bool IsNewBar()
{
   static datetime lastBar=0;
   datetime currentBar=(datetime)SeriesInfoInteger(_Symbol,_Period,SERIES_LASTBAR_DATE);
   if(lastBar != currentBar) {
      lastBar = currentBar;
      return true;
   }
   return false;
}

bool IsTradingTime()
{
   MqlDateTime currentTime;
   TimeCurrent(currentTime);
   return (currentTime.hour >= TradingStartHour) && (currentTime.hour < TradingEndHour);
}

bool VerifyMarketCondition()
{
   int currentSpread=(int)SymbolInfoInteger(_Symbol,SYMBOL_SPREAD);
   if(currentSpread > MaxSpread) return false;
   return SeriesInfoInteger(_Symbol,_Period,SERIES_SERVER_FIRSTDATE) != 0;
}

double GetDailyRisk()
{
   MqlDateTime todayStart;
   TimeCurrent(todayStart);          // 获取当前时间
   todayStart.hour = 0;
   todayStart.min = 0;
   todayStart.sec = 0;
   datetime startTime = StructToTime(todayStart);
   
   double dailyProfit=0;
   HistorySelect(startTime, TimeCurrent());
   
   int totalDeals=(int)HistoryDealsTotal();
   for(int i=0;i<totalDeals;i++) 
   {
      ulong ticket=HistoryDealGetTicket(i);
      if(HistoryDealGetString(ticket,DEAL_SYMBOL)==_Symbol)
        dailyProfit+=HistoryDealGetDouble(ticket,DEAL_PROFIT);
   }
   return (MathAbs(dailyProfit)/AccountInfoDouble(ACCOUNT_EQUITY))*100;
}

double NormalizeLotSize(double lots)
{
   double min=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   double max=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
   double step=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
   
   lots = MathRound(lots / step) * step;
   lots = MathMax(min, MathMin(max, lots));
   return NormalizeDouble(lots, 2);
}
 
【新手必看】如何防止机器人误判:讨论代码时请使用代码表述功能
https://www.mql5.com/zh/forum/448896
【新手必看】如何防止机器人误判:讨论代码时请使用代码表述功能
【新手必看】如何防止机器人误判:讨论代码时请使用代码表述功能
  • 2023.06.13
  • Sky All
  • www.mql5.com
大家好,我是官网版主。 官网内部有机器人辅助管理,目的是自动下架一些有误导性的内容。 内容过长,或同一个IP多次注册,容易导致机器人误判,而被无辜删帖。 如果您被无故删帖,我们对这种体验感到万分抱歉。 为了防止机器人误判,请在讨论代码的时候使用代码表述功能...