Вопросы от начинающих MQL5 MT5 MetaTrader 5 - страница 722

 

Доброе время суток,

Вопрос:

Подскажите пожалуйста, почему я не могу поставить отложенник на бай:

request.price =SymbolInfoDouble(Symbol(),SYMBOL_ASK)+(offset)*point;

при offset=1 выпадает ошибка:

 failed buy stop 0.10 AUDNZD.m at 1.03748 [Invalid price], т.е.маленький уровень цены (в моем случае)

 

Когда же при постановки сразу за ним же «ордера по исполнению»

request.price = SymbolInfoDouble(Symbol(), SYMBOL_ASK)

все нормально отрабатывает (т.е. ордер ставится):

order performed buy 0.10 at 1.03747 [#2 buy 0.10 AUDNZD.m at 1.03747]

 Почему не принимается запрос по отложенному ордеру (1.03748),  т.е. при 1.03747 – ставится, а при 1.03748 – маленькое значение? (ведь SYMBOL_ASK учитавает спред, а offset - отступ от текущей цены для установки ордера, в пунктах, увеличен на 1)

Но при offset=100: ордер отложенный BUY_STOP price = 1.03847 – уже работает


Спасибо.
 
Konstantin_78:

Доброе время суток,

Вопрос:

Подскажите пожалуйста, почему я не могу поставить отложенник на бай:

request.price =SymbolInfoDouble(Symbol(),SYMBOL_ASK)+(offset)*point;

при offset=1 выпадает ошибка:

 failed buy stop 0.10 AUDNZD.m at 1.03748 [Invalid price], т.е.маленький уровень цены (в моем случае)

 

Когда же при постановки сразу за ним же «ордера по исполнению»

request.price = SymbolInfoDouble(Symbol(), SYMBOL_ASK)

все нормально отрабатывает (т.е. ордер ставится):

order performed buy 0.10 at 1.03747 [#2 buy 0.10 AUDNZD.m at 1.03747]

 Почему не принимается запрос по отложенному ордеру (1.03748),  т.е. при 1.03747 – ставится, а при 1.03748 – маленькое значение?

Но при offset=100: ордер отложенный BUY_STOP price = 1.03847 – уже работает


Спасибо.

Вы же сами и ответили на свой вопрос.

Есть такой параметр stoplevel -- минимально необходимое расстояние от текущей цены до цены установки отложенного ордера -- для каждого инструмента своё значение и задаётся в торговых условиях 

 
Andrey F. Zelinsky:

Вы же сами и ответили на свой вопрос.

Есть такой параметр stoplevel -- минимально необходимое расстояние от текущей цены до цены установки отложенного ордера -- для каждого инструмента своё значение и задаётся в торговых условиях 

Тогда наверняка справедлива будет запись:

price =SymbolInfoDouble(Symbol(),SYMBOL_ASK)+SymbolInfoInteger(Symbol(),SYMBOL_TRADE_STOPS_LEVEL)*point 

хотя, если вы написали "...от текущей цены", то причем тут спред? Который входит в SYMBOL_ASK (ведь SYMBOL_ASK = цена открытия+спред).

 
Vladimir Karputov:

Я прикрепил пример, который поможет Вам...

 Понятно, пример помог. Спасибо.


 Теперь такой вопрос.

При увеличении лота в какой-то момент чуть не хватает свободных средств, а открыть нужно увеличенным лотом.

То есть, войти максимальным лотом, сколько позволяет FreeMargin.

Как записать такое условие: если для открытия позиции расчетным лотом недостаточно средств, то функция должна вернуть максимально возможный лот для открытия позиции.

 

double LotA()
{
   double Lot=FirstLot;

   if(DoublingCount<=0) return Lot;
   double MaxLot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
   double MainLot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
if(Lot<MainLot)Lot=MainLot;
     if(Lot>MaxLot)Lot=MaxLot;
   double lt1=Lot;
   HistorySelect(0,TimeCurrent());
   if(HistoryOrdersTotal()==0)return(Lot);
   double cl=HistoryOrderGetDouble(HistoryOrderGetTicket(HistoryOrdersTotal()-1),ORDER_PRICE_OPEN);
   double op=HistoryOrderGetDouble(HistoryOrderGetTicket(HistoryOrdersTotal()-2),ORDER_PRICE_OPEN);

   long typeor=HistoryOrderGetInteger(HistoryOrderGetTicket(HistoryOrdersTotal()-2),ORDER_TYPE);
   if(typeor==ORDER_TYPE_BUY)
     {
      if(op>cl)
        {
         if(ud<DoublingCount)
           {
            lt1=HistoryOrderGetDouble(HistoryOrderGetTicket(HistoryOrdersTotal()-2),ORDER_VOLUME_INITIAL)*_C_;
            ud++;
           }
         else ud=0;
        }
      else ud=0;
     }
   if(typeor==ORDER_TYPE_SELL)
     {
      if(cl>op)
        {
         if(ud<DoublingCount)
           {
            lt1=HistoryOrderGetDouble(HistoryOrderGetTicket(HistoryOrdersTotal()-2),ORDER_VOLUME_INITIAL)*_C_;
            ud++;
           }
         else ud=0;
        }
      else ud=0;
     }
   if(lt1>MaxLot)lt1=MaxLot;
   lt1=LotCheck(lt1);
   return(lt1);
  }
//+------------------------------------------------------------------+}
 
Marina Korotkih:

 Понятно, пример помог. Спасибо.


 Теперь такой вопрос.

При увеличении лота в какой-то момент чуть не хватает свободных средств, а открыть нужно увеличенным лотом.

То есть, войти максимальным лотом, сколько позволяет FreeMargin.

Как записать такое условие: если для открытия позиции расчетным лотом недостаточно средств, то функция должна вернуть максимально возможный лот для открытия позиции.

 

               

double Mgn,Lot=0,BID,ASK;

    BID=SymbolInfoDouble(_Symbol,SYMBOL_BID);
    ASK=SymbolInfoDouble(_Symbol,SYMBOL_ASK);

   if(OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1,ASK,Mgn)==true)Lot=AccountInfoDouble(ACCOUNT_MARGIN_FREE)/Mgn;

   if(OrderCalcMargin(ORDER_TYPE_SELL,_Symbol,1,BID,Mgn)==true)Lot=AccountInfoDouble(ACCOUNT_MARGIN_FREE)/Mgn;
                        

Марина, может быть так?

Два варианта расчета применяете - один для открытия SELL, а другой - для открытия BUY

 
Renat Akhtyamov:

                  if(OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1,ASK,Mgn)==true)Lot=AccountInfoDouble(ACCOUNT_MARGIN_FREE)/Mgn;

                  if(OrderCalcMargin(ORDER_TYPE_SELL,_Symbol,1,BID,Mgn)==true)Lot=AccountInfoDouble(ACCOUNT_MARGIN_FREE)/Mgn;
                        

