Ошибки, баги, вопросы - страница 3143

 
Wizard #:
Добрый день! Нужна ли в коде строка PositionSelectByTicket... Если нужна, то как корректнее записать внутри нее тикет, через PositionGetTicket(i) или оставить PositionGetInteger(POSITION_TICKET) ? Заранее благодарю!

Не сочтите за грубость… А в документации разве не чётко сказано

Функция возвращает тикет позиции по индексу в списке открытых позиций и автоматически выбирает эту позицию для дальнейшей работы с ней


Если позиция уже выбрана, так зачем её повторно выбирать функцией PositionSelectByTicket

 
Alexey Viktorov #:

Не сочтите за грубость… А в документации разве не чётко сказано

Если позиция уже выбрана, так зачем её повторно выбирать функцией PositionSelectByTicket

Благодарю за ответ! Задался вопросом, потому что заглянув в библиотеку <Trade/Trade.mqh>, в функции PositionClose(const ulong ticket,const ulong deviation) также используется PositionSelectByTicket. А саму функцию PositionClose( const ulong ticket,const ulong deviation )  кодеры часто используют в сочетании с циклом for(int i = PositionsTotal()-1; i >= 0; i--) , перебирая все позиции. И думаю, не используется ли где лишнее.
 
Wizard #:
Добрый день! Нужна ли в коде строка PositionSelectByTicket... Если нужна, то как корректнее записать внутри нее тикет, через PositionGetTicket(i) или оставить PositionGetInteger(POSITION_TICKET) ? Заранее благодарю!
int IsPositions()
{
   int pos = 0;     
   
   int total = PositionsTotal();
   for(int i = total-1; i >= 0; i--)
   {
      if(!PositionGetTicket(i))
         continue;        
          
      if(PositionGetString(POSITION_SYMBOL) == Symbol_T && PositionGetInteger(POSITION_MAGIC) == EXPERT_MAGIC)
         pos = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? 1 : (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) ? -1 : 0;
   }
   
   return(pos);
}
 
Roman #:
Благодарю! Значит PositionGetTicket(i) будет достаточно и PositionSelectByTicket не понадобится.
 
Wizard #:
Благодарю за ответ! Задался вопросом, потому что заглянув в библиотеку <Trade/Trade.mqh>, в функции PositionClose(const ulong ticket,const ulong deviation) также используется PositionSelectByTicket. А саму функцию PositionClose( const ulong ticket,const ulong deviation )  кодеры часто используют в сочетании с циклом for(int i = PositionsTotal()-1; i >= 0; i--) , перебирая все позиции. И думаю, не используется ли где лишнее.

В библиотеке функция PositionClose(const ulong ticket,const ulong deviation) получает тикет закрываемой позиции, но никто не знает как был получен тикет и существует-ли позиция.

Следовательно PositionSelectByTicket по бо́льшей мере играет роль проверки есть-ли чего закрывать. И почему вы решили, что часто закрывают все позиции в цикле? Совсем не обязательно…

 
Alexey Viktorov #:

В библиотеке функция PositionClose(const ulong ticket,const ulong deviation) получает тикет закрываемой позиции, но никто не знает как был получен тикет и существует-ли позиция.

Следовательно PositionSelectByTicket по бо́льшей мере играет роль проверки есть-ли чего закрывать. И почему вы решили, что часто закрывают все позиции в цикле? Совсем не обязательно…

Да, теперь все понял. У меня недавно один советник получился, писал по вашему примеру (со средними) с одного форума, совмещая с кодом Тимура Машнина. Теперь решил немного изменить условия там, переписав, заменяя все на системные функции, без библиотек. Если с простым PositionSelect все было предельно просто, одна позиция - один выбор, то с циклом тут конечно нужно больше соображений и логики прилагать.
 

Здравствуйте

Помогите пожалуйста

с кодом

сделал индикатор в тестере работает правильно

ставлю на график показывает неправильно

не могу понять причину почему так

//+------------------------------------------------------------------+
//|                                                        Oscil.mq5 |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property  indicator_buffers 5
#property indicator_plots   5

#property  indicator_color1  clrNONE
#property  indicator_color2  clrRoyalBlue
#property  indicator_color3  clrPink
#property  indicator_color4  clrAqua
#property  indicator_color5  clrYellow

