Erreurs, bugs, questions - page 577

 
papaklass:

...

Ok. Votre position est claire.
 

Il est même difficile d'imaginer un tel conseiller expert qui n'aurait pas la puissance d'un noyau dans la vie réelle. Par exemple, si dans le testeur le conseiller expert fait un passage d'un symbole par jour sur l'historique d'une année (c'est trop ! Peut-être devrions-nous réécrire le code !), alors dans la vie réelle, il chargera le CPU en moyenne 1/250 de la puissance = 0,4%.

Pour un EA sur dix symboles - vous obtenez une charge moyenne de 4%. Il n'y a pas beaucoup d'intérêt à charger les autres noyaux.

 

Quant à l'idée de Konstantin(Lizar), je pense qu'elle est bonne. Mais pour ce type de solution, nous devons séparer les événements qui proviennent directement du graphique et ceux qui sont générés de manière personnalisée. Pour les événements personnalisés, nous pouvons avoir deux files d'attente d'événements et deux gestionnaires d'événements, quelque chose comme OnUserEvents.

Et un ajout intéressant aux événements personnalisés serait la possibilité de spécifier explicitement leur priorité (disons de 0 à 9), ce qui pourrait permettre à l'utilisateur de contrôler la préemption et le traitement de certains événements. Par exemple, une telle fonctionnalité permettrait d'exécuter les événements ayant une valeur inférieure et de les retirer de la file d'attente ayant une valeur supérieure (si la file d'attente est pleine d'événements plus importants, aucun nouvel événement ne sera mis en file d'attente).

papaklass:

Je n'ai jamais fait de développement de logiciels, donc je ne peux pas parler le langage technique des développeurs de logiciels. Je vais décrire ce que j'aimerais obtenir de mon ordinateur à 4 cœurs et de MT5. En général, cela ressemble à ceci :


La manipulation de plusieurs outils est désormais possible et les développeurs ont créé une solution parfaitement exploitable.

2. Sur le travail du testeur et un tas de noyaux. Il s'agit d'un cas particulier et il n'est pas correct de comparer ce mécanisme avec le trading réel. L'essence de la résolution du problème du testeur est qu'avec plusieurs variantes de conseiller expert (ou plutôt un conseiller expert + de nombreux ensembles de paramètres uniques), il est raisonnable de répartir les calculs entre tous les cœurs/agents disponibles. Nous obtenons donc une asynchronie pour l'ensemble des tâches, mais du point de vue d'un agent individuel, tout est synchronisé.

3. En ce qui concerne le multithreading, il ne s'agit pas de traiter plusieurs outils en même temps, mais de traiter plusieurs événements en même temps (et au sein d'un seul agent spécifique). Cela n'était présent dans aucune version du terminal.

Les développeurs sont également compréhensibles : trop de frais généraux, un mélange trop "hétéroclite" d'utilisateurs, trop de problèmes de synchronisation des données auxquelles un conseiller expert "multithread" aura accès, etc.

D'autre part, l'idée avec les événements n'est pas poussée jusqu'à sa conclusion logique. D'accord, il est coûteux et problématique d'implémenter le "multithreading" mais il est possible de paralléliser au maximum les processus et les flux d'information au sein du terminal lui-même + créer un ensemble de gestionnaires suffisants pour résoudre le nombre maximum de tâches (et avec un ensemble normal de paramètres).

 
papaklass:

Mon Expert Advisor sur M5, sur la période 04.01.2010 - 01.09.2011 sur 12 devises fait un seul passage en 1436 sec (24 minutes) et dans le même temps fait 5687 trades. Un seul noyau est chargé, les trois autres sont inactifs. En d'autres termes, à chaque passage, je perds 3/4 du temps car la plateforme n'utilise pas la puissance de l'ordinateur. Il s'agit d'un inconvénient important de la plateforme lors du débogage d'une stratégie. Les cœurs ne sont pleinement utilisés que pendant l'optimisation. Mais l'optimisation est beaucoup plus rare que les courses simples. Et beaucoup de temps est perdu sur des parcours uniques.

L'approche "perdre 3/4 du temps" indique que vous pensez que l'utilisation du multithreading n'est qu'une occasion manquée et un défaut évident des développeurs.

Malheureusement, le multithreading sur les tâches séquentielles (et une seule passe de testeur est une tâche séquentielle) n'est pas donné gratuitement. En réalité, le multithreading entraîne des pertes énormes (parfois multiples) pour la synchronisation des processus. En fait, tous les accès aux ressources partagées doivent être liés à des synchroniseurs.

Nous avons délibérément déplacé le testeur hors du terminal, dans un processus distinct, afin de lui permettre de travailler dans un seul thread, sans verrou, pendant 99 % du temps de test. Cela a permis un gain de vitesse significatif.

La suggestion "poussons le multitâche dans chaque EA" provient d'une incompréhension totale du coût (ralentissement total) du multithreading dans ce cas et des conséquences (ralentissement + faire sauter le toit de 99% des développeurs non professionnels).


Nous avons résolu efficacement les problèmes d'application du multitâche dans le terminal, le testeur et avons permis une mise à l'échelle presque illimitée de la puissance dans les modes agent distant et réseau en nuage MQL5.


Si j'ouvre 12 graphiques et que je place un indicateur sur chacun d'eux, je peux voir comment le terminal est en retard à certains moments. À en juger par les messages sur le forum, cela n'arrive pas qu'à moi. Et si je dois augmenter le nombre d'instruments et d'indicateurs, le terminal se bloque. Et un noyau sera utilisé, tandis que le reste se reposera. Si nous répartissons les processus terminaux entre les cœurs, c'est-à-dire si nous utilisons pleinement la puissance de l'ordinateur, nous serons en mesure de résoudre des tâches à un autre niveau. C'est ce que je veux dire.

S'il existe 12 chartes différentes avec des symboles différents, cela signifie que chaque symbole de chaque charte suit évidemment son propre fil sans affecter les autres.

Si les graphiques commencent à ralentir, la raison est banale - l'un des indicateurs est très peu rentable. Dans ce cas, le multitâche ne sert à rien, car la racine est le travail du programmeur, qui écrit des indicateurs dans sa tête, sans se soucier de l'efficacité.

 

Je n'arrive pas à obtenir le graphique inversé, quelque chose ne va pas, la nouvelle barre se bloque sur cette variante.

l'indicateur original avec lequel j'ai bricolé est joint à ce document

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[])
  {
//---- проверка количества баров на достаточность для расчета
   for(int numb=0; numb<8; numb++) if(BarsCalculated(RSI_Handle[numb])<rates_total) return(RESET);
   if(rates_total<min_rates_total) return(RESET);

//---- объявления локальных переменных 
   int to_copy;

//---- расчеты необходимого количества копируемых данных
   if(prev_calculated>rates_total || prev_calculated<=0)// проверка на первый старт расчета индикатора
      to_copy=rates_total-1;                   // стартовый номер для расчета всех баров
   else to_copy=rates_total-prev_calculated+1; // стартовый номер для расчета новых баров
   
//---- копируем вновь появившиеся данные в массивы
   if(CopyBuffer(RSI_Handle[0],0,0,to_copy,Buffer1)<=0) return(RESET);
   if(CopyBuffer(RSI_Handle[1],0,0,to_copy,Buffer2)<=0) return(RESET);
   if(CopyBuffer(RSI_Handle[2],0,0,to_copy,Buffer3)<=0) return(RESET);
   if(CopyBuffer(RSI_Handle[3],0,0,to_copy,Buffer4)<=0) return(RESET);
   if(CopyBuffer(RSI_Handle[4],0,0,to_copy,Buffer5)<=0) return(RESET);
   if(CopyBuffer(RSI_Handle[5],0,0,to_copy,Buffer6)<=0) return(RESET);
   if(CopyBuffer(RSI_Handle[6],0,0,to_copy,Buffer7)<=0) return(RESET);
   if(CopyBuffer(RSI_Handle[7],0,0,to_copy,Buffer8)<=0) return(RESET);
   
   //мой кусок отсель   
   if (Reverse)
      {
         int start=prev_calculated;
         for(int i=start;i<rates_total;i++)
            {
               Buffer1[i]=100-Buffer1[i];
               Buffer2[i]=100-Buffer2[i];
               Buffer3[i]=100-Buffer3[i];
               Buffer4[i]=100-Buffer4[i];
               Buffer5[i]=100-Buffer5[i];
               Buffer6[i]=100-Buffer6[i];
            }
         Buffer1[0]=100-Buffer1[0];
         Buffer2[0]=100-Buffer2[0];
         Buffer3[0]=100-Buffer3[0];
         Buffer4[0]=100-Buffer4[0];
         Buffer5[0]=100-Buffer5[0];
         Buffer6[0]=100-Buffer6[0];
       }  
   //досель    

//----     
   return(rates_total);
  }
//+------------------------------------------------------------------+

Dossiers :
Multi_RSI.mq5  15 kb
 

Veuillez m'indiquer quel est le problème.

J'écris un programme multidevises

J'obtiens la poignée de l'indicateur MA

maHandle_EURUSD=iMA("EURUSD",PERIOD_H1,MA_Period_EURUSD,MA_Shift_EURUSD,MODE_SMA,PRICE_CLOSE);

maHandle_GBPUSD=iMA("GBPUSD",PERIOD_H1,MA_Period_GBPUSD,MA_Shift_GBPUSD,MODE_SMA,PRICE_CLOSE); 

Je fais la même chose pour les 10 autres devises autorisées dans le championnat, mais je reçois l'erreur 4801 pendant le test, les 12 devises sont dans l'historique (je pense).

Je teste sur le graphique EURUSD

le conseiller expert teste le GBPUSD (je l'ai réglé ainsi dans les paramètres, afin de l'optimiser).

 
Lazarev:

Veuillez m'indiquer quel est le problème.

J'écris un programme multidevises

J'obtiens la poignée de l'indicateur MA

Je fais la même chose pour les 10 autres devises autorisées dans le championnat, mais je reçois l'erreur 4801 pendant le test, les 12 devises sont dans l'historique (je pense).

Je teste sur le graphique EURUSD

le conseiller expert teste le GBPUSD (je l'ai réglé ainsi dans les paramètres, afin de l'optimiser).

Je dois ajouter des symboles àSymbolSelect Market Watch
 

papaklass:

Maintenant, répondez à une question aussi simple ....

Je vais répondre encore plus simplement, même si ce n'est pas poliment.

Malheureusement, vous êtes complètement hors sujet et faites des déclarations qui ne montrent que des idées superficielles sur les processus.

Je crains que la plupart de nos arguments techniques ne soient pas compris, ni même le problème fondamental de la synchronisation et de la perte sur sa fourniture.

Il n'est donc pas nécessaire de faire des demandes du type "vous nous dites vos arguments et nous spéculons", la situation est parfaitement claire.

 

Je ne trouve pas de réponses à ces questions pour un débutant :

1) Lorsque l'on ajoute un autre élément à un tableau dynamique, est-il nécessaire de le développer en utilisant ArrayResize ?

2) Existe-t-il une fonction dans MQL5 pour supprimer un élément (un élément au milieu d'un tableau, par exemple) d'un tableau dynamique i ? Si non, quelle est la meilleure façon de le faire ?

Документация по MQL5: Основы языка / Типы данных / Объект динамического массива
Документация по MQL5: Основы языка / Типы данных / Объект динамического массива
  • www.mql5.com
Основы языка / Типы данных / Объект динамического массива - Документация по MQL5
 
Fia:

En tant que novice, je ne trouve aucune réponse à ces questions :

1) Lorsque vous ajoutez un autre élément à un tableau dynamique, devez-vous le développer avec ArrayResize ?

Vous faites la taille du tableau avec une certaine réserve, lorsque vous approchez de la limite, vous augmentez la taille. Il n'y a pas de redimensionnement automatique et d'ajout à la fin. Regardez l'exemple de la fonction ArrayInitialize()