FORTS : Pour aider les débutants

 

Bon après-midi!

Ici, je publierai des recommandations, des bugs, des fonctionnalités et des fonctions fréquemment utilisées sur le marché à terme FORTS

IMPORTANT : Afin de ne pas "étirer" le sujet, s'il y a des commentaires,

ou avez des questions - créez un sujet séparé dans cette section (je ne répondrai pas ici).

Recommandation :

La bibliothèque standard MQL5 est "affinée" pour le marché FOREX, donc pour

développements d'experts pour FORTS Je recommande de tout écrire vous-même.

Fonctionnalités fréquemment utilisées et utiles :

La fonction de vérification des paramètres de trading du serveur du courtier.

Dans cette fonction, il est nécessaire de vérifier les paramètres qui

Vous l'utiliserez dans votre conseiller. Voici un exemple:

(utiliser UNIQUEMENT dans OnInit() )

 //+------------------------------------------------------------------+
//| Expert Check Market Parameters function                          |
//+------------------------------------------------------------------+
bool CheckMarketParam( const string a_symbol )
{
//--- Check for full mode
   ENUM_SYMBOL_TRADE_MODE trade_mode = ENUM_SYMBOL_TRADE_MODE ( SymbolInfoInteger ( a_symbol, SYMBOL_TRADE_MODE ) );
  
   if ( trade_mode != SYMBOL_TRADE_MODE_FULL )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает полную торговлю!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
//--- Check trade execution mode
   ENUM_SYMBOL_TRADE_EXECUTION market_info = ENUM_SYMBOL_TRADE_EXECUTION ( SymbolInfoInteger ( a_symbol, SYMBOL_TRADE_EXEMODE ) );
    
   if ( market_info != SYMBOL_TRADE_EXECUTION_EXCHANGE )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает TRADE EXECUTION EXCHANGE режим!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
//--- Check orders mode
   int order_mode = int ( SymbolInfoInteger ( a_symbol, SYMBOL_ORDER_MODE ) );
  
   if ( ( SYMBOL_ORDER_MARKET & order_mode )!= SYMBOL_ORDER_MARKET )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает Market Execution режим установки ордеров!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
  
   if ( ( SYMBOL_ORDER_LIMIT & order_mode )!= SYMBOL_ORDER_LIMIT )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает Limit режим установки ордеров!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
  
   if ( ( SYMBOL_ORDER_STOP_LIMIT & order_mode ) != SYMBOL_ORDER_STOP_LIMIT )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает Stop Limit режим установки ордеров!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
  
   if ( ( SYMBOL_ORDER_STOP & order_mode )!= SYMBOL_ORDER_STOP )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает Stop режим установки ордеров!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
  
   if ( ( SYMBOL_ORDER_SL & order_mode) != SYMBOL_ORDER_SL )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает Stop Loss режим установки ордеров!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
  
   if ( ( SYMBOL_ORDER_TP & order_mode) != SYMBOL_ORDER_TP )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает Take Profit режим установки ордеров!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
//---Filing mode
   int filling_mode = int ( SymbolInfoInteger ( a_symbol, SYMBOL_FILLING_MODE ) );
  
   if ( ( SYMBOL_FILLING_IOC & filling_mode ) != SYMBOL_FILLING_IOC )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает filling IOC режим исполнения ордеров!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
  
   if ( ( SYMBOL_FILLING_FOK & filling_mode ) != SYMBOL_FILLING_FOK )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает filling FOK режим исполнения ордеров!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }      
//---Ckeck expiration
   int symbol_exp_type = int ( SymbolInfoInteger ( a_symbol, SYMBOL_EXPIRATION_MODE ) );
//---  
   if ( ( symbol_exp_type & SYMBOL_EXPIRATION_DAY ) != SYMBOL_EXPIRATION_DAY )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает экспирацию DAY!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
   if ( ( symbol_exp_type & SYMBOL_EXPIRATION_SPECIFIED_DAY ) != SYMBOL_EXPIRATION_SPECIFIED_DAY )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает экспирацию SPECIFIED DAY!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
   return ( true );
} 

Exemple d'utilisation :

 int OnInit ()
{
   if ( !CheckMarketParam( _Symbol ) ) return ( INIT_FAILED );
   return ( INIT_SUCCEEDED );
}

Obtenir le nombre de jours restants jusqu'à l'expiration de l'instrument :

 #define YEAR           365

int GetExpiration( const string aSymbol )
{
   MqlDateTime ExpData, CurData;
    
   datetime exp_time = datetime ( SymbolInfoInteger ( aSymbol, SYMBOL_EXPIRATION_TIME ) );
      
   TimeToStruct ( exp_time, ExpData );
   TimeTradeServer ( CurData );
      
   if ( ExpData.year != CurData.year )
  {
     return ( YEAR * ( ExpData.year - CurData.year ) - CurData.day_of_year + ExpData.day_of_year );
  }
   else
  {
     return ( ExpData.day_of_year - CurData.day_of_year );
  }
}

Obtenir le prix "net" de la position, hors compensations :

 //+------------------------------------------------------------------+
//| Expert Get position price function                               |
//+------------------------------------------------------------------+
double GetPositionPrice( const string aSymbol )
{
   double price_in = 0 ;
   double volume_in = 0 ;
   double price_out = 0 ;
   double volume_out = 0 ;
   double price = 0 ;
   double volume = 0 ;
  
   if ( PositionSelect ( aSymbol ) )
  {
     ulong pos_id = ulong ( PositionGetInteger ( POSITION_IDENTIFIER ) );
    
     if ( pos_id > 0 )
    {
       if ( HistorySelectByPosition ( pos_id ) )
      {
         int deals = HistoryDealsTotal ();
      
         for ( int i = 0 ; i < deals; i++ )
        {
           ulong deal_ticket = HistoryDealGetTicket ( i );
           ulong order_ticket = ulong ( HistoryDealGetInteger ( deal_ticket, DEAL_ORDER ) );
        
           if ( order_ticket > 0 )
          {
             ENUM_DEAL_ENTRY deal_entry = ENUM_DEAL_ENTRY ( HistoryDealGetInteger ( deal_ticket, DEAL_ENTRY ) );
              
             if ( deal_entry == DEAL_ENTRY_IN )
            {
              price = HistoryDealGetDouble ( deal_ticket, DEAL_PRICE );
              volume = HistoryDealGetDouble ( deal_ticket, DEAL_VOLUME );
                                
              price_in += price * volume;
              volume_in += volume;  
            }
             else
             if ( deal_entry == DEAL_ENTRY_OUT )
            {
              price = HistoryDealGetDouble ( deal_ticket, DEAL_PRICE );
              volume = HistoryDealGetDouble ( deal_ticket, DEAL_VOLUME );
                                
              price_out += price * volume;
              volume_out += volume;  
            }
          }
        }
         if ( volume_out > 0 )
        {
           if ( volume_in > 0 ) { price_in = price_in / volume_in; } else return ( 0 );
          price_out = price_out / volume_out;
          price = ( price_in - price_out ) * ( volume_in - volume_out );
        }
         else
        {
           if ( volume_in > 0 ) { price = price_in / volume_in; } else return ( 0 );
        }
         return ( NormalizeDouble ( price, _Digits ) );
      }
       else
      {
         Print ( "GetPositionPrice: Невозможно получить историю позиции по символу " , aSymbol );
      }
    }
     else
    {
       Print ( "GetPositionPrice: Невозможно определить идентификатор позиции по символу " , aSymbol );
    }
  }
   return ( 0 );
} 

Création d'une variable terminale globale pour compter les transactions :

( Utiliser UNIQUEMENT dans OnInit() )

   if ( ! GlobalVariableCheck ( "trans_count" ) )
  {
     datetime a_time = GlobalVariableSet ( "trans_count" , 0 );
    
     if ( ulong ( a_time ) == 0 )
    {
       MessageBox ( "Глобальная переменная терминала 'Счётчик транзакций' не создана!" , "Ошибка" , MB_OK | MB_ICONHAND );
       return ( INIT_FAILED );
    }
  }

Ecriture protégée dans la variable globale du terminal (compteur de transactions) :

 //+------------------------------------------------------------------+
//| Expert Set transaction count function                            |
//+------------------------------------------------------------------+
void SetTransCount( const bool up_down )
{
   double tr_count;
   uint i = 0 ;
   do
  {
    i++;
     if ( GlobalVariableGet ( "trans_count" , tr_count ) )
    {
       if ( up_down )
      {
         if ( GlobalVariableSetOnCondition ( "trans_count" , tr_count + 1 , tr_count ) )
        {
          i = 100 ;
        }
      }
       else
      {
         if ( GlobalVariableSetOnCondition ( "trans_count" , tr_count - 1 , tr_count ) )
        {
          i = 100 ;
        }
      }
    }
  }  
   while ( i < 100 );
}

Si le paramètre up_down = true, alors on augmente la variable globale du terminal,

et vice versa.

Vérification des fonds avec réduction automatique du volume, en cas de manque d'argent :

 //| Expert Check money function                                      |
//+------------------------------------------------------------------+ 
bool CheckMoney( long &volume )
{
   if ( volume <= 0 ) return ( false );
//---
   double symbol_go = SymbolInfoDouble ( _Symbol , SYMBOL_MARGIN_INITIAL );
   double free_margin = ( AccountInfoDouble ( ACCOUNT_FREEMARGIN ) / 100 ) * 90 ; //90% от свободных средств
   double real_go = NormalizeDouble ( symbol_go * volume, 2 );
//---     
   if ( real_go <= free_margin )
  {
     return ( true );
  }
   else
  {
     while ( real_go > free_margin )
    {
      volume--;
      
       if ( volume <= 0 )
      {
         Print ( "CheckMoney: Не хватает средств!" );
         return ( false );
      }  
      real_go = NormalizeDouble ( symbol_go * volume, 2 );
    }
     return ( true );
  }
   Print ( "CheckMoney: Не хватает средств!" ); 
   return ( false );
}

Placer un ordre au marché/à cours limité avec la commande OrderSend()

si prix = ''0" - ordre au marché :

 //+------------------------------------------------------------------+
//| Expert set order function                                        |
//+------------------------------------------------------------------+
void SetOrder( const string aSymbol, ulong &ticket, const double price, const double volume, const bool buy_sell )
{
   MqlTradeRequest request = { 0 };
   MqlTradeResult   result  = { 0 };
  ticket = 0 ;
   
//--- Fill structure
  request.magic = 1234567890 ;
  request.symbol = aSymbol;
  request.volume = volume; 
  request.type_filling = ORDER_FILLING_IOC ;
  request.type_time = ORDER_TIME_DAY ;
    
   if ( price == 0 )
  {
    request.action = TRADE_ACTION_DEAL ;
    request.comment = "Рыночный ордер..." ;
//---    
     if ( buy_sell )
    {
      request.type = ORDER_TYPE_BUY ;
    }
     else
    {
      request.type = ORDER_TYPE_SELL ;
    }
  }
   else
  { 
    request.action = TRADE_ACTION_PENDING ;
    request.price = price;
    request.comment = "Лимитный ордер..." ;
//---    
     if (buy_sell)
    {
      request.type = ORDER_TYPE_BUY_LIMIT ;
    }
     else
    {
      request.type = ORDER_TYPE_SELL_LIMIT ;
    }   
  }  
//--- Send order
   if ( OrderSend ( request, result ) )
  {
     if ( result.retcode == TRADE_RETCODE_PLACED ) 
    {
      ticket = result.order;
    }
     else
    {
       Print ( "SeOrder: Установка ордера не выполнена! " , aSymbol );
    }
  }
   else
  {
     Print ( "SeOrder: Ордер не отправлен! " , aSymbol );
  }
}

Supprimer une commande avec la commande OrderSend()

 void RemoveOrder( ulong & ord_ticket )
{
   if ( ord_ticket >   0 )
  {
     if ( OrderSelect ( ord_ticket ) )
    {
       MqlTradeRequest request = { 0 };
       MqlTradeResult   result  = { 0 };
//---  
      request.action = TRADE_ACTION_REMOVE ;
      request.order  = ord_ticket;
//---  
       if ( OrderSend ( request, result ) )
      {
         if ( result.retcode == TRADE_RETCODE_PLACED )
        { 
          ord_ticket = result.order;
        }
         else
        {
           Print ( "RemoveOrder: Удаление старого ордера не выполнено! Билет = " , ord_ticket );
        }  
      }
       else
      {
         Print ( "RemoveOrder: Ордер не отослан! Билет = " , ord_ticket );
      }
    }
  }
}

Passer une commande en attente avec la commande OrderSend()

 //+------------------------------------------------------------------+
//| Place order                                                      |
//+------------------------------------------------------------------+
void PlaceOrder( const string aSymbol, ulong & ticket, const double price, const double volume, const bool buy_sell )
{
   MqlTradeRequest request = { 0 };
   MqlTradeResult   result  = { 0 };
  ticket = 0 ;
     
//--- Fill structure
  request.action = TRADE_ACTION_PENDING ;
  request.magic  = 1234567890 ;
  request.symbol = aSymbol;
  request.volume = volume;
  request.price  = price;
    
   if ( buy_sell )
  {
    request.type = ORDER_TYPE_BUY_LIMIT ;
  }
   else
  {
    request.type = ORDER_TYPE_SELL_LIMIT ;
  } 
  request.comment = "Отложенный ордер..." ;      
  request.type_filling = ORDER_FILLING_RETURN ;
  request.type_time = ORDER_TIME_DAY ;
  
//--- Send order
   if ( OrderSend ( request, result ) )
  {
     if ( result.retcode == TRADE_RETCODE_PLACED ) 
    {
      ticket = result.order;
    }
     else
    {
       Print ( "PlaceOrder: Ордер не установлен!" );
    }
  }
   else
  {
     Print ( "PlaceOrder: Ордер не отослан! " );
  }
}

Modifier une commande en attente avec la commande OrderSend()

 //+------------------------------------------------------------------+
// Modify order                                                      |
//+------------------------------------------------------------------+
void ModifyOrder( const string aSymbol, const double price, ulong & ticket )
{
   if ( ticket > 0 )
  {
     if ( OrderSelect ( ticket ) )
    {
       MqlTradeRequest request = { 0 };
       MqlTradeResult   result  = { 0 };
   
      request.action = TRADE_ACTION_MODIFY ;
      request.symbol = aSymbol;
      request.order  = ticket;
      request.price  = price;
      request.type_time = ORDER_TIME_DAY ;
  
       if ( OrderSend ( request, result ) )
      {
         if ( result.retcode == TRADE_RETCODE_PLACED ) 
        {
          ticket = result.order;
        }
         else
        {
           Print ( "ModifyOrder: Ордер не модифицирован! Билет = " , ticket );
        }
      }
       else
      {
         Print ( "ModifyOrder: Ордер не отослан! Билет " , ticket );
      }
    }
  }
}

Définition d'une commande en attente avec la commande OrderSendAsync()

Lors de l'utilisation de cette commande, le ticket n'est pas obtenu à la suite de cette

fonctions, mais dans la fonction OnTradeTransaction(). Dans la fonction OrderSendAsync(), nous

obtenir le numéro de la demande pour passer une commande :

uint req_id;
 ulong order_ticket = 0;
 void PlaceAsync( const string a_symbol, uint & req_id, const double price, const double volume, const bool buy_sell )
{
   MqlTradeRequest request = { 0 };
   MqlTradeResult   result  = { 0 };
  req_id = 0 ;
     
//--- Fill structure
  request.action = TRADE_ACTION_PENDING ;
  request.magic  = 1234567890 ;
  request.symbol = a_symbol;
  request.volume = volume;
  request.price  = price;
    
   if ( buy_sell )
  {
    request.type = ORDER_TYPE_BUY_LIMIT ;
  }
   else
  {
    request.type = ORDER_TYPE_SELL_LIMIT ;
  } 
  request.comment = "Отложенный ордер..." ;      
  request.type_filling = ORDER_FILLING_RETURN ;
  request.type_time = ORDER_TIME_DAY ;
  
//--- Send order
   if ( OrderSendAsync ( request, result ) )
  {
     if ( result.retcode == TRADE_RETCODE_PLACED ) 
    {
      req_id = result.request_id;
    }
     else
    {
       Print ( "PlaceAsync: Ордер не установлен! " , a_symbol );
    }
  }
   else
  {
     Print ( "PlaceAsync: Ордер на отослан! " , a_symbol );
  }
}

Obtenir un billet par numéro de demande :

 void OnTradeTransaction ( const MqlTradeTransaction &trans,
                         const MqlTradeRequest &request,
                         const MqlTradeResult &result )
{
   switch ( trans.type )
  {
     case TRADE_TRANSACTION_REQUEST : if ( trans.order_state == ORDER_STATE_STARTED )
                                    {
                                       if ( ( req_id != 0 ) && ( result.request_id == req_id ) )
                                      {
                                         if ( result.retcode == TRADE_RETCODE_PLACED )
                                        {
                                           if ( result.order > 0 )
                                          {
                                            order_ticket = result.order;
                                          }
                                           else
                                          {
                                             Print ( "OnTradeTransaction: Не получен билет! Запрос = " , req_id );
                                          }
                                        }
                                      }
                                    }  
                                     break ;
                                    
  }
}

Gestion des erreurs (codes retour) des fonctions OrderSend() et OrderSendAsync()

la fonction CheckError() est ajoutée à l'implémentation de l'envoi de la commande. Exemple :

 void ModifyOrder( const string aSymbol, const double price, ulong & ticket )
{
   if ( ticket > 0 )
  {
     if ( OrderSelect ( ticket ) )
    {
       MqlTradeRequest request = { 0 };
       MqlTradeResult   result  = { 0 };
   
      request.action = TRADE_ACTION_MODIFY ;
      request.symbol = aSymbol;
      request.order  = ticket;
      request.price  = price;
      request.type_time = ORDER_TIME_DAY ;
  
       if ( OrderSend ( request, result ) )
      {
         if ( result.retcode == TRADE_RETCODE_PLACED ) 
        {
          ticket = result.order;
        }
         else
        {
          CheckError( result.retcode, "ModifyOrder: Ордер не модифицирован! Билет = " , ticket );
        }
      }
       else
      {
        CheckError( result.retcode, "ModifyOrder: Ордер не отослан! Билет " , ticket );
      }
    }
  }
}

La fonction CheckError() elle-même ( pas tous les codes de retour dans l'exemple )

 void CheckError( const uint ret_code, const string err_msg, const ulong a_ticket )
{
   switch ( ret_code )
  {
     case TRADE_RETCODE_TRADE_DISABLED :
                                           break ;
     case TRADE_RETCODE_MARKET_CLOSED :
                                           break ;
     case TRADE_RETCODE_NO_MONEY :
                                           break ; 
     case TRADE_RETCODE_PRICE_OFF :
                                           break ;   
     case TRADE_RETCODE_TOO_MANY_REQUESTS :
                                           break ;
     case TRADE_RETCODE_SERVER_DISABLES_AT : 
                                           break ;
     case TRADE_RETCODE_CLIENT_DISABLES_AT : 
                                           break ;
     case TRADE_RETCODE_INVALID_PRICE :      
                                           break ;
     case TRADE_RETCODE_INVALID :
                                           break ;                                                       
                
     default : Print ( err_msg, GetRetCode( ret_code ), "; Билет = " , a_ticket );  
             break ;            
  }
}

Voir la suite


Particularités :

Lors de l'achat de plus d'UN contrat avec une commande LIMIT avec une exécution ORDER_FILLING_IOC,

une commande dans l'historique peut être stockée en tant que ORDER_STATE_CANCELED si la commande est exécutée avec le premier volume,

et le second a échoué.

Exemple:

Acheter 3 contrats avec un ordre LIMIT avec une exécution ORDER_FILLING_IOC,

il y a la situation suivante :

1. Si nous avons acheté les trois contrats, alors la commande dans l'historique a l'état = ORDER_STATE_FILLED

2. Si nous n'avons rien acheté, alors dans l'état de l'historique = ORDER_STATE_CANCELED

3. Si nous avons acheté les deux premiers contrats (28449), mais n'avons pas acheté 1 contrat (28450), alors l'état dans l'historique = ORDER_STATE_CANCELED

4. Si nous n'avons pas acheté les deux premiers contrats (28449), mais en avons acheté 1 (28450), alors dans l'état historique = ORDER_STATE_PARTIAL

======= Fin de l'exemple ===================

Le nombre de transactions inefficaces (une transaction inefficace est une transaction qui n'a pas abouti à une transaction.

Le placement, la modification et la suppression d'un ordre) sur le marché à terme FORTS est limité à 2000 par séance de négociation complète

de 19h00 du jour en cours à 18h45 du lendemain. Pour dépassement - une amende de la Bourse

http://moex.com/n8725

Insectes:

1. Si une panne survient sur le serveur MT5 du broker ou sur la bourse, alors la commande

supprimer (modifier) le serveur de commande EXISTANT renvoie :

erreur 10013 = TRADE_RETCODE_INVALID = Demande invalide (Demande invalide)

2. Parfois, même en cas d'échec, lorsque vous essayez de passer un ordre en attente ou à cours limité, une erreur se produit - " L'instrument n'est pas disponible actuellement "

(ce n'est pas une faute de frappe, c'est le message)

Il n'y a pas de code retour pour le serveur d'échange dans la documentation !

 

Et si un régime n'est pas soutenu ? Pourquoi cela devrait-il vous interdire de commercer ?

Surtout si "ne prend pas en charge le mode de fixation des ordres Stop Limit" ? C'est le problème de ne pas pouvoir faire de commerce du tout.

© DESTRUCTION DANS LA TÊTE

 

C'est écrit au début :

IMPORTANT : Afin de ne pas "étirer" le sujet, si vous avez des commentaires,

ou avez des questions, créezun sujet distinctdans cette section(je ne répondrai pas ici).

P / S pour les personnes particulièrement "douées" :

Dans cette fonction, vous devez vérifier les paramètres suivants

que vous utiliserez dans votre EA. Voici un exemple :

.......................

 

Continué :

Fonctions utiles et fréquemment utilisées :

La fonction CheckError() elle-même (pas tous les codes de retour dans l'exemple)

.........................................................................

Explication des codes de retour :

string GetRetCode( const uint code )
{
  string retcode;
  
  switch( code )
  {
    case TRADE_RETCODE_REQUOTE: retcode = "Реквота";
         break;
    case TRADE_RETCODE_REJECT: retcode = "Запрос отвергнут";
         break;
    case TRADE_RETCODE_CANCEL: retcode = "Запрос отменен трейдером";
         break;
    case TRADE_RETCODE_PLACED: retcode = "Ордер размещен";
         break;
    case TRADE_RETCODE_DONE: retcode = "Заявка выполнена";
         break;
    case TRADE_RETCODE_DONE_PARTIAL: retcode = "Заявка выполнена частично";
         break;
    case TRADE_RETCODE_ERROR: retcode = "Ошибка обработки запроса";
         break;
    case TRADE_RETCODE_TIMEOUT: retcode = "Запрос отменен по истечению времени";
         break;
    case TRADE_RETCODE_INVALID: retcode = "Неправильный запрос";
         break;
    case TRADE_RETCODE_INVALID_VOLUME: retcode = "Неправильный объем в запросе";
         break;
    case TRADE_RETCODE_INVALID_PRICE: retcode = "Неправильная цена в запросе";
         break;
    case TRADE_RETCODE_INVALID_STOPS: retcode = "Неправильные стопы в запросе";
         break;
    case TRADE_RETCODE_TRADE_DISABLED: retcode = "Торговля запрещена";
         break;
    case TRADE_RETCODE_MARKET_CLOSED: retcode = "Рынок закрыт";
         break;
    case TRADE_RETCODE_NO_MONEY: retcode = "Нет достаточных денежных средств для выполнения запроса";
         break;
    case TRADE_RETCODE_PRICE_CHANGED: retcode = "Цены изменились";
         break;
    case TRADE_RETCODE_PRICE_OFF: retcode = "Отсутствуют котировки для обработки запроса";
         break;
    case TRADE_RETCODE_INVALID_EXPIRATION: retcode = "Неверная дата истечения ордера в запросе";
         break;
    case TRADE_RETCODE_ORDER_CHANGED: retcode = "Состояние ордера изменилось";
         break;
    case TRADE_RETCODE_TOO_MANY_REQUESTS: retcode = "Слишком частые запросы";
         break;
    case TRADE_RETCODE_NO_CHANGES: retcode = "В запросе нет изменений";
         break;
    case TRADE_RETCODE_SERVER_DISABLES_AT: retcode = "Автотрейдинг запрещен сервером";
         break;
    case TRADE_RETCODE_CLIENT_DISABLES_AT: retcode = "Автотрейдинг запрещен клиентским терминалом";
         break;
    case TRADE_RETCODE_LOCKED: retcode = "Запрос заблокирован для обработки";
         break;
    case TRADE_RETCODE_FROZEN: retcode = "Ордер или позиция заморожены";
         break;
    case TRADE_RETCODE_INVALID_FILL: retcode = "Указан неподдерживаемый тип исполнения ордера по остатку";
         break;
    case TRADE_RETCODE_CONNECTION: retcode = "Нет соединения с торговым сервером";
         break;
    case TRADE_RETCODE_ONLY_REAL: retcode = "Операция разрешена только для реальных счетов";
         break;
    case TRADE_RETCODE_LIMIT_ORDERS: retcode = "Достигнут лимит на количество отложенных ордеров";
         break;
    case TRADE_RETCODE_LIMIT_VOLUME: retcode = "Достигнут лимит на объем ордеров и позиций для данного символа";
         break;
    case TRADE_RETCODE_INVALID_ORDER: retcode = "Неверный или запрещённый тип ордера";
         break;
    case TRADE_RETCODE_POSITION_CLOSED: retcode = "Позиция с указанным POSITION_IDENTIFIER уже закрыта";
         break;
    default: retcode = "Нет кода возврата.";  
         break; 
  }
  return( retcode );
}

Recommandation:

Lors de la conception de conseillers pour FORTS, je ne recommande pas d'utiliser l'événement Tick, mais

il est préférable d'utiliser l'événement BookEvent

Exemples :

Ajout d'une coche :

(à utiliser UNIQUEMENT dans OnInit() )

  if ( !MarketBookAdd( _Symbol ) )
  {
    MessageBox( "Не добавлен стакан фьючерса " + _Symbol + "!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  } 

Suppression d'un abonnement à un verre :

void OnDeinit( const int reason )
{
  MarketBookRelease( _Symbol );
}

Obtenez les meilleurs ASK et BID et leurs volumes à partir du tumbler des prix :

double sell_price, buy_price;
long sell_volume, buy_volume;

//+------------------------------------------------------------------+
//| Expert Get Stakan values function                                |
//+------------------------------------------------------------------+ 
bool GetStakanValues( const string aSymbol, double &sell_price,
                      double &buy_price, long &sell_volume, long &buy_volume )
{
  MqlBookInfo book_price[];
  buy_price  = 0;
  sell_price = DBL_MAX;
  buy_volume = 0;
  sell_volume = 0;
  
//--- Get stakan
  if ( MarketBookGet( aSymbol, book_price ) )//getBook )
  {
    int size = ArraySize( book_price );
//---    
    if ( size > 0 )
    {
      double a_min_price = SymbolInfoDouble( aSymbol, SYMBOL_SESSION_PRICE_LIMIT_MIN );
      double a_max_price = SymbolInfoDouble( aSymbol, SYMBOL_SESSION_PRICE_LIMIT_MAX );
//---     
      for( int i = 0; i < size; i++ )
      {
        if ( book_price[i].type == BOOK_TYPE_SELL )
        {
          if ( book_price[i].price < sell_price )
          {
            sell_price = book_price[i].price;
            sell_volume = book_price[i].volume;  
          }
        }
        else
        if ( book_price[i].type == BOOK_TYPE_BUY ) //First buy - exit
        {
          buy_price = book_price[i].price;
          buy_volume = book_price[i].volume;
          break;
        }
      }
      if ( ( buy_price <= a_max_price ) && ( buy_price >= a_min_price ) &&
           ( sell_price <= a_max_price ) && ( sell_price >= a_min_price ) )
      {
        if ( sell_price == DBL_MAX ) sell_price = 0;
//---        
        if ( ( sell_price > 0 ) && ( buy_price > 0 ) )
        {
          return( true );
        }  
      }
    }
  }
//---
  if ( sell_price == DBL_MAX ) sell_price = 0;
//---   
  return( false); 
}

Appel de fonction :

Vérifiersi ( a_symbole == _Symbole ) est OBLIGATOIRE, cela garantit que c'est votre pile de prix qui a changé.

//+------------------------------------------------------------------+
//| Expert On Book event function                                    |
//+------------------------------------------------------------------+  
void OnBookEvent( const string &a_symbol )
{
  if ( a_symbol == _Symbol )
  {
    if ( GetStakanValues( _Symbol, sell_price, buy_price, sell_volume, buy_volume ) )
    {
      //you code
    }
  }
}
 

MERCI ! !!)

 

Caractéristiques spéciales :

Formules pour le calcul et l'attribution de points pour l'inefficacité et la défectuosité

transactions dans la pièce jointe.

P/S Les règles et les points sont modifiés assez souvent :(

Dossiers :
 

Fonctions utiles et fréquemment utilisées:

La fonction SetStDayTime() renvoie l'heure de début de la journée de négociation (au moment de la demande).

La fonction GetExgangeFee() renvoie la commission de change et le nombre de transactions pour la journée de négociation (au moment de la demande) :

//+------------------------------------------------------------------+
//|                                                       Tr_fee.mq5 |
//|                                          Copyright 2015, Mikalas |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Mikalas"
#property link      "https://www.mql5.com"
#property version   "1.00"
//
input long   TrPoint   = 1;              //Балл за транзакцию
input long   DealPoint = 40;             //Балл за сделку
//
datetime start_day_time;
//
//+------------------------------------------------------------------+
//| Expert Set start day time function                               |
//+------------------------------------------------------------------+
datetime SetStDayTime()
{
  MqlDateTime  dt_str; 
  TimeTradeServer( dt_str );
//---
  if ( ( dt_str.day_of_week == 0 ) || ( dt_str.day_of_week == 6 ) ) return( datetime( 0 ) );  
//---
  string time_str = IntegerToString( dt_str.year ) + "." + IntegerToString( dt_str.mon ) +
                    "." + IntegerToString( dt_str.day ) + " 19:00:00";
  ulong cur_day = ulong( StringToTime( time_str ) );                     

  if ( ( dt_str.hour >= 19 ) && ( dt_str.hour <= 23 ) )
  {
    return( StringToTime( time_str ) );
  }
  else
  {
    ulong one_day = 24 * 60 * 60;
//---      
    if ( dt_str.day_of_week == 1 )
    {
      cur_day -= one_day * 3;
    }
    else
    {
      cur_day -= one_day;
    }
    return( datetime( cur_day ) );
  }  
  return( datetime( 0 ) );
}
//+------------------------------------------------------------------+
//| Expert calc deals fee function                                   |
//+------------------------------------------------------------------+
double GetExgangeFee( const datetime start_time, long& deals )
{
  double all_fee = 0.0;
  ulong deal_ticket;
  deals = 0;
//---  
  if ( HistorySelect( start_time, TimeTradeServer() ) )
  {
    int deals_total = HistoryDealsTotal();
//---   
    if ( deals_total > 0 )
    {
      for ( uint i = 0; i < uint( deals_total ); i++ )
      {
        deal_ticket = HistoryDealGetTicket( i );
//---        
        if ( deal_ticket > 0 )
        {
          ulong order_ticket = ulong( HistoryDealGetInteger( deal_ticket, DEAL_ORDER ) );
          
          if ( order_ticket > 0 )
          {
            deals++;
            all_fee += HistoryDealGetDouble( deal_ticket, DEAL_COMMISSION );
          }  
        }
      }
      return( MathAbs( all_fee ) );
    }  
  }
  return( 0 );
}
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
  long a_deals;
  start_day_time = SetStDayTime();
//---  
  if ( ulong( start_day_time ) == 0 )
  {
    MessageBox( "Не установлено время начала торгового дня!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  } 
  Print( "Exgange Fee = ", GetExgangeFee( start_day_time, a_deals ), "; Deals = ", a_deals );
  return( INIT_SUCCEEDED );
}
 
Михаил:

Fonctions utiles et fréquemment utilisées:

La fonction SetStDayTime() renvoie l'heure de début de la journée de négociation (au moment de la demande).

La fonction GetExgangeFee() renvoie la commission de change et le nombre de transactions pour la journée de négociation (au moment de la demande) :

Il s'agit d'un candidat sans précédent au titre de "Hindu Coder - 2015".

SetStDayTime() est résolu avec deux lignes. Mais bien sûr, vous n'avez pas besoin de...

 

Michael, merci pour vos articles !

L'invention de certaines bicyclettes par moi est annulée ;)

 
Михаил:

Je dois le faire.

Et comment faites-vous cela ?

Vous devez travailler avec la représentation numérique du temps.

datetime a=TimeTradeServer(); 

L'heure de début de la journée :

datetime r=(a/86400)*86400

L'heure à 19h00 aujourd'hui :

datetime r=(a/86400)*86400+19*3600;

Si l'heure d'aujourd'hui à 19h00 est supérieure à l'heure actuelle, alors nous avons besoin du 19h00 d'hier :

if(r>a)r-=86400;

Ici, si nous devons sauter le week-end, nous vérifions le jour de la semaine, si c'est dimanche, nous soustrayons 86400*2, si c'est samedi, nous soustrayons 86400 (pour obtenir vendredi).

Ça donne quelque chose comme ça.

Ensuite, pour l'affichage, si nécessaire, convertissez en une chaîne de caractères :

TimeToStr(r)
 
Михаил:

Et la grande année ?

Maintenant, traduisez vos pensées en code concret.

Réécrivez ma fonction à votre façon, et comme vous l'avez dit en DEUX lignes !

Et l'année bissextile ? Tout va s'arranger.

Faites-le vous-même, je ne veux pas comprendre complètement votre code, au cas où je manquerais quelque chose, quelle joie vous aurez.