Questions OrderSend() - page 5

 

Apparemment, je n'ai pas expliqué très clairement le problème précédent. Laissez-moi essayer à nouveau.

Au cours de l'année dernière, la description de la liste de valeurs de l'énumérationENUM_ORDER_TYPE_FILLING a été modifiée au moins trois fois. La description précédente se présentait comme suit

ENUM_ORDER_TYPE_FILLING

Identifiant

Description

COMMANDE_REMPLISSAGE_FOK

Une transaction ne peut être exécutée que dans le volume spécifié et à un prix égal ou supérieur à celui spécifié dans l'ordre. S'il n'y a pas assez d'offre sur le marché à ce moment-là pour le symbole de l'ordre, l'ordre ne sera pas exécuté. Ce type de remplissage est utilisé dans le mode d'exécution SYMBOL_TRADE_EXECUTION_INSTANT ouSYMBOL_TRADE_EXECUTION_REQUEST.

COMMANDE_REMPLISSAGE_IOC

Un accord pour exécuter une transaction au volume maximum disponible sur le marché dans le volume spécifié dans l'ordre et à un prix égal ou supérieur à celui spécifié dans l'ordre. Dans ce cas, aucune commande supplémentaire ne sera passée pour le volume manquant. Ce type de remplissage peut être disponible uniquement dans les modes d'exécution SYMBOL_TRADE_EXECUTION_MARKET etSYMBOL_TRADE_EXECUTION_EXCHANGE selon les paramètres du serveur de négociation.

RETOUR_REMPLISSAGE_ORDRE

Accord pour exécuter une transaction sur le volume maximum disponible sur le marché dans le volume spécifié dans l'ordre et à un prix égal ou supérieur à celui spécifié dans l'ordre. Dans ce cas, une commande supplémentaire sera passée pour le volume manquant au prix spécifié dans cette commande. Ce type de remplissage est utilisé uniquement pour les ordres en attente (TRADE_ACTION_PENDING).

Comme nous pouvons facilement le constater, il existe une correspondance biunivoque entre ORDER_FILLING_RETURN et les ordres en attente, à savoir : ORDER_FILLING_RETURN ne pouvait être appliqué qu'aux ordres en attente et le champ type_filling de tous les ordres en attente ne pouvait être rempli qu'avec la valeur de ORDER_FILLING_RETURN.

Pour les ordres de marché(action==TRADE_ACTION_DEAL), le champ type_filling aurait dû être rempli en fonction des modes d'exécution définis côté serveur.

Nous avions donc un certain paradigme : s'il y avait un ordre en attente,ORDER_FILLING_RETURN ; s'il y avait un ordre au marché, ORDER_FILLING_FOK ou ORDER_FILLING_IOC (selon le mode).

Maintenant, tout est un peu chamboulé, à savoir :

ENUM_ORDER_TYPE_FILLING

Identifiant

Description

COMMANDE_REMPLISSAGE_FOK

Cette politique d'exécution des ordres signifie que l'ordre ne peut être exécuté qu'à hauteur du volume spécifié. S'il n'y a pas assez de volume de l'instrument financier sur le marché à ce moment-là, l'ordre ne sera pas exécuté. Le volume requis peut être compilé à partir de plusieurs offres actuellement disponibles sur le marché.

COMMANDE_REMPLISSAGE_IOC

Indique l'accord pour exécuter une transaction au volume maximum disponible sur le marché dans le cadre du volume spécifié dans l'ordre. Si l'exécution complète n'est pas possible, l'ordre sera exécuté à hauteur du volume disponible, et le volume non exécuté sera annulé.

RETOUR_REMPLISSAGE_ORDRE

Ce mode est uniquement utilisé pour les commandes ORDER_TYPE_BUY_LIMIT et ORDER_TYPE_SELL_LIMIT. En cas d'exécution partielle, l'ordre limité avec le volume restant n'est pas supprimé mais reste en vigueur.

Pour les ordres ORDER_TYPE_BUY_STOP_LIMIT et ORDER_TYPE_SELL_STOP_LIMIT, l'ordre à cours limité ORDER_TYPE_BUY_LIMIT/ORDER_TYPE_SELL_LIMIT correspondant avec le type d'exécution ORDER_FILLING_RETURN sera créé lors de l'activation.

La restriction concernant l'utilisation de ORDER_FILLING_FOK et ORDER_FILLING_IOC uniquement avec les ordres au marché est supprimée. Il n'y a pas non plus de restriction sur l'utilisation de ORDER_FILLING_FOK et ORDER_FILLING_IOC avec les ordres au marché selon le mode d'exécution défini sur le serveur. Il existe une restriction concernant l'utilisation de ORDER_FILLING_RETURN uniquement avec les ordres à cours limité et stop_limit .

Ma question est donc la suivante : est-il acceptable d'utiliser ORDER_FILLING_FOK et ORDER_FILLING_IOC pour tous les ordres (au marché et en attente), y compris les ordres à cours limité et stop_limit ? Quelqu'un a-t-il compris les changements ?

 

