Caractéristiques du langage mql5, subtilités et techniques - page 33

 
Artyom Trishkin:

Lesurligné peut renvoyer 0. BCS est tombé dessus.

Ouais, des courtiers véreux. Ils y mettaient aussi des nombres négatifs.

Il serait bon que les développeurs aient une limite de la plage de valeurs possibles de chaque paramètre lorsque les courtiers définissent les symboles.

 
Artyom Trishkin:

Qu'est-ce qui ne va pas exactement ? C'était la question - qu'est-ce que je fais mal pour obtenir des données d'indicateurs à partir d'une période non native ?

Exemple : L'indicateur est exécuté sur M1, et les données de AO doivent être obtenues sur M5. Ainsi, alors que nous avons une limite>1 (l'historique doit être recalculé), l'AO de M5 renvoie des zéros en l'absence d'erreur de données. Dès que l'historique est calculé (limite==0), les données commencent à arriver de AO avec M5.

Pour commencer, vous n'avez pas besoin de faire de telles entrées :

periodForWork=PeriodForWork;

Au début, je pensais que tu assignais une variable à sa propre valeur.

Suivant :

size_ao=CopyBuffer(handle_ao,0,0,count,array_ao);

Il n'est pas nécessaire de faire une copie pendant l'initialisation. L'initialisation ne sert pas à cela. De plus, cet enregistrement n'aura pas de sens si les données sont demandées par des TF plus anciennes qui, au moment de la demande de OnInit(), ne seront pas encore calculées.

ArraySetAsSeries(BufferAO,true);

Mais cet enregistrement est suffisant pour n'être effectué qu'une seule fois au stade de l'initialisation.

En outre... hum... subjectivement, ce n'est pas comme ça que je le ferais.

J'aime diviser le programme en :

1. Première exécution (analyse de l'historique) ;

2. Courses ultérieures :

2.1. chaque coche ;

2.2. la barre formée ;

I.e :

if( prev_calculated > 0 )             // Не первый запуск
{
 if( rates_total <= prev_calculated ) // Новый бар не сформирован
  {
  }
 else                                 // Новый бар сформирован
  {
  }
}
else                                  // Первый запуск
{
}

Et seulement après - cycle de calcul principal (fonction).

Vos fonctions de copie donnent des erreurs non informatives. Le code n'est pas très bon.

Il n'y a pas de contrôle de la synchronisation des données de l'ancien TF.

Et la chose la plus importante ici est de comprendre la séquence. Je conseille de créer un indicateur de test, pour qu'il ne demande que les données du TF principal au premier démarrage et pour comprendre comment la copie est faite. C'est à dire de le supprimer du début du code :

ArraySetAsSeries(array_ao,true);

Et annuler le premier et le dernier élément du tableau. Et seulement ensuite, si nécessaire, changer la direction de l'indexation.

 
Bref, commencez par là :
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
input   ENUM_TIMEFRAMES inpTimeframe=PERIOD_M5;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int _handle;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   _handle=iAO(_Symbol,inpTimeframe);
   if(_handle==INVALID_HANDLE)
     {
      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),"! Хэндл индикатора iAO ТФ "+EnumToString(inpTimeframe)+" не получен!");
      return( INIT_FAILED );
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//--- Массив-приемник значений индикатора
   double ao[];
//---
   if(prev_calculated>0)
     {

     }
   else                                        // Если первый запуск
     {
      //--- Количество просчитанных баров старшего ТФ
      int bars;
      if(( bars=BarsCalculated(_handle))<0 || !(bool)SeriesInfoInteger(_Symbol,inpTimeframe,SERIES_SYNCHRONIZED))
         return( 0 );
      //--- 
      int num=CopyBuffer(_handle,0,0,bars,ao);
      //---
      if(num<0)
        {
         Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": Запрашиваемая таймсерия еще не построена!");
         return( 0 );
        }
      else if(num!=bars)
        {
         Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": Скопированы не все данные (",num," из ",bars,")");
         return( 0 );
        }
      //---
      Print(__FUNCTION__,": Успех! Скопировано ",num," из ",bars," значение индикатора АО ТФ "+EnumToString(inpTimeframe));
     }
//---
   return( rates_total );
  }
//+------------------------------------------------------------------+
 
Alexey Kozitsyn:

Pour commencer, vous n'avez pas besoin de faire de telles entrées :

J'ai d'abord pensé que vous assigniez à une variable sa propre valeur.

Suivant :

Il n'est pas nécessaire de faire une copie pendant l'initialisation. L'initialisation ne sert pas à cela. De plus, cet enregistrement n'aura pas de sens si les données sont demandées par des TF plus anciennes qui, au moment de la demande de OnInit(), ne seront pas encore calculées.

Mais cet enregistrement est suffisant pour n'être effectué qu'une seule fois au stade de l'initialisation.

En outre... hum... subjectivement, ce n'est pas comme ça que je le ferais.

J'aime diviser le programme en :

1. Première exécution (analyse de l'historique) ;

2. Courses ultérieures :

2.1. chaque coche ;

2.2. la barre formée ;

I.e :

Et seulement après - cycle de calcul principal (fonction).

Vos fonctions de copie donnent des erreurs non informatives. Le code n'est pas très bon.

Il n'y a pas de contrôle de la synchronisation des données de l'ancien TF.

Et la chose la plus importante ici est de comprendre la séquence. Je conseille de créer un indicateur de test, pour qu'il ne demande que les données du TF principal au premier démarrage et pour comprendre comment la copie est faite. C'est à dire de le supprimer du début du code :

Et annuler le premier et le dernier élément du tableau. Et seulement ensuite, si c'est nécessaire, changer la direction de l'indexation.

Je fais des variables qui sont claires pour moi en un coup d'œil. Si vous ne les comprenez pas, faites-les d'une manière que vous comprenez ;).

Je commence toujours par écrire les variables non globales avec une petite lettre - la raison est simple : l'intelligence sensible à la casse...

C'est le code de test, car le code non-test est assez gros, et sur MT4, il fonctionne quand on change de traf, et il n'y a pas d'erreurs de données manquantes - tout est toujours là. Mais MT5 quand je passe mtf seulement pour une demi-minute charge l'histoire, et puis ne fonctionne pas avec les données n'est pas son TF - dit sur leur absence.

C'est pourquoi j'ai discuté de ce que je faisais mal. Il s'est avéré qu'il est nécessaire de demander les données pour tous les clients utilisés dans l'unité. Je pense que si vous ne connaissez pas à l'avance le nombre estimé de téléphones usagés, vous devez les demander tous. Seule une minute sur deux compte. Il y en a 21 au total...

Encore un problème ?

 
C'est très utile pour lesdébutants:

Dans MT5, il ne faut qu'une demi-minute pour télécharger l'historique lorsque l'on change d'instrument financier.


a écrit à ce sujet

я правильно понимаю тогда, что подготовив кэш,терминал при последующих обращениях (начиная со 2 обращения) затрачивает на порядки меньше времени?

можно ли как-то уменьшить время первого обращения после перезагрузки терминала,чтобы было как в МТ4?
Теперь выводы:

    Разница только в скорости начальной инициализации кеша чарта 0.6 мс МТ4 против 113 мс у МТ5

plus de détails ici

https://www.mql5.com/ru/forum/1111/page1871#comment_4866969

https://www.mql5.com/ru/forum/1111/page1871#comment_4867939

Plus il demandera de TF ou de symboles, plus le démarrage sera lent.

Ошибки, баги, вопросы
Ошибки, баги, вопросы
  • www.mql5.com
Форум алго-трейдеров MQL5
 
kaus_bonus:


a écrit à ce sujet

plus de détails ici

https://www.mql5.com/ru/forum/1111/page1871#comment_4866969

https://www.mql5.com/ru/forum/1111/page1871#comment_4867939

Plus le nombre de TF ou de personnages interrogés est élevé, plus le démarrage sera lent.

Je pense que ce serait bien si ce n'était que lorsque l'indicateur est mis en marche pour la première fois. Je dois changer d'horizon temporel et il faut une demi-minute pour charger l'historique. Je sais que ça ne devrait pas être comme ça, mais... Je fais quelque chose de mal... Et cela ne se produit que sur un seul indicateur, lorsque j'essaie d'accéder à un cadre temporel non natif.
 
Artyom Trishkin:
Ce serait bien si ce n'était que lorsque je démarre l'indicateur pour la première fois. J'ai une demi-minute de chargement de l'historique à chaque fois que je change de période. Je sais que ça ne devrait pas être comme ça, mais... Je fais quelque chose de mal... J'essaie d'accéder à une période de temps non native dans un seul indicateur.

Eh bien, mesurez la vitesse de copie des données d'une autre période et voyez où se trouve le goulot d'étranglement.
 
Artyom Trishkin:

Si vous avez besoin d'utiliser plusieurs indicateurs de différentes TF pour des calculs - vous devez obtenir la poignée de chaque TF.

Si vous voulez qu'il soit plus rapide, réduisez la taille de l'historique dans le terminal.

Avez-vous exécuté mon indicateur de test ? Est-ce qu'il collecte des données ?

 
Alexey Kozitsyn:

Si vous avez besoin d'utiliser plusieurs indicateurs de différentes TF pour des calculs - vous devez obtenir la poignée de chaque TF.

Si vous voulez qu'il soit plus rapide, réduisez la taille de l'historique dans le terminal.

Avez-vous exécuté mon indicateur de test ? Est-ce qu'il collecte des données ?

Non, je ne l'ai pas fait.

Il s'avère que si vous avez besoin de TOUS les horizons temporels, vous devez créer 21 poignées de l'indicateur AO ? N'est-ce pas du gaspillage ?

 
Artyom Trishkin:

Non, je ne l'ai pas encore fait.

Il s'avère que si vous avez besoin de TOUS les horizons temporels, vous devez créer 21 poignées d'indicateur AO ? N'est-ce pas du gaspillage ?

Comment faire autrement pour obtenir les données du bon symbole/TF ? CopyBuffer ne fonctionne qu'avec des poignées.
Raison: