Jede Anfängerfrage, um das Forum nicht zu überladen. Fachleute, gehen Sie nicht vorbei. Nirgendwo ohne dich - 6. - Seite 342

 

Hier ist die .cpp-Datei des Projekts, schauen Sie es sich an, und nach ein paar Google- und Yandex-Suchen habe ich überhaupt nichts Gescheites gefunden, es ist allgemein verständlich. Es scheint sogar einfach zu sein.

//+------------------------------------------------------------------+
//| 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));
}
//+------------------------------------------------------------------+

Aber wie funktioniert das? Ich bin mir nicht ganz sicher, wie man auf diese ddl verweisen - aus dem Code des EA? Wie? Zunächst sieht es so aus: #include <GetIntValue>.

2. Wenn man die DLL aufruft, muss man das Studio nicht eingeschaltet lassen, oder? wie wird es ausgeführt?

Bitte zeigen Sie das einfachste Beispiel für den Aufruf dieser DLL aus dem MQL-Code.

 
Trader7777:

Ich verstehe das hier nicht...


Die Losgröße sollte exponentiell ansteigen (mit Multiplikator 2), wenn ein zweiter unidirektionaler Auftrag eröffnet wird.



Das ist das Ergebnis.

dann wie folgt

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:


erhalten Sie ein Ergebnis wie dieses

Dann war's das.


Danke, ich habe verstanden... Ich habe es verstanden.

Wofür ist diese Zeile?


datetime o;
 

Ich habe eine weitere Frage: Ich habe einen Auftrag im Nachlauf. Wenn 1 unidirektionaler Auftrag offen ist, funktioniert alles gut, wenn mehr, funktioniert es aus irgendeinem Grund nicht. Und warum?

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:

Hier ist die .cpp-Datei des Projekts, schauen Sie es sich an, und nach ein paar Google- und Yandex-Suchen habe ich überhaupt nichts Gescheites gefunden, es ist allgemein verständlich. Es scheint sogar einfach zu sein.

Aber wie funktioniert das? Ich bin nicht ganz sicher, wie man auf diese ddl verweisen - aus dem Code des EA? Wie? Zunächst sieht es so aus: #include <GetIntValue>.

Das ist ungefähr so. Damit es funktioniert, müssen Sie die dll kompilieren und im Ordner experts/libraries ablegen (lesen Sie die Hilfe und das Tutorial, dort ist es ausführlich beschrieben).

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


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

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

2. Wenn man die DLL aufruft, muss man das Studio nicht eingeschaltet lassen, richtig? Wie wird es also ausgeführt?

Eine DLL ist, um es einfach auszudrücken, ein normales Windows-Programm, mit dem Unterschied, dass die Funktionen, die es implementiert, nicht von einem Benutzer, sondern von einem anderen Programm aufgerufen werden. Um dies zu ermöglichen, geben wir dem C++-Compiler den Modifikator __declspec(dllexport) an.
 
Trader7777:

Ich habe eine weitere Frage: Ich habe einen Auftrag im Nachlauf. Wenn 1 unidirektionaler Auftrag offen ist, funktioniert alles gut, wenn mehr, funktioniert es aus irgendeinem Grund nicht. Und warum?

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);
}
}
}
}
}
}
}


Da Sie Parameter an die Funktion übergeben müssen, versuchen Sie Folgendes

bool IfProfTrail=false; // Nur für profitable Positionen verwenden - Breakeven-Modus
int TrailingStop=0; // Schleppabstand = 0 - Mindestabstand
int TrailingStep=1; // Schleppender Abstandsschritt


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:

Herzlichen Dank!

Jetzt verstehe ich, wo das Problem liegt.

Für den Kauf habe ich verwendet:

Soweit ich weiß, ist der Kauf ein Kauf, aber iClose(Symbol(),Periode(),0) nimmt die Preise vom Angebot. Dies kann der Grund für den Fehler sein.

Jetzt verwende ich die folgende Kombination:

Aber hier stellt sich die Frage, denn der EA ist kein Pips-basierter EA, der Preis war lange Zeit in der Kaufzone und wurde mit jedem Tick aktualisiert.

Warum wird der Handel nicht eröffnet? Es stellt sich heraus, dass der EA auf den Fehler stoppt und nicht sehen, weitere Preisbewegung?

Ich habe die Vorlage für meinen Expert Advisor von https://c.mql5.com/mql4/book/mq4/experts/tradingexpert.mq4 übernommen.

Sollte ich Ihrer Meinung nach der Fehlerbehandlungsfunktion in diesem EA eine Prüfung auf 129 und 138 Fehler hinzufügen?

Wenn ja, wie kann man das tun?

Zumindest müssen Sie eine eigene Funktion für die Eröffnung von Positionen/Aufträgen haben, die alle Fehler behandelt. Hier müssen Sie sich über die neuesten Preise informieren.

Ich habe mir keine Rohlinge angeschaut. Aber ich will sagen: der EA muss alle vom Server zurückgegebenen Fehler behandeln. Und das ist noch nicht genug. Es sollte in der Lage sein, seine Positionen nach einer unerwarteten Situation ohne Funktionsverlust und ohne Ausfall des Algorithmus wieder einzunehmen und seine Arbeit fortzusetzen, als ob nichts Außergewöhnliches passiert wäre.

 
kompilieren und im Ordner experts/libraries ablegen Bitte sehr, danke!!! Ich werde es jetzt versuchen. Und ich habe vor, aber jetzt habe ich nicht finden, etwas so detailliert und verdaulich zu diesem Thema.
 
artmedia70:

Zumindest sollten Sie eine eigene Funktion zum Öffnen von Positionen/Aufträgen haben, die alle Fehler behandelt. Dort müssen Sie sich über die neuesten Preise informieren.

Ich habe mir keine Baupläne angesehen. Aber ich will sagen: Sie müssen alle vom Server zurückgegebenen Fehler in Ihrem EA behandeln. Und das ist nicht genug. Es muss in der Lage sein, nach einer unvorhergesehenen Situation seine Positionen wieder einzunehmen, ohne dass es zu einem Funktionsverlust oder einem Ausfall seines Algorithmus kommt, und seine Arbeit fortzusetzen, als ob nichts Außergewöhnliches passiert wäre.


Die Vorlage stammt aus einem Lehrbuch. Ich bin nicht wirklich gut im Umgang mit Fehlerfunktionen.

Bei Auftragseröffnung gibt es RefreshRates(); (Ich habe Bids und Asks durch Market Info ersetzt, wie vorgeschlagen).

 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()
        }

Und eine Funktion zur Fehlerbehandlung:

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);                             // Выход из функции
     }
  }

Das wollte ich fragen. Ich möchte fragen: Darf ich eine weitere Zeile aus 129 Fehler hinzufügen?

      case 129:Alert("Неправильные цены. Пробуем ещё раз..");
         RefreshRates();                        // Обновим данные
         return(1); 
 
Ich habe das gesamte Visual Studio-Projekt in meinem Expertenordner... Compile ist eine .exe-Datei, richtig? Ich wollte es in den Ordner libarries kopieren... Ich kann es nicht finden! Hier ist der Debug-Ordner des Projekts. Tut mir leid, das ist ein neues Thema.