Mql5 dilinin özellikleri, incelikleri ve çalışma yöntemleri - sayfa 4

 
// Возвращает тип исполнения ордера, равный Type, если он доступен на символе Symb, иначе - корректный вариант.
ENUM_ORDER_TYPE_FILLING GetFilling( const string Symb, const uint Type = ORDER_FILLING_FOK )
{
   const ENUM_SYMBOL_TRADE_EXECUTION ExeMode = ( ENUM_SYMBOL_TRADE_EXECUTION ):: SymbolInfoInteger (Symb, SYMBOL_TRADE_EXEMODE );
   const int FillingMode = ( int ):: SymbolInfoInteger (Symb, SYMBOL_FILLING_MODE );

   return ((FillingMode == 0 || (Type >= ORDER_FILLING_RETURN ) || ((FillingMode & (Type + 1 )) != Type + 1 )) ?
         (((ExeMode == SYMBOL_TRADE_EXECUTION_EXCHANGE ) || (ExeMode == SYMBOL_TRADE_EXECUTION_INSTANT )) ?
           ORDER_FILLING_RETURN : ((FillingMode == SYMBOL_FILLING_IOC ) ? ORDER_FILLING_IOC : ORDER_FILLING_FOK )) :
          ( ENUM_ORDER_TYPE_FILLING )Type);
}
Başvuru
Request.type_filling = GetFilling(Request.symbol);
 
// Возвращает тип истечения ордера, равный Expiration, если он доступен на символе Symb, иначе - корректный вариант.
ENUM_ORDER_TYPE_TIME GetExpirationType( const string Symb, uint Expiration = ORDER_TIME_GTC )
{
   const int ExpirationMode = ( int ):: SymbolInfoInteger (Symb, SYMBOL_EXPIRATION_MODE );

   if ((Expiration > ORDER_TIME_SPECIFIED_DAY ) || (((ExpirationMode >> Expiration) & 1 ) == 0 ))
  {
     if ((Expiration < ORDER_TIME_SPECIFIED ) || (ExpirationMode < SYMBOL_EXPIRATION_SPECIFIED ))
      Expiration = ORDER_TIME_GTC ;
     else if (Expiration > ORDER_TIME_DAY )
      Expiration = ORDER_TIME_SPECIFIED ;

     uint i = 1 << Expiration;

     while ((Expiration <= ORDER_TIME_SPECIFIED_DAY ) && ((ExpirationMode & i) != i))
    {
      i <<= 1 ;
      Expiration++;
    }
  }

   return (( ENUM_ORDER_TYPE_TIME )Expiration);
}
Başvuru
Request.type_time = GetExpirationType(Request.symbol, ( uint )Expiration); // Expiration может быть datetime-временем

if (Expiration > ORDER_TIME_DAY )
  Request.expiration = Expiration;
 
MqlTrade yapılarını bir dizgeye dönüştürme
#define TOSTRING(A)   #A + " = " + ( string )(A) + "\n"
#define TOSTRING2(A) #A + " = " + EnumToString (A) + " (" + ( string )(A) + ")\n"

string ToString( const MqlTradeTransaction &Trans )
{
   return (TOSTRING(Trans.deal) + TOSTRING(Trans.order) + TOSTRING(Trans.symbol) +
         TOSTRING2(Trans.type) + TOSTRING2(Trans.order_type) + TOSTRING2(Trans.order_state) +
         TOSTRING2(Trans.deal_type) + TOSTRING2(Trans.time_type) +
         TOSTRING(Trans.time_expiration) + TOSTRING(Trans.price) + TOSTRING(Trans.price_trigger) +
         TOSTRING(Trans.price_sl) + TOSTRING(Trans.price_tp) + TOSTRING(Trans.volume) +
         TOSTRING(Trans.position) + TOSTRING(Trans.position_by));
}

string ToString( const MqlTradeRequest &Request )
{
   return (TOSTRING2(Request.action) + TOSTRING(Request.magic) + TOSTRING(Request.order) +
         TOSTRING(Request.symbol) + TOSTRING(Request.volume) + TOSTRING(Request.price) +
         TOSTRING(Request.stoplimit) + TOSTRING(Request.sl) +  TOSTRING(Request.tp) +
         TOSTRING(Request.deviation) + TOSTRING2(Request.type) + TOSTRING2(Request.type_filling) +
         TOSTRING2(Request.type_time) + TOSTRING(Request.expiration) + TOSTRING(Request.comment) +
         TOSTRING(Request.position) + TOSTRING(Request.position_by));
}

string ToString( const MqlTradeResult &Result )
{
   return (TOSTRING(Result.retcode) + TOSTRING(Result.deal) + TOSTRING(Result.order) +
         TOSTRING(Result.volume) + TOSTRING(Result.price) + TOSTRING(Result.bid) +  
         TOSTRING(Result.ask) + TOSTRING(Result.comment) + TOSTRING(Result.request_id) +  
         TOSTRING(Result.retcode_external));
}

#undef TOSTRING
#undef TOSTRING2
Başvuru
void OnTradeTransaction ( const MqlTradeTransaction &Trans, const MqlTradeRequest &Request, const MqlTradeResult &Result )
{
   Print (ToString(Trans) + ToString(Request) + ToString(Result));
}
 
// Триггер срабатывания SL/TP - работает только на демо/реале (не в тестере).
void OnTradeTransaction ( const MqlTradeTransaction &Trans, const MqlTradeRequest &Request, const MqlTradeResult &Result )
{
  if ((Trans.type == TRADE_TRANSACTION_ORDER_ADD) &&
       PositionSelectByTicket(Trans.position) && OrderSelect(Trans.order) &&
       (PositionGetInteger(POSITION_TYPE) == 1 - OrderGetInteger(ORDER_TYPE)))
  {
    const double Price = OrderGetDouble(ORDER_PRICE_OPEN);
    
    if (Price == PositionGetDouble(POSITION_TP))
      Print("Position #" + (string)Trans.position + " - triggered TP.");    
    else if (Price == PositionGetDouble(POSITION_SL))
      Print("Position #" + (string)Trans.position + " - triggered SL.");    
  }
}
 
ENUM_DAY_OF_WEEK GetDayOfWeek( const datetime time )
{
   MqlDateTime sTime = { 0 };

  :: TimeToStruct (time, sTime);

   return (( ENUM_DAY_OF_WEEK )sTime.day_of_week);
}

// true - находимся в торговой сессии
bool SessionTrade( const string Symb )
{
   datetime TimeNow = :: TimeTradeServer ();

   const ENUM_DAY_OF_WEEK DayOfWeek = GetDayOfWeek(TimeNow);

  TimeNow %= 24 * 60 * 60 ;

   bool Res = false ;
   datetime From, To;

   for ( int i = 0 ; (!Res) && :: SymbolInfoSessionTrade (Symb, DayOfWeek , i, From, To); i++)
    Res = ((From <= TimeNow) && (TimeNow < To));

   return (Res);
}

// Возвращает true, если символ торгуемый. Иначе - false.
bool SymbolTrade( const string Symb )
{
   MqlTick Tick;

   return (:: SymbolInfoTick (Symb, Tick) ? ((Tick.bid != 0 ) && (Tick.ask != 0 ) && SessionTrade(Symb) /* &&
         ((ENUM_SYMBOL_TRADE_MODE)::SymbolInfoInteger(Symb, SYMBOL_TRADE_MODE) == SYMBOL_TRADE_MODE_FULL) */
) : false );
}

Başvuru

if ( OrderCheck (Request, CheckResult) && SymbolTrade(Request.symbol))
   OrderSend (Request, Result);
 

