#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#define OBJ_NAME_ASK "TestObjectMoveAsk" // nom de l'objet graphique pour le prix Ask (Demande)
#define OBJ_NAME_BID "TestObjectMoveBid" // nom de l'objet graphique pour le prix Bid (Offre)
#define COUNT 100000000 // nombre de ticks à charger depuis l'historique
#define DELAY 1 // délai entre les ticks en ms
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- id du graphique actuel, le symbole du graphique et les décimales du symbole
long chart_id= ChartID();
string symbol = ChartSymbol(chart_id);
int digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
//--- crée deux étiquettes de prix pour afficher le prix de vente et le prix d'achat sur le graphique
if(!CreatePriceLabel(chart_id, true) || !CreatePriceLabel(chart_id, false))
return;
//--- tableau pour recevoir les ticks
MqlTick ticks[]={};
//--- récupère le numéro de la prochaine barre visible sur le graphique et l'heure d'ouverture de cette barre en millisecondes
int first= (int)ChartGetInteger(chart_id, CHART_FIRST_VISIBLE_BAR)-1;
ulong from = GetTime(symbol, PERIOD_CURRENT, first)*1000;
//--- charge l'historique des ticks dans le tableau
Print("Started collecting ticks...");
if(!GetTicksToArray(symbol, ticks))
return;
//--- réinitialise le tableau des ticks et récupère les ticks de la plage de barres visibles sur le graphique
ZeroMemory(ticks);
if(CopyTicksRange(symbol, ticks, COPY_TICKS_INFO, from)<1)
{
PrintFormat("CopyTicksRange() from date %s failed. Error %d", TimeToString(GetTime(symbol, PERIOD_CURRENT, first)), GetLastError());
return;
}
Sleep(500);
PrintFormat("Tick visualization started at %s (%I64u), ticks total: %u", TimeToString(GetTime(symbol, PERIOD_CURRENT, first)), from, ticks.Size());
int count=0; // nombre de ticks traités
int changes=0; // nombre de changements de prix effectués
int total=(int)ticks.Size(); // taille du tableau de ticks
//--- en boucle sur le tableau de ticks
for(int i=0; i<total && !IsStopped(); i++)
{
//--- prends un tick du tableau et incrémente le compteur de ticks
MqlTick tick=ticks[i];
count++;
//--- vérifie les flags des prix Ask et Bid
bool ask_tick=((tick.flags &TICK_FLAG_ASK)==TICK_FLAG_ASK);
bool bid_tick=((tick.flags &TICK_FLAG_BID)==TICK_FLAG_BID);
bool done=false;
//--- si le prix de la demande (Ask) change
if(ask_tick)
{
if(Move(chart_id, OBJ_NAME_ASK, tick.time, tick.ask))
{
changes++;
done=true;
}
}
//--- si le prix de l'offre (Bid) change
if(bid_tick)
{
if(Move(chart_id, OBJ_NAME_BID, tick.time, tick.bid))
{
changes++;
done=true;
}
}
//--- si l'un (ou les deux) des objets graphiques a été déplacé, met à jour le graphique
if(done)
{
ChartRedraw(chart_id);
Sleep(DELAY);
}
}
//--- à la fin de la boucle, nous écrirons dans le journal le nombre de ticks traités.,
//--- attends 2 secondes, supprime les objets créés et redessine le graphique
PrintFormat("Total ticks completed: %u, Total price changes: %d", count, changes);
Sleep(2000);
if(ObjectsDeleteAll(chart_id, "TestObjectMove")>0)
ChartRedraw(chart_id);
/*
à la suite de l'exécution du script, les mouvements des prix Ask et Bid seront affichés sur le graphique visible,
en partant du bord gauche du graphique et jusqu'à la fin des données historiques,
les données suivantes seront écrites dans le journal :
Started collecting ticks...
AUDUSD: received 13726794 ticks in 969 ms
Tick visualization started at 2025.01.31 09:00 (1738314000000), ticks total: 44380
Total ticks completed: 44380, Total price changes: 68513
*/
}
//+------------------------------------------------------------------+
//| Crée un objet "Etiquette de prix" |
//+------------------------------------------------------------------+
bool CreatePriceLabel(const long chart_id, const bool obj_ask)
{
string obj_name=(obj_ask ? OBJ_NAME_ASK : OBJ_NAME_BID);
ResetLastError();
if(!ObjectCreate(chart_id, obj_name, (obj_ask ? OBJ_ARROW_RIGHT_PRICE : OBJ_ARROW_LEFT_PRICE), 0, 0, 0))
{
PrintFormat("%s: ObjectCreate() failed. Error %d",__FUNCTION__, GetLastError());
return(false);
}
return(ObjectSetInteger(chart_id, obj_name, OBJPROP_COLOR, (obj_ask ? clrRed : clrBlue)));
}
//+------------------------------------------------------------------+
//| Déplace l'objet graphique aux coordonnées prix/heure spécifiées |
//+------------------------------------------------------------------+
bool Move(const long chart_id, const string obj_name, const datetime time, const double price)
{
ResetLastError();
if(!ObjectSetInteger(chart_id, obj_name, OBJPROP_TIME, time))
{
PrintFormat("%s: ObjectSetInteger() failed. Error %d",__FUNCTION__, GetLastError());
return(false);
}
if(!ObjectSetDouble(chart_id, obj_name, OBJPROP_PRICE, price))
{
PrintFormat("%s: ObjectSetDouble() failed. Error %d",__FUNCTION__, GetLastError());
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| Charge les ticks dans le tableau |
//+------------------------------------------------------------------+
bool GetTicksToArray(const string symbol, MqlTick &array[])
{
int attempts=0; // compteur des tentatives d'obtention de l'historique des ticks
bool success =false; // flag de copie réussie des ticks
//--- effectue 3 tentatives pour recevoir les ticks
while(attempts<3)
{
//--- mesure l'heure de départ avant de recevoir les ticks
uint start=GetTickCount();
//--- demande l'historique des ticks depuis le 01/01/1970 00:00.001 (paramètre from=1 ms)
ResetLastError();
int received=CopyTicks(symbol, array, COPY_TICKS_ALL, 1, COUNT);
if(received!=-1)
{
//--- afffiche le nombre de ticks et le temps passé
PrintFormat("%s: received %d ticks in %d ms", symbol, received, GetTickCount()-start);
//--- si l'historique des ticks est synchronisé, le code d'erreur est égal à 0
if(GetLastError()==0)
{
success=true;
break;
}
else
PrintFormat("%s: %s ticks are not synchronized yet, %d ticks received for %d ms. Error=%d",
__FUNCTION__, symbol, received, GetTickCount()-start, GetLastError());
}
//--- comptage des tentatives
attempts++;
//--- une pause d'1 seconde pour attendre la fin de la synchronisation de la base de données des ticks
Sleep(1000);
}
//--- la réception des ticks demandés depuis le début de l'historique des ticks a échoué en trois tentatives.
if(!success)
{
PrintFormat("Error! Failed to get ticks for symbol %s after three attempts", symbol);
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| Renvoie l'heure de la barre à l'index |
//+------------------------------------------------------------------+
datetime GetTime(const string symbol, const ENUM_TIMEFRAMES timeframe, const int index)
{
datetime array[1]={};
ResetLastError();
if(CopyTime(symbol, timeframe, index, 1, array)!=1)
PrintFormat("%s: CopyTime() failed. Error %d",__FUNCTION__, GetLastError());
return(array[0]);
}
|