MQL5: Validación :-( Ya me he devanado los sesos para saber qué es y cómo se soluciona. - página 5

 
//+-----------------------------------------------------------------------------------------------+
//| Функция закрывает позицию Sell                                                                |
//+-----------------------------------------------------------------------------------------------+
void CloseSell(void)
{
   if(trd.PositionClose(sell.ticket))
   {
      /*Print(STR_TIME,"Закрыта позиция Sell, тикет: ",sell.ticket,
                     ", об: ",DoubleToString(sell.volume,2),
                     ", цо: ",DoubleToString(sell.openPrice,symb.Digits()),
                     ", сл: ",DoubleToString(sell.stopLoss,symb.Digits()),
                     ", тп: ",DoubleToString(sell.takeProfit,symb.Digits()));*/
                     
      Print(STR_TIME,"Sell position closed, ticket: ",sell.ticket,
                     ", vl: ",DoubleToString(sell.volume,2),
                     ", op: ",DoubleToString(sell.openPrice,symb.Digits()),
                     ", sl: ",DoubleToString(sell.stopLoss,symb.Digits()),
                     ", tp: ",DoubleToString(sell.takeProfit,symb.Digits()));
      
      ZeroMemory(sell);
      line.Attach(0,"Sell SL",0,1);
      line.Delete();
      line.Attach(0,"Sell TP",0,1);
      line.Delete();
      fiboDn.Delete();
 
Andrey Minaev:

Necesito cerrar una posición de COMPRA.

 
//+-----------------------------------------------------------------------------------------------+
//| Функция закрывает позицию Buy                                                                 |
//+-----------------------------------------------------------------------------------------------+
void CloseBuy(void)
{
   if(trd.PositionClose(buy.ticket))
   {
      /*Print(STR_TIME,"Закрыта позиция Buy, тикет: ",buy.ticket,
                     ", об: ",DoubleToString(buy.volume,2),
                     ", цо: ",DoubleToString(buy.openPrice,symb.Digits()),
                     ", сл: ",DoubleToString(buy.stopLoss,symb.Digits()),
                     ", тп: ",DoubleToString(buy.takeProfit,symb.Digits()));*/
                     
      Print(STR_TIME,"Buy position closed, ticket: ",buy.ticket,
                     ", vl: ",DoubleToString(buy.volume,2),
                     ", op: ",DoubleToString(buy.openPrice,symb.Digits()),
                     ", sl: ",DoubleToString(buy.stopLoss,symb.Digits()),
                     ", tp: ",DoubleToString(buy.takeProfit,symb.Digits()));
      
      
      ZeroMemory(buy);
      line.Attach(0,"Buy SL",0,1);
      line.Delete();
      line.Attach(0,"Buy TP",0,1);
      line.Delete();
      fiboUp.Delete();
 
Andrey Minaev:

Supuesto: en el código anterior se calcula incorrectamente el volumen (o más bien se comprueba incorrectamente la posibilidad de abrir con este volumen) - se utiliza el margen libre TOTAL, en lugar del margen libre después de abrir una posición. También debe comprobar de antemano lo que se establece en m_symbol.LotsLimit()

Совершение сделок - Торговые операции - Справка по MetaTrader 5
Совершение сделок - Торговые операции - Справка по MetaTrader 5
  • www.metatrader5.com
Торговая деятельность в платформе связана с формированием и отсылкой рыночных и отложенных ордеров для исполнения брокером, а также с управлением текущими позициями путем их модификации или закрытия. Платформа позволяет удобно просматривать торговую историю на счете, настраивать оповещения о событиях на рынке и многое другое. Открытие позиций...
 
//+-----------------------------------------------------------------------------------------------+
//| Функция рассчитывает объем позиции                                                            |
//+-----------------------------------------------------------------------------------------------+
double CalculateVolume(ENUM_ORDER_TYPE type)
{
   double volume=0;
   
   double size=cndl.high-cndl.low;
   double sl=(size*inpStopLoss*0.01)/symb.Point();
   double risk=AccountInfoDouble(ACCOUNT_BALANCE)*inpRisk*0.01;
   
   if(sl==0 || symb.TickValue()==0)
      return 0;
   
   volume=(risk/sl)/symb.TickValue();
   
   if(inpMaxVolume>0 && inpMaxVolume<volume)
   {
      volume=inpMaxVolume;
      //Print(STR_TIME,"Установлен максимальный объем установленный в настройках");
      //Print(STR_TIME,"The maximum volume set in the settings is set");
   }
   
   double minVolume=symb.LotsMin();
   double maxVolume=symb.LotsMax();
   
   if(volume<minVolume)
   {
      volume=minVolume;
      //Print(STR_TIME,"Установлен минимальный объем допустимый брокером");
      //Print(STR_TIME,"The minimum volume allowed by the broker is set");
   }
   if(volume>maxVolume)
   {
      volume=maxVolume;
      //Print(STR_TIME,"Установлен максимальный объем допустимый брокером");
      //Print(STR_TIME,"The maximum volume allowed by the broker is set");
   }
   double mVolume=symb.LotsLimit();
   double tVolume=buy.volume+sell.volume;

   if(mVolume>0 && mVolume-tVolume-volume<=0)
      return 0;
   
   if(!CheckMoneyForTrade(volume,type))
      return 0;
   
   return NormalizeDouble(volume,DigitsLots());
}

Aquí utilizado antes, también los mismos errores, en la parte inferior comprueba el límite.

 

He creado especialmente un EA de prueba, este EA se somete a la validación.

//+------------------------------------------------------------------+
//|                                                         Test.mq5 |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

#include <Trade\Trade.mqh>
CTrade trd;

input double inpVolume=0.01234;

bool allowOpen;
bool allowClose;
ulong posTicket;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(void)
{
   return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(void)
{
   if(CheckNewCandle())
   {
      if(PositionSelect(_Symbol))
         allowClose=true;
      
      allowOpen=true;
   }
   
   if(allowClose)
      ClosePosition();
   
   if(allowOpen && !allowClose)
      OpenPosition();
}
//+------------------------------------------------------------------+
bool CheckNewCandle(void)
{
   static datetime prevTime=0;
          datetime currTime=iTime(_Symbol,PERIOD_CURRENT,0);
   
   if(prevTime!=currTime)
   {
      prevTime=currTime;
      return true;
   }
   return false;
}
//+------------------------------------------------------------------+
void ClosePosition(void)
{
   if(trd.PositionClose(posTicket))
   {
      allowClose=false;
      posTicket=0;
   }
}
//+------------------------------------------------------------------+
void OpenPosition(void)
{
   double volume=inpVolume;
   volume=NormalizeDouble(volume,DigitsLots());
   volume=CheckVolumeValue(volume);
   if(!CheckMoneyForTrade(_Symbol,volume,ORDER_TYPE_BUY))
   {
      allowOpen=false;
      return;
   }
   
   if(trd.Buy(volume))
   {
      allowOpen=false;
      posTicket=trd.ResultOrder();
   }
}
//+------------------------------------------------------------------+
bool CheckMoneyForTrade(string symb,double lots,ENUM_ORDER_TYPE type)
  {
//--- получим цену открытия
   MqlTick mqltick;
   SymbolInfoTick(symb,mqltick);
   double price=mqltick.ask;
   if(type==ORDER_TYPE_SELL)
      price=mqltick.bid;
//--- значения необходимой и свободной маржи
   double margin,free_margin=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
   //--- вызовем функцию проверки
   if(!OrderCalcMargin(type,symb,lots,price,margin))
     {
      //--- что-то пошло не так, сообщим и вернем false
      Print("Error in ",__FUNCTION__," code=",GetLastError());
      return(false);
     }
   //--- если не хватает средств на проведение операции
   if(margin>free_margin)
     {
      //--- сообщим об ошибке и вернем false
      Print("Not enough money for ",EnumToString(type)," ",lots," ",symb," Error code=",GetLastError());
      return(false);
     }
//--- проверка прошла успешно
   return(true);
  }
//+------------------------------------------------------------------+
double CheckVolumeValue(double volume)
  {
//--- минимально допустимый объем для торговых операций
   double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
   if(volume<min_volume)
     {
      PrintFormat("SYMBOL_VOLUME_MIN=%.2f",min_volume);
      volume=min_volume;
     }

//--- максимально допустимый объем для торговых операций
   double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
   if(volume>max_volume)
     {
      PrintFormat("SYMBOL_VOLUME_MAX=%.2f",max_volume);
      volume=max_volume;
     }

//--- получим минимальную градацию объема
   double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);

   int ratio=(int)MathRound(volume/volume_step);
   if(MathAbs(ratio*volume_step-volume)>0.0000001)
     {
      PrintFormat("SYMBOL_VOLUME_STEP=%.2f, %.2f",
                               volume_step,ratio*volume_step);
                               volume=ratio*volume_step;
     }
   return volume;
  }
//+------------------------------------------------------------------+  
int DigitsLots(void) 
{
   return (int)(MathLog(1.0/SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP))/MathLog(10.0));
}
//+------------------------------------------------------------------+

Hago las mismas comprobaciones para el EA deseado, y hay errores.

 
Andrey Minaev:

He creado especialmente un EA de prueba, este EA se somete a la validación.

Hago las mismas comprobaciones para el EA deseado, ahí hay errores.

No estás leyendo nada: ¿por qué utilizas TODO el margen libre, en lugar del margen libre después de abrir una posición?

En definitiva, leer y releer el artículo.


Añadido: Acabo de comprobar mi último código - en la función de Señales de Trading he añadido a propósito un coeficiente - para involucrar a LotCheck

//+------------------------------------------------------------------+
//| Search trading signals                                           |
//+------------------------------------------------------------------+
bool SearchTradingSignals(void)
  {
   double fast[],slow[];
   MqlRates rates[];
   ArraySetAsSeries(fast,true);
   ArraySetAsSeries(slow,true);
   ArraySetAsSeries(rates,true);
   int start_pos=0,count=6;
   string name=Inp_MA_Symbol;
   if(!iGetArray(handle_iMA_Fast,0,start_pos,count,fast) ||
      !iGetArray(handle_iMA_Slow,0,start_pos,count,slow) ||
      CopyRates(name,Inp_MA_period,start_pos,count,rates)!=count)
     {
      return(false);
     }
   int size_need_position=ArraySize(SPosition);
   if(fast[m_bar_current+1]<slow[m_bar_current+1] &&fast[m_bar_current]>slow[m_bar_current])
      if(fast[m_bar_current]-slow[m_bar_current]>=m_min_intersections_height)
        {
         if(m_prev_bars==m_last_deal_in) // on one bar - only one deal
            return(true);
         if(!InpReverse)
           {
            ArrayResize(SPosition,size_need_position+1);
            SPosition[size_need_position].pos_type=POSITION_TYPE_BUY;
            SPosition[size_need_position].lot_coefficient=1.087;
            if(InpPrintLog)
               Print(__FILE__," ",__FUNCTION__,", OK: ","Signal BUY");
            return(true);
           }
         else
           {
            ArrayResize(SPosition,size_need_position+1);
            SPosition[size_need_position].pos_type=POSITION_TYPE_SELL;
            SPosition[size_need_position].lot_coefficient=1.087;
            if(InpPrintLog)
               Print(__FILE__," ",__FUNCTION__,", OK: ","Signal SELL");
            return(true);
           }
        }
   if(fast[m_bar_current+1]>slow[m_bar_current+1] &&fast[m_bar_current]<slow[m_bar_current])
      if(slow[m_bar_current]-fast[m_bar_current]>=m_min_intersections_height)
        {
         if(m_prev_bars==m_last_deal_in) // on one bar - only one deal
            return(true);
         if(!InpReverse)
           {
            ArrayResize(SPosition,size_need_position+1);
            SPosition[size_need_position].pos_type=POSITION_TYPE_SELL;
            SPosition[size_need_position].lot_coefficient=1.087;
            if(InpPrintLog)
               Print(__FILE__," ",__FUNCTION__,", OK: ","Signal SELL");
            return(true);
           }
         else
           {
            ArrayResize(SPosition,size_need_position+1);
            SPosition[size_need_position].pos_type=POSITION_TYPE_BUY;
            SPosition[size_need_position].lot_coefficient=1.087;
            if(InpPrintLog)
               Print(__FILE__," ",__FUNCTION__,", OK: ","Signal BUY");
            return(true);
           }
        }
//---
   return(true);
  }

El Asesor Experto ha pasado la validación con una explosión.

 
Dónde leer sobre estos errores y qué son en general.
 

.

No está claro.

 
Andrey Minaev:

.

No está claro.

Dice: archivo de registro enorme. No cabe en el disco, por lo que se interrumpen las pruebas. Utiliza el traductor.