İşler çok daha kolay. Siparişi göndermeden önce tarihin uzunluğunu hatırladım ve gönderdikten sonra tarihin uzunluğunun artmasını bekledim. Aniden sonsuza kadar takılmaması için bir zaman aşımı girilmelidir.

 
Dmitry Fedoseev :

İşler çok daha kolay. Siparişi göndermeden önce tarihin uzunluğunu hatırladım ve gönderdikten sonra tarihin uzunluğunun artmasını bekledim. Aniden sonsuza kadar takılmaması için zaman aşımı girilmelidir.

Bir zaman aşımı var. Sizin sürümünüzde, ne yazık ki, birden fazla Sipariş Gönderiminin birlikte işlenmesi (farklı Uzman Danışmanlardan) sorunlar olabilir.

Ayrıca, yalnızca geçmiş senkronize değil, aynı zamanda açık pozisyonların/emirlerin SL/TP'si vb. Piyasalar için tarih, önce yalnızca bir siparişle ve bir an sonra - bir anlaşmayla artabilir. Başka durumlar da var. Bu nedenle, ilk bakışta çok hantal görünüyor.

 
Dmitry Fedoseev :

Mesajınızın anlamı nedir? Peki, OnTradeTransaction()'a gelecek, ne olmuş yani? Bu, etkinliği beklemeniz gerektiği anlamına gelir. Hala bekliyorum. fxsaber mesajının anlamı, OrderSend()'in yürütülmesinden sonra, gerçekleştirilen eylemle ilgili bilgilerin uçbirimde hemen görünmemesidir. Birisi OnTradeTransaction() için beklemeyi sever, biri listedeki bir siparişin veya anlaşmanın görünümünü beğenir. Örneğin, MT4'ten farkı. M4'te OrderSend()'den sonra sipariş zaten emirler listesindedir ve OrderClose()'dan sonra her zaman geçmiştedir.

Neden OnTradeTransaction() 'ı bekleyelim? Bir istek kuyruğu oluşturun, bir yanıt gelirse bir şeyler yapın ... en azından isteği kuyruktan kaldırın. SB'de Kuyruk olmaması üzücü, ancak bu basit bir sınıf.

 
fxsaber :

Bir zaman aşımı var. Sizin sürümünüzde, ne yazık ki, birden fazla Sipariş Gönderiminin birlikte işlenmesi (farklı Uzman Danışmanlardan) sorunlar olabilir.

Ayrıca, yalnızca geçmiş senkronize değil, aynı zamanda açık pozisyonların/emirlerin SL/TP'si vb. Piyasalar için tarih, önce yalnızca bir siparişle ve bir an sonra - bir anlaşmayla artabilir. Başka durumlar da var. Bu nedenle, ilk bakışta çok hantal görünüyor.

Evet katılıyorum. Ancak böyle bir danışman sadece bir tanesiydi ve eğer bir şey olursa, korkunç bir şey olmayacak.

Standart ticaret sınıfının da kullanılabilmesi için bekleme için ayrı bir fonksiyon yazmak daha iyi olur.

 
Alexey Volchanskiy :

Neden OnTradeTransaction() 'ı bekleyelim? Bir istek kuyruğu oluşturun, bir yanıt gelirse bir şeyler yapın ... en azından isteği kuyruktan kaldırın. SB'de Kuyruk olmaması üzücü, ancak bu basit bir sınıf.

Mesele şu ki, OnTradeTransaction() içinde OrderSend'den hemen sonra çalışmayacaktır.

Kısacası, anlaşmazlığın konusuna girmeden tartışacak bir sevgili kalabalığı var.

OrderSend()'den hemen sonra bir şeyler yapmanız gerekiyorsa, algoritmanın iki çeşidi vardır:

1. Sipariş ve anlaşma listelerini güncellemek için bekleme döngüsünü açın.

2. OnTick()'i bitirin ve OnTradeTransaction()'ın tetiklenmesini bekleyin.

3. Listede yeni bir sipariş veya anlaşmanın görünüp görünmediğini kontrol edin.

Neden: