[ARCHIVE]Toute question de débutant, afin de ne pas encombrer le forum. Professionnels, ne passez pas à côté. Je ne peux aller nulle part sans toi - 5. - page 396

 
lottamer:

Il y a quelque temps, des personnes aimables m'ont expliqué comment faire la fonction "ticket de retour de la dernière position fermée" à partir de la fonction "ticket de retour des deux dernières positions fermées".

Et lorsque j'ai eu besoin de la fonction "tickets de trois positions fermées", je n'ai pas pu l'implémenter (par similitude et méthode de sélection).

Aidez-nous, s'il vous plaît,

vous pouvez voir qu'il y a deux copies, la seconde avec quelques changements. mais j'ai pu les continuer...

J'ai cette variante pour le 3ème ticket... et il retourne le ticket de la première position pour une raison quelconque...


Remplacer

if(OrderTicket()==A && (OrderTicket()==B) )continue;

à

if(OrderTicket()==A || (OrderTicket()==B) )continue;

Ce n'est pas clair ce que vous faites pour retourner trois valeurs à partir d'une seule fonction.

 
Roger:


Remplacer

à l'adresse

Ce que vous faites pour renvoyer trois valeurs à partir d'une seule fonction n'est pas clair.



le but est de calculer le résultat des N dernières positions. pour cela j'appelle leurs billets, et ensuite c'est une question de technique

fLastClosetPoz();
     OrderSelect( Ticket1,SELECT_BY_TICKET); X=OrderProfit(); SL1=OrderType(); TM1=OrderOpenTime();      Print (Ticket1); Print (SL1,"_",X); //ПОСЛЕДНИЙ 
     OrderSelect( Ticket2,SELECT_BY_TICKET); Y=OrderProfit(); SL2=OrderType(); TM2=OrderOpenTime();      Print (Ticket2); Print (SL2,"_",Y); //ПРЕДпоследний
     OrderSelect( Ticket3,SELECT_BY_TICKET); Z=OrderProfit(); SL3=OrderType(); TM3=OrderOpenTime();      Print (Ticket3); Print (SL3,"_",Z); //ПРЕД-ПРЕДпоследний
 
Roger:


Remplacer par

à


Ça a marché ! Honnêtement, j'ai eu l'idée de remplacer OR par AND.... mais ... :)))))))))))))))))))))

merci ! maintenant je comprends la logique, bien que pour compter 15 fermés, je vais devoir faire exploser le code à la taille d'un ballon !

peut-on tout condenser en une seule boucle ? et ne substituer que le paramètre du nombre de transactions requises N ?

 
Zhunko:

1. Vous ne devriez pas faire ça. Il exprime même mon admiration pour son algorithme. C'est le HENRYFIX. Il avait un autre surnom à l'époque.

Le préfixe du nom de script correspond aux premières lettres de nos surnoms.

===============

2. Dmitry, quoi qu'il en soit, je suis sincèrement heureux que vous ayez résolu un problème secret avec un algorithme secret, qui ne peut être divulgué.

3. Tout semblait très mystérieux. Merci de te vanter. Vous êtes sans aucun doute le programmeur le plus cool de ce forum et peut-être même de l'univers entier !

1. Oh ouais ! Après avoir découvert que c'était ton code, ou celui de ton pote. Abalde, était le plus foireux et embarrassant, maintenant il est immédiatement devenu admirable.

2. Avec ce que je suis un programmeur, ce que je sais et comment je sais et peux faire, avec ce que je ne sais pas et ne connais pas - je m'en accommoderai d'une manière ou d'une autre.

3. La tâche n'est absolument pas secrète, elle est absolument claire, elle a été ouvertement définie ici. Tous ceux qui sont capables de le comprendre, l'ont compris immédiatement sans aucun problème. Il a été résolu non pas par des méthodes secrètes et magiques, mais par les méthodes habituelles et évidentes (et connues dans le monde entier). Je ne me vante pas ici, je me moque de toi, miracle. Seule votre mégalomanie vous empêche de le comprendre et de vous en rendre compte.

 
Integer:

1. Oh oui ! Après qu'il se soit avéré être votre code, ou celui de votre compagnon. Abaldez, c'était le plus foireux et embarrassant, maintenant c'est immédiatement admirable.

2. Avec ce que je suis un programmeur, ce que je sais et comment je sais et peux faire, avec ce que je ne sais pas et ne connais pas - je m'en accommoderai d'une manière ou d'une autre.

3. La tâche n'est pas du tout secrète, elle est absolument claire, elle a été ouvertement définie ici. Tous ceux qui sont capables de le comprendre, l'ont compris immédiatement sans aucun problème. Il a été résolu non pas par des méthodes secrètes et magiques, mais par les méthodes habituelles et évidentes (et connues dans le monde entier). Je ne me vante pas ici, et à toi, miracle, je ris. Seule votre mégalomanie vous empêche de le comprendre et de le réaliser.




Les gens résolvent des problèmes concrets ici, et vous, vous polluez le fil de discussion avec des émotions...
 
lottamer:


Allez vous frotter à d'autres endroits ! Les gens résolvent des problèmes pratiques ici. Vous ne faites que polluer le fil de discussion avec des émotions...


Pourquoi m'écrivez-vous à ce sujet ? Prenez Junko et écrivez cela, c'est son quatrième jour ici, il ne peut pas comprendre ce dont nous parlons, tous les autres ont compris le premier jour.
 

Bien sûr, il doit y avoir des limites à tout débat. Dans le cas contraire, elle peut déjà franchir les limites du raisonnable.

Après l'exposé des deux positions, les parties peuvent se mettre d'accord ou non. - C'est leur droit. Même si les gens ont tort. Tout le monde a le droit d'avoir tort.

S'il s'agit d'un débat public, comme celui-ci, ceux qui le regardent voient les arguments de chaque partie et, quel que soit le consensus atteint (ou non) sur la question, chacun a la possibilité de choisir sa version de la solution (ou les deux).

Mais se tourner vers les accusations et les appels à l'individu (plutôt qu'à la tâche, au problème, à l'affaire), c'est déjà baisser sa crédibilité. C'est inutile et condamnable (pour avoir insulté une personne).


Puisque les arguments et les moyens de résoudre le problème ont été exposés depuis longtemps, je suggère que les deux parties s'arrêtent sur cette question et fassent appel l'une à l'autre.

Apparemment, si les débatteurs sont des professionnels de la résolution de problèmes programmatiques, ils sont des novices du débat. Ce qui ne s'écarte pas du sujet du fil de discussion, mais permet de donner un avis professionnel. J'espère que ce conseil sera pris en compte.

 
Integer:

1. Oh oui ! Après qu'il se soit avéré être votre code, ou celui de votre compagnon. Abaldez, était le plus foireux et embarrassant, maintenant c'est immédiatement admirable.

2. Avec ce que je suis un programmeur, ce que je sais et comment je sais et peux faire, avec ce que je ne sais pas et ne connais pas - je m'en accommoderai d'une manière ou d'une autre.

3. La tâche n'est pas du tout secrète, elle est absolument claire, elle a été ouvertement définie ici. Tous ceux qui sont capables de le comprendre, l'ont compris immédiatement sans aucun problème. Il a été résolu non pas par des méthodes secrètes et magiques, mais par les méthodes habituelles et évidentes (et connues dans le monde entier). Je ne me vante pas ici, je me moque de toi, miracle. Seule votre mégalomanie vous empêche de le comprendre et de vous en rendre compte.

1. Connaissez-vous la différence entre un code et un algorithme ? De plus, l'algorithme n'a rien à voir avec l'ouverture de la fenêtre du graphique. J'ai corrigé le code, bien sûr. L'endroit où s'ouvre le graphique n'a pratiquement pas changé. Nous n'avions pas d'autre choix à ce moment-là. Je l'ai fait d'une manière différente dans la DLL. Il est plus fiable.

2. C'était génial ! Tu es le meilleur !

3. Tu le penses vraiment :

FAQ:

1) Problème : chaque script (EA) doit être conscient de la présence de tous les autres.

2) Problème : s'il y a un échec, les globaux de celui qui a échoué resteront inoccupés et la file d'attente sera bloquée.

3) Solution :

Chaque exp organise 1 globalka avec le nom - préfixe commun + poignée de fenêtre + symbole. La valeur du globalka est le temps du dernier tick sur cet instrument. 2 global commun avec sa propre poignée (après avoir travaillé, il écrit sa propre poignée dans celui-ci ou l'efface s'il est le plus ancien)

La file d'attente est classée par ordre croissant (poignées), la plus ancienne met la deuxième globale à zéro.

dans chaque exp, nous créons trois tableaux (par manque de structures) - symbole/manipulateur/dernier temps d'accès/dernier temps de tic.

tous les EXPs gardent la trace de (last access time/last tick time) pour chacun d'entre eux et dès qu'ils sont différents (un des EXPs tombe en panne) les deux globaux de l'EXP en panne sont supprimés et il est considéré comme inactif. ses cellules dans les tableaux sont supprimées (le tableau est reconstruit).

la file d'attente est restaurée

cette opération sera en fait effectuée par l'EA se trouvant sur le graphique le plus actif (ticks fréquents).

lorsqu'elle est désinitialisée normalement, chaque expo nettoie après elle-même.

saut max - une coche.

ZS. et en général, il est préférable de faire une seule multidevise

C'est donc grâce aux capacités télépathiques de Rustam. C'est un problème hypothétique et une solution hypothétique. Qu'est-ce que ça a à voir avec votre problème ? Tu n'as jamais rien dit à ce sujet. J'ai dû faire pression. La réponse n'est rien d'autre que des injures au lieu de mots constructifs, que vous ne cessez de suggérer, mais que vous ne mettez pas en œuvre.

J'ai eu un défi similaire en 2008. Les secrets ne feront pas l'affaire, comme certains. Je donnerai un exemple concret du type de problème, de la manière de le résoudre et des raisons pour lesquelles je pense que la résolution de tels problèmes de cette manière est vouée à l'échec.

============================

Les données initiales du problème :

1. La tâche comporte plusieurs conseillers experts identiques en boucle. C'est-à-dire des fils totalement indépendants.

2. Il existe une base de données de coefficients divisée en 8 groupes, à laquelle certains experts ont accès. La taille de la base de données commence à partir de 2 Go.

3. La BD est parfois reconstituée. Réapprovisionnement par périodes multiples de 2 heures. Le délai de traitement dépend des multiples de l'heure de la journée. La durée varie de 5 minutes à 45 minutes en fonction de la multiplicité des moments de la journée et de la capacité du processeur.

Tâche :

Étant donné que l'enrichissement de la base de données prend beaucoup de temps, un seul expert devrait être responsable de l'enrichissement de la base de données. Sinon, vous risquez de ne pas pouvoir attendre qu'elle se termine.

2. Il est nécessaire d'interdire l'accès à la base de données pendant sa mise à jour. Faites-le en groupe, afin de ne pas ralentir de manière significative la mise à jour des coefficients, avec lesquels les experts travaillent.

Les experts qui travaillent avec des coefficients en cours de mise à jour doivent travailler avec les anciens coefficients.

Les experts qui sont passés à un groupe spécifique de coefficients pendant la période de mise à jour doivent travailler avec un seul coefficient et en informer. Lorsque la mise à jour est terminée, ils doivent passer au nouveau coefficient. Il en va de même pour le point 3.

Solution à l'époque :

1. Une file d'attente commune d'identifiants d'experts composée de leurs indices est réalisée.

2. Une file d'attente des identifiants des experts, qui accèdent à la base de données, constituée de leurs indices, est constituée.

Les deux files d'attente constituent une ressource commune. L'accès aux files d'attente est synchronisé par un seul objet de synchronisation.

Le premier expert de la deuxième file d'attente est responsable de la mise à jour de la base de données. 4.

5. De plus, c'est presque comme Rustam l'a décrit. C'est un peu plus facile grâce à l'implémentation en DLL.

Les identifiants sont les indices de passage. Lorsque nous supprimons un conseiller expert, l'identifiant est retiré de la file d'attente. La réindexation n'est pas effectuée. Les experts restants laisseront leurs index.

Lors de l'ajout d'un nouvel expert, si l'index du dernier expert ne correspond pas à son numéro, le premier ancien index libre est attribué. Sinon, de nouveaux indices sont attribués.

Il n'est pas nécessaire de se lier au descripteur et à l'instrument graphique. De plus, il n'est pas nécessaire de garder la trace d'un échec de déchargement. Il n'y a jamais eu d'échec. Même si cela s'est produit, ce n'est pas une catastrophe. L'EA continuerait à travailler avec les anciens ratios. Lors de la mise à jour suivante, le contrôleur du compteur de mise à jour aurait détecté l'absence de mise à jour et supprimé l'ID de l'EA principal de la deuxième file d'attente. L'expert suivant reprendrait la mission du maître. Le même contrôleur ferait la même chose lorsque l'Expert Advisor passe en mode de connexion à la base de données. C'est-à-dire qu'il l'introduit dans la deuxième file d'attente. C'est-à-dire que seuls les experts travaillant sur M1, où la valeur du coefficient n'est pas critique, seraient affectés.

Cette solution a permis d'accomplir pleinement la tâche, mais elle m'a fortement déplu en raison de la liaison des conseillers experts entre eux et d'une tâche inhabituelle pour le conseiller expert, qui alimentait la base de données, ce qui ne contribue pas à la fiabilité. À l'époque, je ne savais pas et ne savais pas comment faire beaucoup de choses. Un an plus tard, je l'ai refait.

Solution 2 :

1. la base de données est maintenue dans un thread séparé, où elle se réapprovisionne sur un timer.

2. L'accès à la base de données au moment de son réapprovisionnement est protégé par l'objet de synchronisation.

Tout s'est avéré beaucoup plus simple. Sans file d'attente. Mais je ne l'ai pas beaucoup aimé non plus. Avant un réapprovisionnement, la base de données appelait le script de permutation des quotes qui conduisait parfois au débordement de la mémoire. Ce qui a beaucoup ralenti MT4. À l'époque, MT4 fonctionnait avec 2 Go de mémoire. Il fonctionne maintenant avec 4GB.

Solution 3 :

1. la DB est une application distincte. C'est-à-dire un autre processus avec sa propre mémoire dédiée, indépendant de MT4.

2. La DB se reconstitue.

L'échange de données se fait par le biais de la cartographie. Il a augmenté la vitesse d'échange des données et de réapprovisionnement de la base de données. Auparavant, tout était lu sur le disque. Il était impossible de faire autrement. La mémoire de travail du МТ4 est très limitée.

4. L'historique est pompé par MT4 à distance de l'application DB, où vous le kickez selon les besoins. Toute défaillance de MT4 - son déchargement et son chargement ultérieur.

5. Le point 4 est réalisé en créant un lien symbolique vers le répertoire MT4 actuel. C'est-à-dire qu'il s'agit d'une copie complète du MT4 actuel. L'historique est mis à jour à la volée directement dans les répertoires MT4, sans attendre le téléchargement MT4 en cours.

6. Synchronisation de l'accès à la base de données au moment de sa mise à jour par le biais de mutex, car la section critique ne fonctionne que pour un seul processus.

========================

Donc, Dmitry, ne connaissant pas votre tâche, vous pouvez supposer qu'elle peut être résolue sans organiser de file d'attente et en gardant les fils d'Expert Advisor indépendants. Cela augmentera la fiabilité et les performances globales. J'en parle (indépendance des fils) depuis plusieurs pages déjà.

 

Désolé. Pas de réponse à cela :

Integer:

Il s'agit d'une unité d'accès atomique et sans synchronisation. Cela n'a pas de sens de n'aborder le dépôt que de cette manière. L'appel de l'une des fonctions de paramètre de dépôt sera atomique par lui-même, sans aucune modification. Si vous le faites de manière atomique, tout le travail du conseiller expert. C'est ainsi que l'on résout les problèmes - on pense avoir fait quelque chose, mais en fait c'est une illusion.

Dmitry, vous ne devriez pas penser qu'il n'y a que des imbéciles. D'après la question de Sergey, vous pouvez voir qu'il a bien compris le problème.

Bien entendu, une simple référence aux paramètres de dépôt avec synchronisation n'a aucun sens. Une synchronisation est nécessaire pour modifier ces paramètres. Pour que le conseiller expert parallèle reçoive le paramètre correct qui a déjà été modifié, plutôt que de le recevoir en cours de modification.

 
lottamer:

Ça a marché ! Honnêtement, j'ai eu l'idée de remplacer OR par AND.... mais ... :)))))))))))))))))))))

merci ! maintenant je comprends la logique, bien que pour compter 15 fermés, je vais devoir faire exploser le code à la taille d'un ballon !

Peut-on tout condenser en une seule boucle ? et ne substituer que le paramètre du nombre de N transactions nécessaires ?

Voici l'une des façons possibles de rechercher les ordres les plus récemment clôturés. Les ordres recherchés peuvent être filtrés par type (ACHAT, VENTE) et par rentabilité (déficitaire, rentable) :

//IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII+
//|  Автор : TarasBY, taras_bulba@tut.by                                              |
//+-----------------------------------------------------------------------------------+
//|        Функция получает Ticket следующего перед fdt_Time закрытого ордера         |
//IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII+
int fGet_TicketLastClosePos (int fi_Type = -2,          // OrderType()
                             int fi_TypeProfit = 0,     // флаг профитности ордеров: 0 - все, -1 - убыточные, 1 - прибыльные
                             datetime fdt_Time = 0)     // Точка отсчёта времени
{
    datetime ldt_CloseTime = 0, ldt_LastTime = 0;
    double   ld_Profit = 0.;
    int      li_Ticket = 0, li_Total = OrdersHistoryTotal();
//----
    for (int li_ORD = li_Total - 1; li_ORD >= 0; li_ORD--)
    {
        //if (!fCheck_MyOrders (li_ORD, fi_Type, MODE_HISTORY)) continue;
        // Здесь прописываете свою фильтрацию ордеров
        ldt_CloseTime = OrderCloseTime();
        //---- Пропускаем ордера, закрытые после указанной даты
        if (fdt_Time != 0) if (fdt_Time <= ldt_CloseTime) continue;
        if (ldt_LastTime >= ldt_CloseTime) continue;
        ld_Profit = OrderProfit();
        //---- Фильтруем ордера по профитности
        if (fi_TypeProfit > 0) if (ld_Profit < 0.) continue;
        if (fi_TypeProfit < 0) if (ld_Profit > 0.) continue;
        ldt_LastTime = ldt_CloseTime;
        li_Ticket = OrderTicket();
    }
//----
    return (li_Ticket);
}
//IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII+
//|  Автор : TarasBY, taras_bulba@tut.by                                              |
//+-----------------------------------------------------------------------------------+
//|        Функция получает Tickets N закрытых ордеров                                |
//IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII+
int fGet_TicketsLastCloseOrd (int fi_NUM,                // Количество искомых тикетов
                              int& ar_Tickets[],         // возвращаемый массив с тикетами
                              int fi_Type = -2,          // OrderType()
                              int fi_TypeProfit = 0)     // флаг профитности ордеров: 0 - все, -1 - убыточные, 1 - прибыльные
{
    int      li_cnt = 0, li_Ticket;
    datetime ldt_Time = 0;
//----
    for (int li_IND = 0; li_IND < fi_NUM; li_IND++)
    {
        li_Ticket = fGet_TicketLastClosePos (fi_Type, fi_TypeProfit, ldt_Time);
        if (li_Ticket > 0)
        {
            li_cnt++;
            ArrayResize (ar_Tickets, li_cnt);
            ar_Tickets[li_cnt-1] = li_Ticket;
            OrderSelect (li_Ticket, SELECT_BY_TICKET);
            ldt_Time = OrderCloseTime();
        }
        else break;
    }
//----
    return (li_cnt);
}

Après que la fonction fGet_TicketsLastCloseOrd() soit appelée et qu'elle renvoie la quantité de billets trouvés selon les paramètres spécifiés, vous pouvez (je le ferais) vérifier avec la quantité spécifiée de billets (fi_NUM) et la valeur renvoyée par la fonction. Tous les tickets collectés seront dans le tableau passé à la fonction par référence.

Et dans cette variante, il n'est pas important de savoir combien de ces derniers tickets sont recherchés. :)

Et si vous avez besoin d'un bénéfice par ces derniers ordres fermés, c'est encore plus facile :

//IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII+
//|  Автор : TarasBY, taras_bulba@tut.by                                              |
//+-----------------------------------------------------------------------------------+
//|        Функция получает Profit N последних закрытых ордеров                       |
//IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII+
double fGet_ProfitLastCloseOrd (int fi_NUM,          // Количество просчитываемых ордеров
                                int fi_Type = -2)    // OrderType()
{
    int      li_Ticket;
    double   ld_Profit = 0.;
    datetime ldt_Time = 0;
//----
    for (int li_IND = 0; li_IND < fi_NUM; li_IND++)
    {
        li_Ticket = fGet_TicketLastClosePos (fi_Type, 0, ldt_Time);
        if (li_Ticket > 0)
        {
            OrderSelect (li_Ticket, SELECT_BY_TICKET);
            ldt_Time = OrderCloseTime();
            ld_Profit += (OrderProfit() + OrderSwap() + OrderCommission());
        }
        else break;
    }
//----
    return (ld_Profit);
}