Марина, может быть так?

Не, не так.

Нужно не просто вычислить максимально возможный лот, но и проверить всё это дело на минимально допустимый, потому как может произойти ситуация, что минимальный лот 0.01, а маржа позволяет открыть только 0.009, тогда замучаете сервер запросами, которые никогда не примут, а вот меры на вас могут и принять)

 
Vitaly Muzichenko:

Не, не так.

Нужно не просто вычислить максимально возможный лот, но и проверить всё это дело на минимально допустимый, потому как может произойти ситуация, что минимальный лот 0.01, а маржа позволяет открыть только 0.009, тогда замучаете сервер запросами, которые никогда не примут, а вот меры на вас могут и принять)

Напишите полный код, как должно быть, ну и я посмотрю заодним....?

Я теперь всегда буду учиться у Вас и посматривать за Вами, чтобы ответы были в полном объеме.

Я когда то работал технадзором, не переживайте, всё будет ОК!

Вместе мы - команда!

 
Marina Korotkih:

 Понятно, пример помог. Спасибо.


 Теперь такой вопрос.

При увеличении лота в какой-то момент чуть не хватает свободных средств, а открыть нужно увеличенным лотом.

То есть, войти максимальным лотом, сколько позволяет FreeMargin.

Как записать такое условие: если для открытия позиции расчетным лотом недостаточно средств, то функция должна вернуть максимально возможный лот для открытия позиции.


Скользкой дорожкой вы идёте)).
[Удален]  

            Люди подскажите  что не так  делаю ,  Почему  два индикатора iRSI,iCCI  не вызывают проблем  ,  а   мувинг и ВВ   выдает предупреждение  (possible loss of data due to type conversion    Indicator.mqh  )

//+------------------------------------------------------------------+
//|                                                    Indicator.mqh |
//|                        Copyright 2017, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
// интерфейс к индикаторам.  

class CIndicators
{
public:

   double iRSI(string symbol, ENUM_TIMEFRAMES tf, int period, ENUM_APPLIED_PRICE applied, int shift);
   double iCCI(string symbol, ENUM_TIMEFRAMES tf, int period, ENUM_APPLIED_PRICE applied, int shift);  
   double iBands(string symbol,ENUM_TIMEFRAMES tf,int BBPeriod,int shift,double BBDeviation,ENUM_APPLIED_PRICE BBPrice );  
   double iMA(string symbol,ENUM_TIMEFRAMES tf, int nMAPeriod,int shift, ENUM_MA_METHOD eMAMethod ,ENUM_APPLIED_PRICE MAPrice);
      
};
// -Создадим экземпляр индикатора iRSI
double CIndicators::iRSI(string symbol, ENUM_TIMEFRAMES tf, int period, ENUM_APPLIED_PRICE applied, int shift)
{
//---  
   int hRSI = iRSI(symbol, tf, period, applied);
   if(hRSI == INVALID_HANDLE)
      return 0.0;
   double rsi[];
   CopyBuffer(hRSI, 0, shift, 1, rsi);
   if(ArraySize(rsi))
      return rsi[0];
   return 0.0;
//--Создадим экземпляр индикатора iCCI
}
//----------------------------------
double CIndicators::iCCI(string symbol, ENUM_TIMEFRAMES tf, int period, ENUM_APPLIED_PRICE applied, int shift)
{
   int hCCI = iCCI(Symbol(), PERIOD_CURRENT, 55, PRICE_CLOSE);
   if(hCCI == INVALID_HANDLE)return 0.0;
   double cci[];
   ArrayResize(cci, 1);
   CopyBuffer(hCCI, 0, 0, 1, cci);
   return cci[0];
}
//--------------------------------------------------
// Создадим экземпляр индикатора ВВ
double CIndicators::iBands(string symbol,ENUM_TIMEFRAMES tf,int BBPeriod,int shift,double BBDeviation,ENUM_APPLIED_PRICE BBPrice)
{

   int hBands = iBands(Symbol(),tf,BBPeriod,0,BBDeviation,PRICE_CLOSE);
   if(hBands==INVALID_HANDLE)return 0.0;
  // Создадим массив значений верхней границы ВВ
   double fBBUpper[];
   ArrayResize(fBBUpper,true);
   CopyBuffer(hBands,UPPER_BAND,0,3,fBBUpper);
   return fBBUpper[0];  
   // Создадим массив значений нижней границы ВВ
   double fBBLower[];
   ArraySetAsSeries(fBBLower,true);
   CopyBuffer(hBands,LOWER_BAND,0,3,fBBLower);
   return  fBBLower[0];
   }
  
// Создадим экземпляр индикатора МА  
double CIndicators::iMA(string symbol,ENUM_TIMEFRAMES tf, int nMAPeriod,int shift, ENUM_MA_METHOD eMAMethod ,ENUM_APPLIED_PRICE MAPrice)
{
// получим его хэндл
   int hMA=iMA(Symbol(), PERIOD_CURRENT, nMAPeriod,0,MODE_EMA,PRICE_CLOSE);
   if(hMA == INVALID_HANDLE)return 0.0;
// Создадим массив значений МА,заполним тремя последними значениями мувинга.
   double fMA[];
   ArraySetAsSeries(fMA,true);
   CopyBuffer(hMA,0,0,3,fMA);
   return fMA[0];

}
[Удален]  

И еще хотел спросить:   Что нужно изменить в торговом запросе  ,  появилась ошибка 10030  ,,,  годом ранее  код  эксперта  работал  без проблем  а теперь  опять меня заставляет читать/искать  новшество изменений MQL5


// функция открытия позиции с рынка
bool MarketOrder(const string sSymbol, const ENUM_POSITION_TYPE eType, const double fLot, const int nSL = 0, const int nTP = 0, const ulong nMagic = 0, const uint nSlippage = 1000)
{
        bool bRetVal = false;
        
        // запрос
        MqlTradeRequest oRequest = {0};
        MqlTradeResult   oResult = {0};
        
        double fPoint = SymbolInfoDouble(sSymbol, SYMBOL_POINT);
        int nDigits     = (int) SymbolInfoInteger(sSymbol, SYMBOL_DIGITS);

        oRequest.action         = TRADE_ACTION_DEAL;
        oRequest.symbol         = sSymbol;
        oRequest.volume         = fLot;
        oRequest.stoplimit      = 0;
        oRequest.deviation      = nSlippage;
        
        if(eType == POSITION_TYPE_BUY)
        {
                oRequest.type           = ORDER_TYPE_BUY;
                oRequest.price          = NormalizeDouble(SymbolInfoDouble(sSymbol, SYMBOL_ASK), nDigits);
                oRequest.sl                     = NormalizeDouble(oRequest.price - nSL * fPoint, nDigits) * (nSL > 0);
                oRequest.tp                     = NormalizeDouble(oRequest.price + nTP * fPoint, nDigits) * (nTP > 0);
        }
        
        if(eType == POSITION_TYPE_SELL)
        {
                oRequest.type           = ORDER_TYPE_SELL;
                oRequest.price          = NormalizeDouble(SymbolInfoDouble(sSymbol, SYMBOL_BID), nDigits);
                oRequest.sl                     = NormalizeDouble(oRequest.price + nSL * fPoint, nDigits) * (nSL > 0);
                oRequest.tp                     = NormalizeDouble(oRequest.price - nTP * fPoint, nDigits) * (nTP > 0);
        }
        
        // определим допустимый тип заливки ордера (зависит от типа исполнения - Instant, Market, биржевое и т.д.)
        switch((int) SymbolInfoInteger(sSymbol, SYMBOL_FILLING_MODE))
        {
        case SYMBOL_FILLING_FOK:
                oRequest.type_filling = ORDER_FILLING_FOK;
                break;
        case SYMBOL_FILLING_IOC:
                oRequest.type_filling = ORDER_FILLING_IOC;
                break;
        default:
                oRequest.type_filling = ORDER_FILLING_RETURN;
        }

        oRequest.magic                          = nMagic;
        
        
        // проверка перед отправкой
        MqlTradeCheckResult oCheckResult= {0};
        
        bool bCheck = OrderCheck(oRequest, oCheckResult);

        Print("Проверка заявки MarketOrder:",
                        " OrderCheck = ",               bCheck,
                        ", retcode = ",         oCheckResult.retcode,
                        ", balance = ",         NormalizeDouble(oCheckResult.balance, 2),
                        ", equity = ",                  NormalizeDouble(oCheckResult.equity, 2),
                        ", margin = ",                  NormalizeDouble(oCheckResult.margin, 2),
                        ", margin_free = ",     NormalizeDouble(oCheckResult.margin_free, 2),
                        ", margin_level = ",    NormalizeDouble(oCheckResult.margin_level, 2),
                        ", comment = ",         oCheckResult.comment);
        
        // если проверка удачная - отправка заявки
        if(bCheck == true && oCheckResult.retcode == 0)
        {
                bool bResult = false;
                
                // 3 попытки выставления ордера
                for(int k = 0; k < 3; k++)
                {
                        bResult = OrderSend(oRequest, oResult);
                        
                        if(bResult == true && oResult.retcode == TRADE_RETCODE_DONE)
                                break;
                        
                        if(k == 2)
                                break;
                                
                        Sleep(100);
                }
        
                Print("Отправка заявки:",
                                " OrderSend = ",        bResult,
                                ", retcode = ", oResult.retcode,
                                ", deal = ",            oResult.deal,
                                ", order = ",           oResult.order,
                                ", volume = ",          NormalizeDouble(oResult.volume, 2),
                                ", price = ",           NormalizeDouble(oResult.price, _Digits),
                                ", bid = ",                     NormalizeDouble(oResult.bid, _Digits),
                                ", ask = ",                     NormalizeDouble(oResult.ask, _Digits),
                                ", comment = ", oResult.comment,
                                ", request_id = ",oResult.request_id);  
                                
                if(oResult.retcode == TRADE_RETCODE_DONE)
                        bRetVal = true;
        }
        else if(oResult.retcode == TRADE_RETCODE_NO_MONEY)
        {
                Print("Недостаточно денег для открытия позиции. Работа эксперта прекращена.");
                ExpertRemove();
        }
        
        return(bRetVal);
}