La bibliothèque standard dispose de cette méthode (schéma) :

bool CTrade::PositionClose(const string symbol,ulong deviation)
  {
   do
     {
      //--- checking
      if(PositionSelect(symbol))
        {
         if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
           {
            //--- prepare request for close BUY position
            m_request.type =ORDER_TYPE_SELL;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_BID);
           }
         else
           {
            //--- prepare request for close SELL position
            m_request.type =ORDER_TYPE_BUY;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_ASK);
           }
        }
      else
        {
         //--- position not found
         m_result.retcode=retcode;
         return(false);
        }
      m_request.action      =TRADE_ACTION_DEAL;
      m_request.volume      =PositionGetDouble(POSITION_VOLUME);
      //--- check volume
      double max_volume=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
      if(m_request.volume>max_volume)
        {
         m_request.volume=max_volume;
         partial_close=true;
        }
      else
         partial_close=false;
      //--- order send
      if(!OrderSend(m_request,m_result))
        {
         if(--retry_count!=0) continue;
         if(retcode==TRADE_RETCODE_DONE_PARTIAL)
            m_result.retcode=retcode;
         return(false);
        }
      retcode=TRADE_RETCODE_DONE_PARTIAL;
      if(partial_close) Sleep(1000);
     }
   while(partial_close);
   return(true);
  }

Ici, dans le cas où le volume de la position est supérieur auvolume maximum pour effectuer une transaction, des tentatives successives de fermeture partielle de la position sont effectuées.

Après un appel réussi de la fonction OrderSend(), un délai de quelques secondes est fixé, puis la fonctionPositionSelect() est appelée dans le corps de la boucle do-while. C'est-à-dire qu'il est supposé que si le serveur accepte avec succès un ordre de marché, une seconde est suffisante pour mettre à jour les données sur la position ouverte dans le terminal de base et obtenir les données de position mises à jour (dans cet exemple - le volume de la position) à l'itération suivante. Mais il y a deux ans, le délai dans la même méthode avant d'appeler la fonction PositionSelect() était de trois secondes. La question est donc :

Une seconde est-elle suffisante dans tous les cas pour garantir qu'après un appel réussi à OrderSend(), la base de données du terminal est assurée de recevoir les données de position mises à jour (et donc de permettre au volume de position restant d'être traité correctement du côté du terminal) ? Quel est le délai maximum dans lequel la base de données terminale doit être assurée de recevoir les données de position actualisées dans ce cas ?

 

Le championnat dispose d'une telle règle :

Les conditions commerciales seront aussi proches de la réalité que possible:

  • Temps de traitement des demandes de commerce de 2 à 7 secondes
En réalité, avec un courtier (après le retrait), le traitement a pris environ 3 secondes (ouverture-fermeture-modification), ce qui m'a fait passer immédiatement à NDD.
 
Karlson:

Le championnat dispose d'une telle règle :

Les conditions commerciales seront aussi proches de la réalité que possible:

  • temps de traitement de 2 à 7 secondes

OK, merci pour le conseil ! Il s'avère qu'une seconde n'est pas suffisante pour que la base de données du terminal reçoive les données de position mises à jour après un appel réussi de la fonction OrderSend() ?

De cette conclusion, il résulte que la méthode de la Standard Library que j'ai citée ne garantit pas du tout que la position sera inversée au lieu d'être fermée. C'est-à-dire que si la méthode PositionClose() retarde l'itération suivante d'une seconde, et que les demandes de transaction peuvent prendre 2 à 7 fois plus de temps à traiter, nous ne pouvons pas exclure que pendant les nouvelles itérations, la fonctionPositionSelect() recevra les informations précédentes sur l'état de la position du terminal de base et bombardera le serveur d'ordres identiques, dont le volume total dans ce cas sera plus grand que lemontant initial de la position en cours de fermeture.

Pourquoi alors y a-t-il un délai d'une seconde dans la méthode PositionClose(), si elle permet de retourner la position au lieu de la fermer ? Et ce n'est pas compatible avec les"conditions commerciales, aussi proches que possible des conditions réelles" ?

En général, j'ai besoin de plus d'informations sur la durée pendant laquelle la base de données du terminal, après un appel réussi de la fonction OrderSend(), est assurée de recevoir les données de position mises à jour, et quelle est la raison du retard d'une seconde dans la méthode standard PositionClose().

 
Commençons par le fait que
if(PositionSelect(symbol))

ne garantit rien. Il ne peut pas être utilisé.

Deuxièmement, aucune garantie n'est fournie pour la mise à jour des données du terminal. Vous devez vous-même configurer un TradeContextBusy artificiel et attendre que tous vos ordres soient traités.
Vous ne pouvez pas le faire immédiatement et passer directement à MQL5. Il n'y a pas de garantie de temps.

 

sergeev:

начнем с того, что

if(PositionSelect(symbol))

ne garantit rien. Il ne peut pas être appliqué.

Deuxièmement, il n'y a aucune garantie de mise à jour des données du terminal - vous devez organiser vous-même un TradeContextBusy artificiel et attendre que tous vos ordres soient traités.
Vous ne pouvez pas utiliser MQL5 directement et directement. Il n'y a pas de garantie de temps.

Oui, je vais devoir continuer à réfléchir. Il s'avère que j'aurais dû prendre la méthode standard de la bibliothèque comme exemple pour le recyclage.

Pouvez-vous me dire si une transaction apparaît dans l'historique avec l'indication

DEAL_ENTRY_OUT

Sortie du marché

cela signifie-t-il que toutes les informations contenues dans la base de données du terminal ont été automatiquement modifiées (mises à jour à l'état actuel) ? Ou bien la transaction peut déjà apparaître dans l'historique et les informations sur la position ne seront toujours pas mises à jour ? En d'autres termes, la question est intéressante : les informations sur les transactions dans l'historique et les informations sur les positions correspondantes changent-elles simultanément ? Ou, dans ce cas, les transactions et les positions sont également mises à jour dans le terminal de manière asynchrone ? Je n'ai pas réussi à l'attraper dans l'article de Rosh - d'après ce que j'ai compris, l'asynchronie entre la mise à jour de la base du terminal et le retour du résultat de la demande de transaction y est décrite.

 

Le modèle d'échange de données dans le terminal est asynchrone, comme vous l'avez remarqué.

Ainsi, lors des opérations (récupération des propriétés des ordres/opérations/positions), nous devons analyser le succès de la récupération des données. Et en cas d'erreur (faux/0), terminez l'analyse de la logique de trading.

Tous les ordres OrdSend exécutés et non confirmés doivent être mémorisés et attendre l'apparition de l'ordre, bloquant l'envoi du nouvel ordre lui-même s'il n'y a pas encore de réponse de l'envoi précédent.

Et, par exemple, il serait préférable de remplacer PositionSelect par une construction

for(int i=PositionsTotal()-1;i>=0;i--) 
{
  if(PositionGetSymbol(i)==Symbol())
  {
    ....
  }

En général, la logique de négociation doit être asynchrone. Comme le terminal est asynchrone, le serveur MT et le serveur du fournisseur de liquidités sont asynchrones.

La tâche de vérifier la synchronisation incombe entièrement au programmeur MQL.

Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций
Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций
  • www.mql5.com
Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций - Документация по MQL5
 

Je n'ai eu aucun problème à utiliser cette réponse lors du dernier championnat.

https://www.mql5.com/ru/forum/4342#comment_88688

Дублирование запросов на открытие позиций.
Дублирование запросов на открытие позиций.
  • www.mql5.com
Дублирование запросов на открытие позиций.
 
sergeev:

Et, par exemple, il serait préférable de remplacer PositionSelect par la construction

for(int i=PositionsTotal()-1;i>=0;i--) 
{
  if(PositionGetSymbol(i)==Symbol())
  {
    ....
  }

Veuillez expliquer, si ce n'est pas difficile, quel est l'avantage d'utiliserPositionsTotal() + PositionGetSymbol() par rapport à PositionSelect()? Les trois fonctions accèdent à la même base terminale, et les fonctions PositionGetSymbol() et PositionSelect() peuvent échouer. C'est-à-dire que si la position existe dans la base terminale, tant la fonction PositionSelect() que la construction proposée peuvent échouer. Vous devez encore vérifier le code d'erreur.

Quelles sont les particularités/fiabilité de votre construction ? Je n'arrivais toujours pas à comprendre.

Документация по MQL5: Торговые функции / PositionSelect
Документация по MQL5: Торговые функции / PositionSelect
  • www.mql5.com
Торговые функции / PositionSelect - Документация по MQL5
 

Je me creuse la tête... l'arrêt ne se met pas en place... et beaucoup d'erreurs. voici ce qu'il reste de l'expérience, et ça ne marche plus.

void OnTick(){ if(PositionsTotal()<1){OPEN();}}

bool OPEN(){
             MqlTradeRequest request;
             MqlTradeResult result;
             

             request.symbol       = _Symbol;
             request.action       = TRADE_ACTION_DEAL;
             request.type_filling = ORDER_FILLING_FOK;
             request.deviation    = 100;
             request.volume       = NormalizeDouble(2,2);
             request.type         = ORDER_TYPE_BUY;
             request.price        = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
             request.tp           = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK) + 500*_Point,_Digits);
             request.sl           = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK) - 500*_Point,_Digits);

             OrderSend(request,result);     
                        
             if(result.retcode==10009 || result.retcode==10008)  Print("Succsesful open");
             else                                               Print("Error open: ",DoubleToString(GetLastError(),0),"  response code: ",result.retcode);
    
   return(true);}

Si vous faites cela, il n'y a pas d'erreur, mais le stop-loss n'est toujours pas défini.

MqlTradeRequest request={0};MqlTradeResult result={0};