#property  indicator_width1 1
#property  indicator_width2 5
#property  indicator_width3 5
#property  indicator_width4 5
#property  indicator_width5 5

double MainLine[];
double UpLine[];
double DnLine[];
double muls[];
double x,y,z;
double price;
double mulSum=0;
double Pi   = 3.1415926535;
bool LastUp = false;
bool GoUp   = false;
input bool otl    = false;
/***********Range***************/
int    Length             = 3;
int    MajorRangeStrength = 4;


double MajorRangeBuy[];
double MajorRangeSell[];


double RangePrice  = 0.0,
       SweepB      = 0.0;
int    Switch2     = 0,
         SwitchB     = 0;
double Price2BuyA  = 0.0;
int    Price2BuyB  = 1.0;
double Price2SellA = 0.0;
int    Price2SellB = 0.0;
bool   BuySwitchB  = false,
       SellSwitchB = false;
       
int hendlMA_1;
double MA_1[];

int hendlMA_2;
double MA_2[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MainLine,INDICATOR_DATA);
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0);
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_HISTOGRAM); 
   ArraySetAsSeries(MainLine, true);
   
   SetIndexBuffer(1,UpLine,INDICATOR_DATA);
   PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0);
   PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_HISTOGRAM); 
   ArraySetAsSeries(UpLine, true);
   
   SetIndexBuffer(2,DnLine,INDICATOR_DATA);
   PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, 0);
   PlotIndexSetInteger(2,PLOT_DRAW_TYPE,DRAW_HISTOGRAM); 
   ArraySetAsSeries(DnLine, true);
   
   SetIndexBuffer(3,MajorRangeBuy,INDICATOR_DATA);
   PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, 0);
   PlotIndexSetInteger(3,PLOT_DRAW_TYPE,DRAW_HISTOGRAM); 
   ArraySetAsSeries(MajorRangeBuy, true);
   
   SetIndexBuffer(4,MajorRangeSell,INDICATOR_DATA);
   PlotIndexSetDouble(4, PLOT_EMPTY_VALUE, 0);
   PlotIndexSetInteger(4,PLOT_DRAW_TYPE,DRAW_HISTOGRAM); 
   ArraySetAsSeries(MajorRangeSell, true);
   
   hendlMA_1=iMA(Symbol(),0,1,0,MODE_LWMA,PRICE_CLOSE);
   ArraySetAsSeries(MA_1,true);
   
   hendlMA_2=iMA(Symbol(),0,1,0,MODE_SMMA,PRICE_CLOSE);
   ArraySetAsSeries(MA_2,true);
   
   ArrayResize(muls, 99);
   
   mulSum = 0;
   
   for (int i0 = 0; i0 < 98; i0++) {//повторяем в цикле 98 раз
      if (i0 <= 18) y = 1.0 * i0 / 18; //если это первые 18 повторений
      else y = (i0 - 18) * 7.0 / 79.0 + 1.0; //иначе
      
      x = MathCos(Pi * y);
      z = 1.0 / (3.0 * Pi * y + 1.0);
      if (y <= 0.5) z = 1;
      
      muls[i0] = z * x;
      mulSum += muls[i0];
   }
   if(otl)Print(" Распределение создано muls[20]=",muls[20]);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
  if (PeriodSeconds() <60*60 || PeriodSeconds() >10080*60) return(0);
   int depth=0;

   int l_ind_counted_8 = prev_calculated; //Возвращает количество баров, не измененных после последнего вызова индикатора.
   
   int bars=Bars(Symbol(),PERIOD_CURRENT);
   if (l_ind_counted_8 < 0) return (0);
   if (l_ind_counted_8 == 0)
      {
         depth = bars - 98;
         for(int a=0;a<bars;a++)
            {
               MainLine[a] = 0;
               UpLine[a] = 0;
               DnLine[a] = 0;
               MajorRangeBuy[a]=0;
               MajorRangeSell[a]=0;
            }
      }
   if (l_ind_counted_8 > 0)  depth = bars - l_ind_counted_8;
   if(otl)Print(" количество баров, не измененных после последнего вызова индикатора= ",l_ind_counted_8,"  Количество баров на текущем графике Bars=",bars,"  depth= ",depth);
   if (l_ind_counted_8 < 1) {
      for (int i2 = 1; i2 < 100; i2++) {
         MainLine[bars - i2] = 0;
         UpLine[bars - i2] = 0;
         DnLine[bars - i2] = 0;
      }
   }
   
   for (int i1 = depth; i1 >= 0; i1--) 
   {
      price = 0;
          
          CopyBuffer(hendlMA_1,0,0,bars,MA_1);
          
      for (int i2 = 0; i2 <= 98; i2++) 
         {
            if(i2 + i1>=bars)break;
            price += muls[i2] * MA_1[i2 + i1];
         }
          
      if (mulSum > 0.0) MainLine[i1] = price / mulSum;

     GoUp=MainLine[i1 + 1] > MainLine[i1] ;
     
      if (GoUp) 
      {
         if (!LastUp) DnLine[i1+1] = MainLine[i1+1];
         DnLine[i1] = MainLine[i1];
         UpLine[i1] = 0;
      }
         else
      {
         if (LastUp) UpLine[i1+1] = MainLine[i1+1];
         UpLine[i1] = MainLine[i1];
         DnLine[i1] = 0;
      }
      LastUp=GoUp; 

   }//  for (int i1

 //  return (0);

/***************** Range **********************/

  int counted_bars=prev_calculated;
  if(otl)Print(" Range counted_bars = ", counted_bars);
   if(counted_bars<0) return(-1);
   int position=bars-counted_bars;
   if (position<0) position=0;
   if (position==0) position=1;
   int rnglength = 250;
   double range = 0.0, srange = 0.0;
   if(otl) Print(" position=",position);
   
   for (int pos = position; pos >=0; pos--)
   {/***************** MAIN Range **********************/
      srange = 0.0;
      int j = 0;
      for (int i=0;i<rnglength;i++)
      {
         j++;
         int posr = pos + i;
         if (posr >= bars) break; 
         srange = srange + (High(posr) - Low(posr));
      }
      range = srange / j * Length;
      int BarNumber = bars-pos; //??????????
      if (BarNumber < 0)  BarNumber = 0;
          
          CopyBuffer(hendlMA_2,0,0,bars,MA_2);
          //Print(bars," - ",pos);
      if(pos<bars)RangePrice = MA_2[pos];  //Moving Average MODE_SMMA
      else RangePrice = MA_2[pos-1];

      if (BarNumber == 1)
      {
         SweepB  = range *  MajorRangeStrength;
         Price2BuyA = RangePrice;
         Price2SellA = RangePrice;
      }     

      if (BarNumber > 1)
      {

         if (Switch2  >  - 1)//проверка цикла на покупку
         {
            if (RangePrice < Price2BuyA) //если средняя цена ниже
            {
if (BuySwitchB ) MajorRangeBuy [pos +BarNumber - Price2BuyB] = 0;                                                                //OUT
                           Price2BuyA = RangePrice;
               Price2BuyB = BarNumber;
               BuySwitchB = true;
            } 
            else if (RangePrice > Price2BuyA)
            {
                            SwitchB = BarNumber - Price2BuyB;
MajorRangeBuy [pos +SwitchB] = MainLine[pos + SwitchB]*1.0005;                                                                                                                          //OUT
                BuySwitchB = true;

                              if (RangePrice - MA_2[pos + SwitchB] >= SweepB && SwitchB >= 1)
                              {
                     Switch2 =  - 1;
                     Price2SellA = RangePrice;
                     Price2SellB = BarNumber;
                     SellSwitchB = false;
                     BuySwitchB = false;
               }
            }
         }
         if (Switch2  < 1)//проверка цикла на продажу
         {
            if (RangePrice  > Price2SellA )
            {
if (pos +BarNumber - Price2SellB<bars&&SellSwitchB ) MajorRangeSell [pos +BarNumber - Price2SellB] = 0;                                                         //OUT
                           Price2SellA = RangePrice;
               Price2SellB = BarNumber;
               SellSwitchB = true;
                    }
                       else if (RangePrice < Price2SellA)
                    {
               SwitchB = BarNumber - Price2SellB ;

         if(pos+ SwitchB<bars)MajorRangeSell[pos + SwitchB] =MainLine[pos + SwitchB]*1.0005;                                                                                                                             //OUT
                SellSwitchB = true;             
        
                              if (pos + SwitchB<bars&&MA_2[pos + SwitchB] - RangePrice >= SweepB && SwitchB >= 1)
                              {
                                     Switch2 = 1;
                     Price2BuyA = RangePrice;
                     Price2BuyB = BarNumber;
                     SellSwitchB = false;
                     BuySwitchB = false;
                                  }
            }
         }
      }

   //   MajorRangeSell[pos] = 0;
    //  MajorRangeBuy[pos]  = 0;  
    }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//========================================================================================
double High(int index)
{   
   if(index < 0) return(-1);
   double Arr[];
   ENUM_TIMEFRAMES timeframe=PERIOD_CURRENT;
   if(CopyHigh(Symbol(),timeframe, index, 1, Arr)>0) 
        return(Arr[0]);
   else return(-1);
}
//========================================================================================
double Low(int index)
{   
   if(index < 0) return(-1);
   double Arr[];
   ENUM_TIMEFRAMES timeframe=PERIOD_CURRENT;
   if(CopyLow(Symbol(),timeframe, index, 1, Arr)>0) 
        return(Arr[0]);
   else return(-1);
}
 

Что возвращается в структуру MqlTradeCheckResult?

В документации написано, что «Размер маржи необходимой для требуемой торговой операции».

Поле

Описание

retcode

Код возврата

balance

Значение баланса, которое будет после выполнения торговой операции

equity

Значение собственных средств, которое будет после выполнения торговой операции

profit

Значение плавающей прибыли, которое будет после выполнения торговой операции

margin

Размер маржи необходимый для требуемой торговой операции

margin_free

Размер свободных собственных средств, которые останутся после выполнения требуемой торговой операции

margin_level

Уровень маржи, который установится после выполнения  требуемой торговой операции

comment

Комментарий к коду ответа, описание ошибки


Но на самом деле получается размер суммарной маржи, текущей и плюс той, что будет взята после выполнения этой операции.

Вот скрипт

#include <Trade\Trade.mqh>
CTrade trade;
  MqlTradeRequest           my_request;
  MqlTradeCheckResult       my_check_result;
  MqlTick                   mqlTick;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
 {
  SymbolInfoTick(_Symbol, mqlTick);
  CheckOrder(0.01, ORDER_TYPE_SELL);
  Print(my_check_result.margin);
//---
  trade.PositionOpen(_Symbol, ORDER_TYPE_SELL, 0.01, mqlTick.bid, 0.0, 0.0);
//---
  CheckOrder(0.01, ORDER_TYPE_SELL);
  Print(my_check_result.margin);
 }/******************************************************************/

/********************************************************************\
||
\********************************************************************/
bool CheckOrder(double volume, ENUM_ORDER_TYPE order_type)
 {
  if(order_type != ORDER_TYPE_BUY && order_type != ORDER_TYPE_SELL)
    return false;
  ZeroMemory(my_request);
  ZeroMemory(my_check_result);
  bool checkOrder = false;
//--- setting my_request
  my_request.action = TRADE_ACTION_DEAL;
  my_request.symbol = _Symbol;
  my_request.volume = volume;
  my_request.type   = order_type;
  my_request.price  = order_type == ORDER_TYPE_BUY ? mqlTick.ask : mqlTick.bid;
  checkOrder = ::OrderCheck(my_request, my_check_result);
  if(my_check_result.retcode != 0)
    return(false);
//---
  return(true);
 }/******************************************************************/

и результат выполнения

2022.02.01 10:11:28.002 Test bag (EURUSD,H1)    2.25
2022.02.01 10:11:28.108 Test bag (EURUSD,H1)    4.5

Пока на счёте нет открытых позиций my_check_result.margin равен марже открытой позиции лотом 0.01, а когда на счёте уже есть позиция 0.01 то размер маржи уже за лот 0.02

Файлы:
Test_bag.mq5  5 kb
 
Alexey Viktorov #:

Но на самом деле получается размер суммарной маржи, текущей и плюс той, что будет взята после выполнения этой операции.

Верно.

MarginOpen = CheckResult.margin - ::AccountInfoDouble(ACCOUNT_MARGIN); // Маржа для открытия.
 
fxsaber #:

Верно.

Пусть будет так, но тогда в документации должно быть одинаково написано.

Если balans — Значение баланса, которое будет после выполнения торговой операции

то и margin — должно быть. Размер маржи, которое будет после выполнения торговой операции

Причина обращения: