Toute question de débutant, afin de ne pas encombrer le forum. Professionnels, ne passez pas à côté. Nulle part sans toi - 6. - page 641

 
simpleton:

Pourquoi émuler une erreur ?

Erreur - il s'agit de signaler que, pour une raison quelconque liée à des limitations ou à des défaillances du système, l'algorithme n'a pas pu être exécuté et le résultat obtenu avec certaines garanties (limitées, bien sûr, mais - ). La fonction FillAndPrint() montre de manière éloquente ce qu'une situation d'erreur signifie et ce qu'elle ne signifie pas. Lorsqu'une erreur se produit, il n'essaie même pas d'imprimer le résultat. S'il n'y a pas d'erreur, on peut se fier au résultat. C'est ainsi que la logique erreur/absence d'erreur doit être construite.

Vous devez modifier l'algorithme ici : vous devez appliquer un filtre supplémentaire.

C'est ainsi qu'il faut procéder :

Tout d'abord, nous "filtrons" par types d'objets et paramètres, en sélectionnant uniquement les objets dont nous avons besoin parmi tous ceux qui sont disponibles, puis nous appliquons un filtre supplémentaire. C'est à peu près comme ça qu'une personne ferait. C'est ce qu'une personne ferait, non ?

Pour chacune de ces petites sous-tâches, une fonction distincte est souhaitable.

Il ne doit pas y avoir de chiffres dans les expressions, sauf dans des cas très particuliers, par exemple si vous devez doubler et qu'il est dans la nature de l'algorithme de le faire. Ensuite, le nombre 2 peut être utilisé directement dans les expressions. Et dans d'autres cas aussi rares.

Dans les autres cas, il convient d'utiliser des moyens mnémotechniques. Tout d'abord, ils améliorent considérablement la compréhension de ce qui se passe dans un lieu donné, et contribuent donc à réduire les risques d'erreur. Et deuxièmement, la valeur elle-même est définie à un seul endroit et il est facile de la modifier si nécessaire, et il sera impossible de faire une erreur par rapport au cas où le nombre est utilisé dans l'algorithme plus d'une fois, et sans utiliser de mnémonique vous devez fixer les nombres à plusieurs endroits de l'algorithme.

Résultat de la course :

Pas un seul objet n'est trouvé. Augmentez les valeurs des deux mnémoniques 10 fois jusqu'à 36000 (10 heures), et exécutez à nouveau :

Une tendance a déjà "passé" le filtre. Maintenant, rétablissons la valeur du premier mnémonique à 3600 et exécutons :

On peut constater que les deux tendances ont maintenant "passé" le filtrage. À propos, je recommande de déboguer toutes les branches (parties) du programme de cette manière, plutôt qu'une branche en particulier.

Pour aider à formaliser en quelque sorte, je vais essayer de l'expliquer de la manière suivante. Le programme est apparemment comme un plan.

Chaque élément majeur du plan peut être décomposé en éléments secondaires plus petits. Les plus petits en encore plus petits. Les éléments des plus petits sous-plans sont exécutés directement.

Chaque plan, sous-plan et même les plus petits sous-plans correspondent à des fonctions du programme. Les éléments des plus petits sous-plans correspondent à des fonctions "finales" qui n'appellent que des fonctions système, voire ne les appellent pas. Par exemple, AddValue() ou DiffInSecs() en sont des exemples. Les éléments du sous-plan ci-dessus correspondent aux fonctions qui appellent les fonctions qui mettent en œuvre les éléments du sous-plan ci-dessous. Dans celles discutées ci-dessus, ce sont MassTrendNumber(), AddValueIfFound(), AddValueIfFiltered(). Les fonctions de "bas niveau" ne doivent pas appeler les fonctions de "haut niveau", et les fonctions de "haut niveau" ne doivent pas sauter plusieurs niveaux vers le bas, c'est-à-dire qu'elles ne doivent appeler que les fonctions du niveau inférieur. Cette règle est beaucoup plus stricte pour le "bas niveau" que pour le "haut niveau".

Essayez de construire vos programmes en organisant les actions qu'ils contiennent comme des fonctions (courtes) liées par ce type d'arborescence, dans le sens de qui appelle qui.

Ce programme a un arbre dégénéré : une branche qui se "ramifie" plusieurs fois. Et il se "ramifie" non pas en deux petites branches mais en une seule. Mais on peut constater que les fonctions de "haut niveau" appellent systématiquement les fonctions de "bas niveau". Dans cette modification, j'ai inséré un niveau supplémentaire dans cette structure, une "branche non ramifiée" de plus - AddValueIfFiltered().

Je colle le code prêt.

La tâche : rechercher les lignes de tendance(OBJ_TREND) et enregistrer les valeurs de prix relatives à la barre courante dans un tableau. Filtré contre l'existence des paramètres temporels des objets (OBJ_TREND).

#property strict

/******************************************************************************/
bool AddValue(double &array[], const double value) {
  const int size = ArraySize(array);

  if (ArrayResize(array, size + 1) != size + 1) {
    return false; // Ошибка, значение не может быть добавлено к массиву
  }

  array[size] = value; //записываем
  return true; // Нет ошибки, значение добавлено к массиву
}

/******************************************************************************/
bool AddValueIfFound(double &array[], const string name) {
  const int type = ObjectType(name);

  if (type == OBJ_TREND) {
    switch ((color)ObjectGet(name, OBJPROP_COLOR)) { // Тип color допустимо использовать в switch
    case Goldenrod:
    case Gainsboro:
    case White:
      if (!AddValueIfFiltered(array, name)) { // Пропускаем через фильтр
        return false;
      }
    }
  }

  return true; // Нет ошибки, значение, если найдено, добавлено к массиву
}
/******************************************************************************/
bool MassTrendNumber(double &array[], const bool buy) { // Поиск значения цены трендовой линии, текущего бара, запись в массив. Два массива: masS и masB
  const string subname = (buy ? "uptrendline" : "downtrendline"); // существует два названия трендовых линий, первое и второе

  if (ArrayResize(array, 0) != 0) {
    return false; // Ошибка, массив не может быть заполнен достоверно
  }

  for (int i = 0, limit = ObjectsTotal(OBJ_TREND); i < limit+2; i++) {
    if (!AddValueIfFound(array, subname + IntegerToString(i))) {
      return false; // Ошибка, массив, если и заполнен, то недостоверно
    }
  }
 
  return true; // Нет ошибки, массив заполнен достоверно
}
/******************************************************************************/
long DiffInSecs(const datetime dt1, const datetime dt2) {
  return dt1 - dt2;
}
/******************************************************************************/
bool AddValueIfFiltered(double &array[], const string name) {
#define MIN_SECS_BETWEEN_PRICE1_AND_PRICE2 3600
#define MAX_SECS_AFTER_PRICE2              3600

  const datetime dt1 = (datetime)ObjectGet(name, OBJPROP_TIME1);
  const datetime dt2 = (datetime)ObjectGet(name, OBJPROP_TIME2);
  const datetime dt = TimeCurrent();
  
  Print("name = ", name,// ", dt = ", dt, ", dt1 = ", dt1,"\n", 
  " DiffInSecs = ", DiffInSecs(dt,dt2)," DiffInSecs = ", DiffInSecs(dt2,dt1));

   if( DiffInSecs(dt,dt2)>MAX_SECS_AFTER_PRICE2 && DiffInSecs(dt2,dt1)> MIN_SECS_BETWEEN_PRICE1_AND_PRICE2){
    if (!AddValue(array, ObjectGetValueByShift(name, 1))) { // Пытаемся добавить
      return false; // Ошибка, значение не добавлено
    }
  }

  return true; // Нет ошибки, значение, если удовлетворило условию фильтра, добавлено к массиву
}

/******************************************************************************/
void FillAndPrint(double &array[], const bool buy) {
  if (MassTrendNumber(array, buy)) {
    const int limit = ArraySize(array);

    Print("Найдено объектов: ", limit);

    for (int i = 0; i < limit; i++) {
      Print("Price[", i, "] = ", DoubleToStr(array[i], Digits));
    }
  } else {
    Print("Чёрт!");
  }
}

/******************************************************************************/
void OnTick()

//=============================================================================================
//====================================== Линии тренда =========================================
//=============================================================================================
 double masS[]; double masB[];

  Print("Sell:");
  FillAndPrint(masS, false);

  Print("Buy:");
  FillAndPrint(masB, true);
 simpletonСпасибо вам большое, вы за пестовали меня на ощущения правильного кода!) (Правда я немногое понял))))
 
evillive:

J'ai 4 chiffres maintenant, sur ewardollar à 1 lot 1 point coûte 10$ et il en a toujours été ainsi. Pour les croix, le coût sera de 8 à 16, la formule est un peu plus compliquée dans ce cas.

Par exemple, pour la livre euro, marketinfo a donné 16,984, le taux de change livre-dollar = 1,6984, c'est-à-dire que 1 pip de la livre euro vaut 1 livre, multiplié par la valeur du point livre-dollar, qui est toujours de 10,0 (100000 * 0,0001 = 10,0 ou 100000 * 0,00010 = 10,0 - comme on veut).


Tous ces calculs ne sont corrects que si votre compte est en dollars :

Dans ce cas, pour xUSD (EURUSD, GBPUSD etc.) tickvalue = lot*point = 100000*0.0001 = 10.0

pour USDh (USDCHF, USDJPY etc) tickvalue = lot*point/offre = 100000*0.01/101.93=9.8107

pour xUSD/yUSD (EURGBP) tickvalue = Bid(yUSD)*lot*point = 1.6980*100000*0.0001 = 16.98

pour xUSD/USDy (EURJPY) tickvalue = lot*point/offre(USDy) = 100000*0.01/101.91 = 9.8126


Quelque chose que tu as raté ! J'ai pris le temps de regarder dans le code, de sélectionner les expressions, et de regarder :

  double TV = MarketInfo(Symbol(),MODE_TICKVALUE); 
  string sTV = DoubleToStr(TV,4); 
  Comment("TV ",sTV); //sTV = 1.0/Bid

Il n'y a pas plus simple ! No 10, 16, etc.

 
evillive:

J'ai 4 chiffres maintenant, sur ewardollar à 1 lot 1 point coûte 10$ et il en a toujours été ainsi. Pour les croix, le coût sera de 8 à 16, la formule est un peu plus compliquée dans ce cas.

Par exemple, pour la livre euro, marketinfo a donné 16,984, le taux de change livre-dollar = 1,6984, c'est-à-dire que 1 pip de la livre euro vaut 1 livre, multiplié par la valeur du point livre-dollar, qui est toujours de 10,0 (100000 * 0,0001 = 10,0 ou 100000 * 0,00010 = 10,0 - comme on veut).


Tous ces calculs ne sont corrects que si votre compte est en dollars :

Dans ce cas, pour xUSD (EURUSD, GBPUSD etc.) tickvalue = lot*point = 100000*0.0001 = 10.0

pour USDx (USDCHF, USDJPY etc) tickvalue = lot*point/offre = 100000*0.01/101.93 = 9.8107

pour xUSD/yUSD (EURGBP) tickvalue = Bid(yUSD)*lot*point = 1.6980*100000*0.0001 = 16.98

pour les croisements xUSD/USDy (EURJPY) tickvalue = lot*point/offre(USDy) = 100000*0.01/101.91=9.8126




C'est faux ! La valeur d'un devis n'a pas d'importance !Et la valeur d'un tick min. doit être calculée à partir du prix actuel! Ce qui équivaut à TICK_VALUE ! Ci-dessus, un exemple tiré de mon code.
 
borilunad:

borilunad:

C'est mal ! La valeur d'une citation n'est pas pertinente ! Et la valeur d'un min.tick devrait être calculée à partir du prix actuel ! Ce qui équivaut à TICK_VALUE ! Ci-dessus, un exemple tiré de mon code.

En quoi est-ce mal ? Marketinfo renvoie les mêmes valeurs que les formules que j'ai données ci-dessus. Je n'ai pas inventé ces formules, elles sont utilisées par le terminal pour calculer la TickValue))).

Il est clair qu'il est plus pratique de prendre la valeur de Marketinfo, mais il demandait des formules ou des méthodes de calcul.

Et à propos de la valeur, j'ai écrit plus tôt, que cela n'a pas d'importance, parce que sur les comptes à 5 chiffres, un point = 10 pips, et c'est le même point à partir de 4 chiffres.

 
evillive:

En quoi est-ce mal ? Marketinfo renvoie les mêmes valeurs que les formules que j'ai données ci-dessus. Je n'ai pas inventé ces formules, elles sont utilisées par le terminal pour calculer la TickValue))).

Il est clair qu'il est plus pratique de prendre la valeur de Marketinfo, mais il demandait des formules ou des méthodes de calcul.

Et j'ai écrit plus tôt à propos de la signitude, que cela n'a pas d'importance, car sur les comptes à 5 chiffres, un point = 10 pips, et c'est le même point à partir de 4 chiffres.


C'est ce que je veux dire parMarketInfo(Symbol(),MODE_TICKVALUE) =1.0/Bid ;Peut-être seulement pour l'Eurodollar, je ne le pulvérise pas sur les autres !
 
borilunad:

C'est ce que je veux dire parMarketInfo(Symbol(),MODE_TICKVALUE) =1.0/Bid ;Peut-être, seulement pour l'Euro, pas pour les autres !

C'est exactement ce qui ne va pas avec l'eurodollar, d'après la définition donnée dans l'aide

MODE_TICKVALUE

16

Changement minimal du prix du titre dans la monnaie de dépôt.


Et cela signifie multiplier

MODE_POINT

11

Taille du point dans la monnaie de cotation. Pour le symbole actuel est stocké dans la variable prédéfinie Point


par

MODE_LOTSIZE

15

Taille du contrat dans la devise de base de l'instrument


Bien sûr, si votre compte est en euros, vous devez utiliser l'euro comme devise de base, mais pour les traders qui ont un compte en dollars (c'est le cas le plus souvent), les formules ci-dessus sont valables. Comme les paires principales et les plus négociées sont basées sur le dollar américain, ces formules sont le plus souvent utilisées.

 
evillive:

C'est exactement faux, d'après la définition donnée dans l'aide

MODE_TICKVALUE

16

Changement minimal du prix du symbole dans la devise du dépôt.


Cela signifie que vous devez multiplier

MODE_POINT

11

Taille du point dans la monnaie de cotation. Pour le symbole actuel est stocké dans la variable prédéfinie Point


à l'adresse

MODE_LOTSIZE

15

Taille du contrat dans la devise de base de l'instrument


Bien sûr, si votre compte est en euros, vous devez utiliser des euros, mais la plupart des traders ont un compte en dollars.


Bon, alors, j'ai un cas particulier, mais pour moi qui vit dans la zone euro, il est plus pratique d'effectuer tous les calculs en euros !
 

Messieurs, veuillez me donner un exemple de code pour l'indicateur suivant. Je n'arrive pas à savoir combien de zones tampons sont nécessaires, quel type de cartographie et où et quelles propriétés doivent être prescrites pour ces zones.

L'indicateur est le suivant :

1 Les barres se connectent au moins toutes les trois barres et les barres adjacentes. La ligne est rouge.

2 Les sections de barres relient les maximums de chaque 5e barre et des barres adjacentes. La ligne est bleue.

L'essentiel : les segments ne se croisent en aucune façon. Le début et la fin de chaque segment sont indépendants des autres segments.

L'indicateur calcule les valeurs du début et de la fin de chaque segment. Ils doivent être colorés différemment en fonction des conditions.

Voici en gros à quoi il devrait ressembler


 

Et une autre question.

Est-il normal que je ne puisse pas travailler avec l'indicateur en mode Debug?

Lorsque le programme atteint le point d'arrêt, le terminal MT4 se bloque et la fenêtre devient blanche (en HP) de sorte qu'il est impossible de voir ce qui est dessiné sur le graphique.

 
Top2n:

Voici le code prêt.

Tâche : Rechercher des lignes de tendance (OBJ_TREND), enregistrer les valeurs de prix relatives à la barre courante dans un tableau. Avec filtrage par rapport à l'existence des paramètres temporels des objets (OBJ_TREND).

simpleton:Merci beaucoup, vous m'avez fait sentir le bon code !) (Bien que je n'ai pas compris beaucoup))))

Si vous pratiquez, la compréhension viendra, de plus en plus. Il faut être concentré et attentif. Lorsque l'algorithme du programme est étalé sur une grande fonction, il est difficile de le réaliser avec concentration et attention - trop de liens se forment. Mais si un programme est divisé en parties fonctionnellement complètes (petites fonctions), il est beaucoup plus facile de le faire pour chaque petite fonction séparée. Et ainsi de suite à chaque niveau de fonction. Au fait :

   if( DiffInSecs(dt,dt2)>MAX_SECS_AFTER_PRICE2 && DiffInSecs(dt2,dt1)> MIN_SECS_BETWEEN_PRICE1_AND_PRICE2){
    if (!AddValue(array, ObjectGetValueByShift(name, 1))) { // Пытаемся добавить
      return false; // Ошибка, значение не добавлено
    }
  }
J'ai dû mal nommer le mnémonique MAX_SECS_AFTER_PRICE2 (car j'ai d'abord compris que la condition devait être inverse), la signification devrait probablement être MIN_SECS_AFTER_PRICE2, c'est-à-dire le minimum autorisé, et non le maximum.
Raison: