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

 

Voici le fichier .cpp du projet, jetez-y un coup d'œil et après quelques recherches sur Google et Yandex, je n'ai rien trouvé de bien compliqué, c'est généralement compréhensible. Cela semble même simple.

//+------------------------------------------------------------------+
//| Sample DLL for MQL4 |
//| Copyright 2001-2012, MetaQuotes Software Corp. |
//| http://www.metaquotes.net |
//+------------------------------------------------------------------+
#define  WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
//---
#define  MT4_EXPFUNC __declspec(dllexport) //это что?
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#pragma  pack(push,1)
struct RateInfo // Структура, переменные
{
unsigned int ctm;
double open;
double low;
double high;
double close;
double vol;
};
#pragma  pack(pop)
//---
struct MqlStr
{
int len;
char *string // Указатель на стринг, я плохо помню.
};
static int CompareMqlStr(const void *left,const void *right);
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)//функция 
{
//---
switch(ul_reason_for_call) // оператор что делать
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH: //что это всюду, не понял.
break;
}
//---
return(TRUE);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall GetIntValue(const int ipar) // __stdcall кладет аргументы в стек справа налево
{ // MT4_EXPFUNC говорит что функция будет видима из метатрайдера, я не совсем понял.
printf("GetIntValue takes %d\n",ipar);
return(ipar);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC double __stdcall GetDoubleValue(const double dpar)
{
printf("GetDoubleValue takes %.8lf\n",dpar);
return(dpar);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC char* __stdcall GetStringValue(char *spar)
{
printf("GetDoubleValue takes \"%s\"\n",spar);
return(spar);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC double __stdcall GetArrayItemValue(const double *arr,const int arraysize,const int nitem)
{
//---
if(arr==NULL)
{
printf("GetArrayItemValue: NULL array\n");
return(0.0);
}
if(arraysize<=0)
{
printf("GetArrayItemValue: wrong arraysize (%d)\n", arraysize);
return(0.0);
}
if(nitem<0 || nitem>=arraysize)
{
printf("GetArrayItemValue: wrong item number (%d)\n", nitem);
return(0.0);
}
//---
return(arr[nitem]);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC BOOL __stdcall SetArrayItemValue(double *arr,const int arraysize,const int nitem,const double value)
{
//---
if(arr==NULL)
{
printf("GetArrayItemValue: NULL array\n");
return(FALSE);
}
if(arraysize<=0)
{
printf("GetArrayItemValue: wrong arraysize (%d)\n", arraysize);
return(FALSE);
}
if(nitem<0 || nitem>=arraysize)
{
printf("GetArrayItemValue: wrong item number (%d)\n", nitem);
return(FALSE);
}
//---
arr[nitem]=value;
return(TRUE);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC double __stdcall GetRatesItemValue(const RateInfo* rates,const int rates_total,const int shift,const int nrate)
{
//---
if(rates==NULL)
{
printf("GetRatesItemValue: NULL array\n");
return(0.0);
}
//---
if(rates_total<0)
{
printf("GetRatesItemValue: wrong rates_total number (%d)\n", rates_total);
return(0.0);
}
//---
if(shift<0 || shift>=rates_total)
{
printf("GetRatesItemValue: wrong shift number (%d)\n", shift);
return(0.0);
}
//---
if(nrate<0 || nrate>5)
{
printf("GetRatesItemValue: wrong rate index (%d)\n", nrate);
return(0.0);
}
//---
int nitem=rates_total-1-shift;
switch(nrate)
{
case 0: return double(rates[nitem].ctm);
case 1: return rates[nitem].open;
case 2: return rates[nitem].low;
case 3: return rates[nitem].high;
case 4: return rates[nitem].close;
case 5: return rates[nitem].vol;
}
//---
return(0.0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall SortStringArray(MqlStr *arr,const int arraysize)
{
//---
if(arr==NULL)
{
printf("SortStringArray: NULL array\n");
return(-1);
}
if(arraysize<=0)
{
printf("SortStringArray: wrong arraysize (%d)\n", arraysize);
return(-1);
}
//---
qsort(arr,arraysize,sizeof(MqlStr),CompareMqlStr);
//---
return(arraysize);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall ProcessStringArray(MqlStr *arr,const int arraysize)
{
int len1,len2;
//---
if(arr==NULL)
{
printf("ProcessStringArray: NULL array\n");
return(-1);
}
if(arraysize<=0)
{
printf("ProcessStringArray: wrong arraysize (%d)\n", arraysize);
return(-1);
}
//---
for(int i=0; i<arraysize-1; i++)
{
if(arr[i].string==NULL) len1=0;
else len1=strlen(arr[i].string);
if(arr[i+1].string==NULL) len2=0;
else len2=strlen(arr[i+1].string);
//--- uninitialized string
if(arr[i+1].string==NULL) continue;
//--- destination string is uninitialized and cannot be allocated within dll
if(arr[i].string==NULL) continue;
//--- memory piece is less than needed and cannot be reallocated within dll
if(arr[i].len<len1+len2) continue;
//--- final processing
strcat(arr[i].string,arr[i+1].string);
}
//---
return(arraysize);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int CompareMqlStr(const void *left,const void *right)
{
MqlStr *leftstr=(MqlStr *)left;
MqlStr *rightstr=(MqlStr *)right;
//---
if(leftstr->string==NULL) return(-1); //-> вот этот знак я не знаю
if(rightstr->string==NULL) return(1);
//---
return(strcmp(leftstr->string,rightstr->string));
}
//+------------------------------------------------------------------+

Mais comment cela fonctionne-t-il ? Je ne suis pas sûr de savoir comment faire référence à ce ddl - à partir du code de l'EA ? Comment ? D'abord, cela ressemble à ceci #include <GetIntValue>.

2. Lors de l'appel de la dll, il n'est pas nécessaire de garder le studio allumé, n'est-ce pas ? Comment est-ce exécuté ?

Veuillez montrer l'exemple le plus simple d'appel de cette dll à partir du code mql.

 
Trader7777:

Je ne comprends pas ici...


La taille du lot doit augmenter de manière exponentielle (avec le multiplicateur 2) si un deuxième ordre unidirectionnel est ouvert.



Voici le résultat.

puis comme ceci

double OrderLotsSell(string sy="", int op=-1, int mn=-1) { 
 datetime o;
   int      i, k=OrdersTotal(); double r=-1;

  if (sy=="0") sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (OrderSymbol()==sy || sy=="") {
        if ( OrderType()==OP_SELL) {
          if (op<0 || OrderType()==OP_SELL) {
            if (mn<0 || OrderMagicNumber()==Magic) {
              r=OrderLots()*2;
            }
          }
        }
      }
    }
  }
  return(r);
}

double OrderLotsBuy(string sy="", int op=-1, int mn=-1) { 
 datetime o;
   int      i, k=OrdersTotal(); double r=-1;

  if (sy=="0") sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (OrderSymbol()==sy || sy=="") {
        if ( OrderType()==OP_BUY) {
          if (op<0 || OrderType()==OP_BUY) {
            if (mn<0 || OrderMagicNumber()==Magic) {
              r=OrderLots()*2;
            }
          }
        }
      }
    }
  }
  return(r);
}





 
max020780:


vous obtenez un résultat comme celui-ci

Alors c'est tout.


Merci, j'ai compris l'idée... J'ai tout compris.

A quoi sert cette ligne ?


datetime o;
 

Voici une autre question : j'ai un ordre de suivi. Quand un ordre unidirectionnel est ouvert, tout fonctionne bien, s'il y en a plus, cela ne fonctionne pas pour une raison quelconque. Pourquoi ?

void Trailing ()
{
for(int i = 0; i<OrdersTotal(); i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
{
if (OrderType() == OP_BUY)
{
if(Bid - OrderOpenPrice() > TrailingStop*Point)
{
if (OrderStopLoss() < Bid - (TrailingStop + TrailingStep)*Point)
{
SL = NormalizeDouble(Bid - TrailingStop*Point,Digits);
if (OrderStopLoss() !=SL)
OrderModify(OrderTicket(),OrderOpenPrice(),SL,0,0);
}
}
}
if (OrderType() == OP_SELL)
{
if(OrderOpenPrice() - Ask > TrailingStop*Point)
{
if (OrderStopLoss() > Ask + (TrailingStop+ TrailingStep)*Point)
{
SL = NormalizeDouble (Ask+TrailingStop*Point,Digits);
if (OrderStopLoss() !=SL)
OrderModify (OrderTicket(), OrderOpenPrice(), SL,0,0);
}
}
}
}
}
}
}


 
Vladimirovits:

Voici le fichier .cpp du projet, jetez-y un coup d'œil et après quelques recherches sur Google et Yandex, je n'ai rien trouvé de bien compliqué, c'est généralement compréhensible. Cela semble même simple.

Mais comment cela fonctionne-t-il ? Je ne suis pas sûr de savoir comment faire référence à ce ddl - à partir du code de l'EA ? Comment ? D'abord, cela ressemble à ceci #include <GetIntValue>.

C'est à peu près comme ça. Pour le faire fonctionner, vous devez compiler la dll et la placer dans le dossier experts/libraries (lisez l'aide et le tutoriel, c'est détaillé là).

//сначала надо объявить импорт функции из DLL
#import "имя_вашей_длл.dll"
int SortStringArray(string *arr[],const int arraysize);
#import


//в тексте программы вызов проще простого

string arr[];
int size;
...
//где-то в коде массив заполняется
...
//а вот и вызов сортировки
SortStringArray(arr,size);

2. Lors de l'appel de la dll, il n'est pas nécessaire de garder le studio allumé, n'est-ce pas ? Comment est-ce exécuté ?

Une DLL est, pour faire simple, un programme Windows normal, sauf que les fonctions qu'elle implémente ne sont pas appelées par un utilisateur, mais par un autre programme. Pour rendre cela possible, nous spécifions le modificateur __declspec(dllexport) au compilateur C++.
 
Trader7777:

J'ai une autre question : j'ai un ordre de suivi. Quand un ordre unidirectionnel est ouvert, tout fonctionne bien, s'il y en a plus, cela ne fonctionne pas pour une raison quelconque. Pourquoi ?

void Trailing ()
{
for(int i = 0; i<OrdersTotal(); i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
{
if (OrderType() == OP_BUY)
{
if(Bid - OrderOpenPrice() > TrailingStop*Point)
{
if (OrderStopLoss() < Bid - (TrailingStop + TrailingStep)*Point)
{
SL = NormalizeDouble(Bid - TrailingStop*Point,Digits);
if (OrderStopLoss() !=SL)
OrderModify(OrderTicket(),OrderOpenPrice(),SL,0,0);
}
}
}
if (OrderType() == OP_SELL)
{
if(OrderOpenPrice() - Ask > TrailingStop*Point)
{
if (OrderStopLoss() > Ask + (TrailingStop+ TrailingStep)*Point)
{
SL = NormalizeDouble (Ask+TrailingStop*Point,Digits);
if (OrderStopLoss() !=SL)
OrderModify (OrderTicket(), OrderOpenPrice(), SL,0,0);
}
}
}
}
}
}
}


Parce que vous devez passer des paramètres dans la fonction, essayez ceci

bool IfProfTrail=false ; // A utiliser uniquement pour les positions rentables - mode Breakeven
int TrailingStop=0 ; // Distance de traînage = 0 - minimum autorisé
int TrailingStep=1 ; // Pas de distance de traînage


void Trailing(string sy="",int op=-1,int mn=-1)
  {
   double po,pp;
   int    i,k=OrdersTotal();
   

   if(sy=="0") sy=Symbol();
   if(TrailingStop==0)TrailingStop=MarketInfo(Symbol(),MODE_STOPLEVEL);
   for(i=0;i<k;i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if((OrderSymbol()==sy || sy=="") && (op<0 || OrderType()==op))
           {
            po=MarketInfo(OrderSymbol(),MODE_POINT);
            if(mn<0 || OrderMagicNumber()==mn)
              {
               if(OrderType()==OP_BUY)
                 {
                  pp=MarketInfo(OrderSymbol(),MODE_BID);
                  if((!IfProfTrail && OrderProfit()>0) || pp-OrderOpenPrice()>TrailingStop*po)
                    {
                     if(OrderStopLoss()<pp-(TrailingStop+TrailingStep-1)*po)
                       {
                        ModifyOrder(-1,pp-TrailingStop*po,-1);
                       }
                    }
                 }
               if(OrderType()==OP_SELL)
                 {
                  pp=MarketInfo(OrderSymbol(),MODE_ASK);
                  if((!IfProfTrail && OrderProfit()>0) || OrderOpenPrice()-pp>TrailingStop*po)
                    {
                     if(OrderStopLoss()>pp+(TrailingStop+TrailingStep-1)*po || OrderStopLoss()==0)
                       {
                        ModifyOrder(-1,pp+TrailingStop*po,-1);
                       }
                    }
                 }
              }
           }
        }
     }
  }


 
Forexman77:

Merci beaucoup !

Je comprends maintenant quel est le problème.

Pour l'achat, j'ai utilisé :

Pour autant que je sache, l'achat se fait à la demande, mais iClose(Symbol(),Period(),0) prend les prix à la demande. Cela peut être la raison de l'erreur.

Maintenant, j'utilise la combinaison suivante :

Mais ici la question se pose, car l'EA n'est pas un EA basé sur les Pips, le prix était dans la zone d'achat depuis longtemps et mis à jour avec chaque tick.

Pourquoi le commerce ne s'ouvre-t-il pas ? Il s'avère que l'EA s'arrête sur l'erreur et ne voit pas de mouvement de prix supplémentaire ?

J'ai pris le modèle de mon conseiller expert sur https://c.mql5.com/mql4/book/mq4/experts/tradingexpert.mq4.

À votre avis, dois-je ajouter à la fonction de traitement des erreurs dans cet EA une vérification des erreurs 129 et 138 ?

Si oui, comment faire ?

Au minimum, vous devez disposer de votre propre fonction d'ouverture des positions/de définition des ordres qui traitera toutes les erreurs. C'est ici que vous devez obtenir les derniers prix.

Je n'ai pas regardé d'ébauches. Mais je dirai que l'EA doit gérer toutes les erreurs renvoyées par le serveur. Et ce n'est pas suffisant. Il doit pouvoir reprendre ses positions après toute situation inattendue sans perte de fonctionnalité et sans défaillance de l'algorithme, et poursuivre son travail comme si rien d'extraordinaire ne s'était produit.

 
compilez-le et mettez-le dans le dossier experts/libraries Voilà, merci !!! Je vais essayer maintenant. Et je l'ai déjà vu, mais maintenant je ne trouve rien d'aussi détaillé et digeste, sur le sujet.
 
artmedia70:

Vous devriez au moins avoir votre propre fonction d'ouverture des positions/de définition des ordres qui gère toutes les erreurs. C'est là que vous devez trouver les derniers prix.

Je n'ai pas regardé les plans. Mais je dirai que vous devez gérer toutes les erreurs renvoyées par le serveur dans votre EA. Et ce n'est pas suffisant. Il doit pouvoir reprendre ses positions après toute situation imprévue, sans perte de fonctionnalité, sans défaillance de son algorithme, et poursuivre son travail comme si rien d'extraordinaire ne s'était produit.


Le modèle est tiré d'un manuel scolaire. Je ne suis pas très doué pour les fonctions de gestion des erreurs.

A l'ouverture de l'ordre, il y a RefreshRates() ; (j'ai remplacé les Bids et Asks par Market Info comme suggéré).

 while(true)                                  // Цикл закрытия орд.
     {
      if (Total==0 && Opn_B==true)              // Открытых орд. нет +
        {                                       // критерий откр. Buy
         RefreshRates();                        // Обновление данных
         SL=Bid - New_Stop(StopLoss)*Point;     // Вычисление SL откр.
         TP=Bid + New_Stop(TakeProfit)*Point;   // Вычисление TP откр.
         Alert("Попытка открыть Buy. Ожидание ответа..");
         Ticket=OrderSend(Symb,OP_BUY,Lts,Ask,2,SL,TP);//Открытие Buy
         if (Ticket > 0)                        // Получилось :)
           {
            Alert ("Открыт ордер Buy ",Ticket);
            return;                             // Выход из start()
           }
         if (Fun_Error(GetLastError())==1)      // Обработка ошибок
            continue;                           // Повторная попытка
         return;                                // Выход из start()
        }

Et une fonction de gestion des erreurs :

int Fun_Error(int Error)                        // Ф-ия обработ ошибок
  {
   switch(Error)
     {                                          // Преодолимые ошибки            
      case  4: Alert("Торговый сервер занят. Пробуем ещё раз..");
         Sleep(3000);                           // Простое решение
         return(1);                             // Выход из функции
      case 135:Alert("Цена изменилась. Пробуем ещё раз..");
         RefreshRates();                        // Обновим данные
         return(1);                             // Выход из функции
      case 136:Alert("Нет цен. Ждём новый тик..");
         while(RefreshRates()==false)           // До нового тика
            Sleep(1);                           // Задержка в цикле
         return(1);                             // Выход из функции
      case 137:Alert("Брокер занят. Пробуем ещё раз..");
         Sleep(3000);                           // Простое решение
         return(1);                             // Выход из функции
      case 146:Alert("Подсистема торговли занята. Пробуем ещё..");
         Sleep(500);                            // Простое решение
         return(1);                             // Выход из функции
         // Критические ошибки
      case  2: Alert("Общая ошибка.");
         return(0);                             // Выход из функции
      case  5: Alert("Старая версия терминала.");
         Work=false;                            // Больше не работать
         return(0);                             // Выход из функции
      case 64: Alert("Счет заблокирован.");
         Work=false;                            // Больше не работать
         return(0);                             // Выход из функции
      case 133:Alert("Торговля запрещена.");
         return(0);                             // Выход из функции
      case 134:Alert("Недостаточно денег для совершения операции.");
         return(0);                             // Выход из функции
      default: Alert("Возникла ошибка ",Error); // Другие варианты   
         return(0);                             // Выход из функции
     }
  }

Je voulais demander. Je voudrais demander : puis-je y ajouter une autre ligne de l'erreur 129 ?

      case 129:Alert("Неправильные цены. Пробуем ещё раз..");
         RefreshRates();                        // Обновим данные
         return(1); 
 
J'ai l' ensemble du projet Visual Studio dans mon dossier d' experts... Compile est un fichier .exe, non ? Je voulais le copier dans le dossier libarries... Je ne le trouve pas ! Voici le dossier de débogage du projet. Je suis désolé, c'est un nouveau sujet.