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// Указатель на стринг, я плохо помню.
};
staticint CompareMqlStr(constvoid *left,constvoid *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(constint ipar) // __stdcall кладет аргументы в стек справа налево
{ // MT4_EXPFUNC говорит что функция будет видима из метатрайдера, я не совсем понял.printf("GetIntValue takes %d\n",ipar);
return(ipar);
}
//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+
MT4_EXPFUNC double __stdcall GetDoubleValue(constdouble 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(constdouble *arr,constint arraysize,constint 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,constint arraysize,constint nitem,constdouble 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,constint rates_total,constint shift,constint 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)
{
case0: returndouble(rates[nitem].ctm);
case1: return rates[nitem].open;
case2: return rates[nitem].low;
case3: return rates[nitem].high;
case4: return rates[nitem].close;
case5: return rates[nitem].vol;
}
//---return(0.0);
}
//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall SortStringArray(MqlStr *arr,constint 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,constint 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 stringif(arr[i+1].string==NULL) continue;
//--- destination string is uninitialized and cannot be allocated within dllif(arr[i].string==NULL) continue;
//--- memory piece is less than needed and cannot be reallocated within dllif(arr[i].len<len1+len2) continue;
//--- final processing
strcat(arr[i].string,arr[i+1].string);
}
//---return(arraysize);
}
//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+int CompareMqlStr(constvoid *left,constvoid *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.
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 ?
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[],constint 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++.
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 ?
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
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 ?
À 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.
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);//Открытие Buyif (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)
{ // Преодолимые ошибки case4: Alert("Торговый сервер занят. Пробуем ещё раз..");
Sleep(3000); // Простое решениеreturn(1); // Выход из функцииcase135:Alert("Цена изменилась. Пробуем ещё раз..");
RefreshRates(); // Обновим данныеreturn(1); // Выход из функцииcase136:Alert("Нет цен. Ждём новый тик..");
while(RefreshRates()==false) // До нового тикаSleep(1); // Задержка в циклеreturn(1); // Выход из функцииcase137:Alert("Брокер занят. Пробуем ещё раз..");
Sleep(3000); // Простое решениеreturn(1); // Выход из функцииcase146:Alert("Подсистема торговли занята. Пробуем ещё..");
Sleep(500); // Простое решениеreturn(1); // Выход из функции// Критические ошибкиcase2: Alert("Общая ошибка.");
return(0); // Выход из функцииcase5: Alert("Старая версия терминала.");
Work=false; // Больше не работатьreturn(0); // Выход из функцииcase64: Alert("Счет заблокирован.");
Work=false; // Больше не работатьreturn(0); // Выход из функцииcase133:Alert("Торговля запрещена.");
return(0); // Выход из функцииcase134: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 ?
case129: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.
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>.
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.
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
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 ?
{
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);
}
}
}
}
}
}
}
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à).
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é ?
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 ?
{
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
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.
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.Maintenant, j'utilise la combinaison suivante :
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.
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é).
Et une fonction de gestion des erreurs :
Je voulais demander. Je voudrais demander : puis-je y ajouter une autre ligne de l'erreur 129 ?