Questions des débutants MQL5 MT5 MetaTrader 5 - page 577

 
Artyom Trishkin:
Eh bien, je formerais tout cela dans une fonction, et je l'appellerais quand j'en ai besoin - même à chaque tick (si c'est raisonnable et nécessaire), ou à l'ouverture d'une nouvelle bougie - par exemple, une fois par heure, si nous travaillons en H1.

Avec la fonction, bien sûr, c'est pratique. J'ai compris le code. C'est clair maintenant. Je réfléchirai à la manière de l'amener aux fins que je souhaite et je comprendrai quand et à quel stade il faut prendre les données nécessaires.

 
Koldun Zloy:

Si c'était carrément "le comble de l'imprudence", ce serait interdit.

WinAPI étend considérablement les capacités de MQL. Et vous pouvez faire quelque chose de stupide même sans dll.

Et voici un exemple de passage de chaîne vers le presse-papiers :

Bien joué, et avec des commentaires en plus.

Merci.

Voici une autre question.

Serait-il possible d'émuler un clic de souris à des coordonnées données ?

 
mila.com:

Super, et avec un commentaire en plus.

Merci.

Une dernière question.

Est-il possible de faire une émulation d'un clic de souris aux coordonnées données ?

Si vous ne devez pas le faire à partir de MQL, regardez AutoIT, vous pouvez tout y faire. Le produit est gratuit, vous n'avez besoin que d'une DLL pour interagir avec MQL.
 
mila.com:

Super, et avec des commentaires en plus.

Merci.

Une dernière question.

Est-il possible de faire une émulation d'un clic de souris aux coordonnées données ?

Oui, nous le pouvons.

#define  MK_LBUTTON     0x0001
#define  WM_LBUTTONDOWN 0x0201
#define  WM_LBUTTONUP   0x0202

struct POINT
{
   int x;
   int y;
};

#import "User32.dll"
   uint WindowFromPoint( int x, int y );
   uint PostMessageW( uint hWnd, uint Msg, uint wParam, uint lParam );
   int ScreenToClient( uint hWnd, POINT& lpPoint );
#import

int x = 1000;  // Экранные координаты
int y = 350;

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   uint hwnd = WindowFromPoint( x, y ); // Получаем дескриптор окна в нужном месте
   
   if( hwnd ){
      POINT point;
      point.x = x;
      point.y = y;
      ScreenToClient( hwnd, point );  // Преобразуем экранные координаты в координаты рабочей области окна
      
      uint lParam = (point.y * 65536) + (point.x & 0xFFFF);  // Упаковываем координаты в 32-разрядное целое
      
      PostMessageW( hwnd, WM_LBUTTONDOWN, MK_LBUTTON, lParam ); // Посылаем сообщения от "мыши"
      PostMessageW( hwnd, WM_LBUTTONUP, MK_LBUTTON, lParam );
   }
}
 
Artyom Trishkin:
Eh bien, je formulerais tout cela dans une fonction et je l'appellerais quand je le voudrais - à chaque tick (si nécessaire et raisonnable) ou à l'ouverture d'une nouvelle bougie - par exemple, une fois par heure, si nous travaillons avec H1.

Artem, je comprends bien, si nous avons une boucle:for(int i=0 ; i<copy_bars ; i++) et qu'il y a une boucle for(int j=0 ; j<copy_bars ; j++) où if(j==i) continue ; ,

cela signifie que le calcul est parallèle et si nous avons environ 5 chandeliers, la comparaison se poursuivra :

1 avec 1 - à rejeter.

1 avec 2, 1 avec 3, 1 avec 4, 1 avec 5.

Puis un cycle commencera là où il sera :

2 avec 1, 2 avec 3, 2 avec 4, 2 avec 5.

et ainsi de suite.

C'est comme ça que ça va être ?

 
Andrey Koldorkin:

Artem, je comprends bien, que si nous avons une boucle:for(int i=0 ; i<copy_bars ; i++) et qu'il y a une boucle for(int j=0 ; j<copy_bars ; j++) où if(j==i) continue ; ,

cela signifie que le calcul est parallèle et si nous avons environ 5 chandeliers, la comparaison se poursuivra :

1 avec 1 - à rejeter.

1 avec 2, 1 avec 3, 1 avec 4, 1 avec 5.

Puis un cycle commencera là où il sera :

2 avec 1, 2 avec 3, 2 avec 4, 2 avec 5.

et ainsi de suite.

Est-ce que ce sera la même chose ?

Oui.
 
