Нет, так нельзя. В строке double "res=end[0]-start[0];" игнорируются значения end[1], start[1], которые могут быть не одинаковыми. Кроме того, надо учесть, что в MT4 end[0], start[0] воспринимаются как знаковые целые!
Все верно. Так же, как GetTickCount через 49 суток начнет отсчет с нуля, здесь "малый" круг в зависимости от частоты составит около 20 минут. А "знаковость" проявится через полкруга, т.е. минут через 10 величина интервала станет отрицательной.
И, да, частота не меняется. Она очевидно как-то связана с номинальной частотой процессора (примерно в 1000 раз меньше), но от нагрузки не меняется.
Ну, во-первых, 49 суток - это не 10 минут. Вероятность исполнения ордера за 1 секунду в момент переполнения функции GetTickCount равна 1 с / 49 суток = 1/4233600 (т.е. 1 ордер из 4 млн.), а вот "знаковость" end[0], start[0] будут проявляться значительно чаще, вероятность равна 1 с / 10 мин = 1/600 (т.е. 1 ордер на 600).
Во-вторых, я не знаю, как посчитано время круга 20 минут, а полкруга 10 минут. У меня на двуядерном процессоре AMD Athlon 64 X2 4800+ с текущей частотой около 2511 МГц (взято из CPU-Z) частота тиков freq[0]=25000000. Т.е. полный круг займёт 4294967296/25000000 сек = 172 сек, а полкруга - 86 секунд! И это действительно так, я проверял. А это значит, что время исполнения каждого 86-го ордера будет вычислено неправильным. Учитывая, что некоторые ордера могут исполняться до 20 секунд (пост #101), время исполнения такого каждого 5-го ордера будет неверным.
Предлагаю свой код, который учитывает проблемы переполнения и "знаковости" в функции GetElapsedTime:
#import "Kernel32.dll"
int QueryPerformanceFrequency(int &a[]);
int QueryPerformanceCounter(int &a[]);
#import
int start_tick[2], cur_tick[2], start_freq[2], cur_freq[2];
bool MeasureOrderExecutionTime;
void StartTimer() // запускает (перезапускает) таймер
{
QueryPerformanceFrequency(start_freq);
QueryPerformanceCounter(start_tick);
}
double GetElapsedTime() // возвращает текущее значение таймера в мс
{
QueryPerformanceCounter(cur_tick);
QueryPerformanceFrequency(cur_freq);
double ticks=cur_tick[0]-start_tick[0];
// следующие 2 строчки учитывают проблему "знаковости"
if (cur_tick[0]<0) ticks=ticks+4294967296.0;
if (start_tick[0]<0) ticks=ticks-4294967296.0;
// следующая строка учитывает возможное изменение старших 32 бит
// длинного целого ("переполнение")
ticks=ticks+(cur_tick[1]-start_tick[1])*4294967296.0;
return(ticks*2000.0/(start_freq[0]+cur_freq[0]));
// учтено возможное изменение частоты
}
void init()
{
MeasureOrderExecutionTime=QueryPerformanceFrequency(start_freq)!=0;
if (!MeasureOrderExecutionTime)
Print("Измерение времени исполнения торговых приказов недоступно!");
<...>
}
int start()
{
<...>
if (MeasureOrderExecutionTime) StartTimer();
ticket = OrderSend(<...>);
if (MeasureOrderExecutionTime)
Print("Время исполнения = "+GetElapsedTime()+" мс");
<...>
}
Код также предусматривает возможное изменение частоты тиков (start_freq и cur_freq). Хотя я на своём Desktop-е, как и уважаемый kazakov.v, не обнаружил изменений значений частоты, возвращаемой функцией QueryPerformanceFrequency, это ещё не означает, что реальная частота тиков не меняется (ведь частота процессора у меня несколько плавает, что видно из CPU-Z). Постоянство значения, возвращаемой функцией QueryPerformanceFrequency, при плавающей частоте тиков может быть связано с аппаратными или программными особенностями системы. Про это можно прочитать здесь и в замечаниях ("Remarks") описания функции QueryPerformanceCounter. Не факт, что такое положение останется навсегда для всех систем, поэтому лучше перестраховаться усреднением начальной и текущей частоты ( (start_freq[0]+cur_freq[0])/2 ).
Функция GetElapsedTime может быть использована, не только для измерения времени исполнения приказа, но и для измерения значительно более длительных промежутков времени.