Artyom Trishkin:
Oui.

Autre question : si nous n'avons pas besoin de comparer la bougie actuelle, ne devons-nous pas commencer le compte à partir de 1 et non de zéro ?

Ou devons-nous comprendre qu'ici, 0 est la bougie 1, 1 est la bougie 2, etc.

 
Andrey Koldorkin:

Autre question : si nous n'avons pas besoin de comparer la bougie actuelle, ne devons-nous pas commencer le compte à partir de 1 et non de zéro ?

ou devons-nous comprendre qu'ici 0 est la bougie 1, 1 est la bougie 2, etc ?

Ici, zéro est le début du tableau. Et dans le tableau, nous écrivons les chandeliers de la première à ..., pas "à", mais dans le nombre dont nous avons besoin :

int copied=CopyRates(Symbol(),PERIOD_CURRENT,1,copy_bars,array);

1 est le numéro du chandelier à copier, et copy_bars est le nombre de chandeliers à copier.

Par conséquent, array[] contient le chandelier nécessaire dans la cellule d'indice 0 - soit 1, soit 1+copy_bars-1. En fonction du sens d'indexation de array[] (ArraySetAsSeries() définit le sens d'indexation, qui peut être vérifié à l'aide de ArrayGetAsSeries(), ArrayIsSeries()).

 
Artyom Trishkin:

Ici, zéro est le début du tableau. Et dans le tableau, nous écrivons les chandeliers du premier au ..., pas "au", mais en nombre de chandeliers dont nous avons besoin :

1 est le numéro du chandelier à copier, et copy_bars est le nombre de chandeliers à copier.

Par conséquent, array[] contient la bougie requise dans la cellule avec l'indice 0 - soit 1, soit 1+copy_bars-1. En fonction de la direction d'indexation de array[] (ArraySetAsSeries() définit la direction d'indexation, ce qui peut être vérifié avec ArrayGetAsSeries(), ArrayIsSeries())

Oh, cette programmation. Plus on avance dans les bois....

J'ai d'abord vérifié ce qu'il montre via Alert. Il semble que ce soit l'inverse, c'est-à-dire que la bougie la plus proche de la bougie actuelle a un nombre maximal.

Puis je l'ai vérifié via :

bool series=ArrayIsSeries(dataCandle) ;

Alerte (série) ;

et le script affiche "faux".

Selon ma logique, si le faux est au mauvais bout, alors le vrai sera au bon bout.

J'ai prescrit :

ArraySetAsSeries (dataCandle, true) ; //changer de direction

bool series=ArrayIsSeries(dataCandle) ; //vérifier encore une fois

Alert (série) ; //écrit le résultat à l'écran.

Mais je reçois toujours des "faux" après ça.

Quel est mon problème ?

 
Andrey Koldorkin:

Oh, cette programmation. Plus on avance dans les bois....

J'ai d'abord vérifié juste par le biais d'Alert ce qu'il donnait. Il s'avère que c'est le contraire, c'est-à-dire que la bougie la plus proche de la bougie actuelle a le nombre maximum.

Puis je l'ai vérifié via :

bool series=ArrayIsSeries(dataCandle) ;

Alerte (série) ;

et le script affiche "faux".

Selon ma logique, si le faux est au mauvais bout, alors le vrai sera au bon bout.

J'ai prescrit :

ArraySetAsSeries (dataCandle, true) ; //changer de direction

bool series=ArrayIsSeries(dataCandle) ; //vérifier encore une fois

Alert (série) ; //écrit le résultat à l'écran.

Mais je reçois toujours des "faux" après ça.

Quel est mon problème ?

Le dataCandles est une structure. Le tableau où nous écrivons les bougies de l'historique - array[]. Et nous devons en faire une série temporelle pour que son indexation coïncide avec l'indexation des bougies sur le graphique. C'est-à-dire que la cellule zéro du tableau[] correspondra aux chandeliers les plus proches de la date actuelle.

C'est-à-dire 1. copier les chandeliers dans le tableau array[], 2. en faire une série temporelle, puis lire les valeurs de celle-ci dans la structure.

Vous pouvez faire sans array[] - juste écrire les données directement du graphique dans la structure, mais j'ai suggéré ceci pour la compatibilité avec Five - il permet de copier directement seulement dans l'indicateur en utilisant high[i], low[i] et d'autres données, mais dans le script ou Expert Advisor, nous devons d'abord copier l'intervalle historique nécessaire dans le tableau, ce que j'ai fait.

Raison: