Вопросы от начинающих MQL5 MT5 MetaTrader 5 - страница 856

 
Алексей Барбашин:

Хм... вероятно я не совсем внимательно смотрел API, но не заметил такой функции.... А было бы скорее всего удобно. 

Может еще подскажете... возможно вопрос слишком .. нелепый... Как число, например double, перевести в массив char? То есть в некоторых API требуется передавать числа в виде указателя. Указатели передаются в виде одномерных массивов... Со строками понятно, для них предусмотрены функции StringToShortArray и StringToCharArray, а вот с числами я пока не понял как их переводить в байтовые массивы (char).

Может какой-то пример?
 
. ... Rick D. ... .:
Может какой-то пример?

Далеко пожалуй ходить не будем. Рассмотрим работу с реестром. В реестр можно помещать как строчные величины, так и числовые (не в виде строки). Передачу в реестр числа и получение обратно указателя на него происходит посредством массивов (согласно Вашему исправлению). Такой пример подойдет? 

 
pivomoe:

Изучаю историю тиков. Не всегда получается понять, что происходило на рынке в момент появления тиков.

SBER

i=987 2016.06.27 10:00:30.274  Ask=133.91  Bid=133.9  Last=133.9   Vol=50   TICK_FLAG_ASK 

i=988 2016.06.27 10:00:30.280  Ask=133.93  Bid=133.9  Last=133.9   Vol=50   TICK_FLAG_ASK 

i=989 2016.06.27 10:00:30.280  Ask=133.93  Bid=133.9  Last=133.91   Vol=100   TICK_FLAG_LAST  TICK_FLAG_VOLUME  TICK_FLAG_BUY  TICK_FLAG_SELL 

i=990 2016.06.27 10:00:30.280  Ask=133.93  Bid=133.9  Last=133.92   Vol=300   TICK_FLAG_LAST  TICK_FLAG_VOLUME  TICK_FLAG_BUY  TICK_FLAG_SELL 

i=991 2016.06.27 10:00:30.280  Ask=133.93  Bid=133.9  Last=133.92   Vol=100   TICK_FLAG_LAST  TICK_FLAG_VOLUME  TICK_FLAG_BUY  TICK_FLAG_SELL 

i=992 2016.06.27 10:00:30.281  Ask=133.94  Bid=133.9  Last=133.92   Vol=100   TICK_FLAG_ASK 

1. Что это за загадочные тики с одновременным флагами TICK_FLAG_BUY   и TICK_FLAG_SELL ? Мне удавалась даже находить  такие тики  с объемом в 1 лот. 

2. На тике 988. Ask=133.93  Bid=133.9 Откуда на 989 взялся Last 133.91 ?

3. Что происходило вообще на рынке  ?

Подобные вопросы лучше оформлять в виде отдельной ветки в разделе "Биржевой трейдинг" форума.

Вкратце, если видите, что у тика есть одновременно флаг покупки и флаг продажи - значит сервер брокера не обновлен и он транслирует сделки неизвестного направления.

На каком сервере смотрите тики?
 
Vladimir Karputov:

Пожалуйста или перепишите свой вопрос или расставьте знаки препинания, а ещё лучше добавьте на картинке что, где и кто. Иначе получается, что я вижу знакомые буквы, а понять смысл и Вашу мысль не могу.

Вот картинка


 
Seric29:

Вот картинка


Так, а мою картинку зачем вставили (или это кэш сбрендил?)?

 
Seric29:

Вот картинка


Уточните: Вы хотите прямо в терминале навести мышку и через правый клик мышки скопировать цену ПОЗИЦИИ?

 
Алексей Барбашин:

Далеко пожалуй ходить не будем. Рассмотрим работу с реестром. В реестр можно помещать как строчные величины, так и числовые (не в виде строки). Передачу в реестр числа и получение обратно указателя на него происходит посредством массивов (согласно Вашему исправлению). Такой пример подойдет? 

Держите. Я думаю - разберетесь.
Файлы:
TestReg.mq5  33 kb
 
. ... Rick D. ... .:
Держите. Я думаю - разберетесь.

Оригинально! Я в сторону union даже и не думал. )))

По прошлому примеру пытался разобраться на чем именно происходил креш памяти и терминала.

Для начала отказался от массивов для получения указателей на открытый раздел реестра. То есть просто в API передавал uint& phkResult. Все прошло успешно, никаких ошибок. В документации к mql указано что простые типы могут передаваться по ссылке, что при работе с API является адресом переменной, то есть указателем. В этой части все прошло успешно. Параметры NULL тоже вернул на место и передаю без использования массивов.

Далее, поработал над передачей самого значения в реестр. В описании функции указано что нужно передавать строку с завершающим нулем на конце. А тип string как раз таким и является, поэтому в первой версии я просто передавал переменную. Вы не стали это изменять в предыдущей версии, основываясь на этом же. Но я решил поэкспериментировать с массивами и ввел ushort массив, заполнил его нужным значением. Одним из параметров при передаче в функцию

uint RegSetValueExW(uint hKey, string lpValueName, uint Reserved, uint dwType, ushort &lpData[], uint cbData);

является размер передаваемых данных. В Вашем примере было так:

uint cbData = (StringLen(value)+1)*2; 

Тут все понятно. Мы берем длину строки, добавляем "завершающий" нуль и умножаем на 2 байта, по размеру ushort;

Попробовал так:

   ushort Data[];

   StringToShortArray(value, Data);

uint cbData = sizeof(Data);

Каково же было мое удивление, когда размер данных оказался не равен предыдущему примеру!

Проверил размер массива, он полностью соответствует значению StringLen(value)+1, но вот размер данных не совпал... до сих пор не понимаю почему..

Ну да ладно.

Исходная проблема в итоге заключалась в получении значения из реестра, ведь я в качестве указателя передавал строчную переменную по ссылке. Вот тут и происходил крах.

"если в DLL передается не сама строка а эта структура или ссылка на нее, то ожидать правильного результата нельзя - ведь системная DLL-ка наверняка принимает честную строку с нулевым символом в конце а не эту структуру" - это цитата десятилетней давности, не потеряла своей актуальности.

Поэтому при передаче любого строчного константного значения, например имени раздела реестра или строчного значения параметра все происходит корректно. А при передаче строчной переменной по ссылке, как я это делал, приводит к проблеме, указанной в цитате. )))

А что касается получаемого размера, то в документации к API дается пример, при котором в случае получения ошибки "есть еще данные" увеличиваем в цикле размер приемного буфера и еще раз получаем данные.

Ну как-то так.

Еще раз благодарю за помощь! )))


 
Алексей Барбашин:

Оригинально! Я в сторону union даже и не думал. )))

Union использовать удобно. Не нужно думать - где старший байт, а где младший. Union можно использовать даже для REG_BINARY. Описываете свою структуру данных. И добавляете ее в Union, вместе с массивом байт по размеру структуры. Но мне кажется - вам это не очень нужно. Любые данные можно преобразовать в строку и хранить, как строку.

По прошлому примеру пытался разобраться на чем именно происходил креш памяти и терминала.

Возможно еще и потому, что стек летел, вы long впесто int в описании функции указывали.

В документации к mql указано что простые типы могут передаваться по ссылке, что при работе с API является адресом переменной, то есть указателем.

Можете скинуть ссылку на данный раздел документации?

uint cbData = sizeof(Data);

Нужно uint cbData = ArraySize(Data) * 2, если вы передаете массив ushort.

и uint cbData = ArraySize(Data),  если вы передаете массив uchar.

В последнем примере в качестве параметра API функции я передаю массив uchar, для полной совместимости с виндовым LPBYTE  lpData.

Это правильно. Но это добавило возни для преобразования всех данных в байтовый массив.

А что касается получаемого размера, то в документации к API дается пример, при котором в случае получения ошибки "есть еще данные" увеличиваем в цикле размер приемного буфера и еще раз получаем данные.

Посмотрите в последнем коде. Там в реализации сначала идет запрос на получение размера данных, потом задается размер массива, потом забираются все данные целиком.

 
. ... Rick D. ... .:

Union использовать удобно. Не нужно думать - где старший байт, а где младший. Union можно использовать даже для REG_BINARY. Описываете свою структуру данных. И добавляете ее в Union, вместе с массивом байт по размеру структуры. Но мне кажется - вам это не очень нужно. Любые данные можно преобразовать в строку и хранить, как строку.

Возможно еще и потому, что стек летел, вы long впесто int в описании функции указывали.

Можете скинуть ссылку на данный раздел документации?

Нужно uint cbData = ArraySize(Data) * 2, если вы передаете массив ushort.

и uint cbData = ArraySize(Data),  если вы передаете массив uchar.

В последнем примере в качестве параметра API функции я передаю массив uchar, для полной совместимости с виндовым LPBYTE  lpData.

Это правильно. Но это добавило возни для преобразования всех данных в байтовый массив.

Посмотрите в последнем коде. Там в реализации сначала идет запрос на получение размера данных, потом задается размер массива, потом забираются все данные целиком.

Приветствую еще раз!

Очень надеюсь что наше с Вами разбирательство в данной теме окажется полезным не только новичкам, но и бывалым программистам.

Касаемо лонг. Да это моя ошибка, но изначально тесты были именно с int. Long  я применил по причине того, что использую 64-х разрядный терминал. Но все хорошо работает и с int.

Про указатели. Полагаю что в следующих статьях все хорошо описано: https://www.mql5.com/ru/docs/basis/types/thishttps://www.mql5.com/ru/docs/runtime/imports

С sizeof тоже признаю свою ошибку. Мы используем для обмена динамический массив, а именно для динамических массивов sizeof просто возвращает размер самого массива, а не размер данных: https://www.mql5.com/ru/docs/basis/operations/other

По поводу получения полного объема данных. Да, Ваша правда. Действительно при первом обращении функция возвращает размер размещенных в параметре данных, так что можно обойтись без цикла, о котором я написал. Тут видимо я не верно понял описание функции, так как там говорится о том, что в переменную возвращается размер считанных данных.

Вернемся к string... В принципе, как оказалось, можно было при получении данных передать переменную по ссылке, но предварительно ее проинициализировать каким-либо значением до максимальной длины. Как по мне, так это костыль, ведь потом из данной строки нужно вырезать само значение. Получение данных в буфере массива является более оптимальным вариантом, то есть наше с Вами решение на мой взгляд лучшее ))). 

Тут про передачу string в качестве указателя: https://www.mql5.com/ru/forum/103532/page2#comment_2983919

Ну и про работу с dll Андрей хорошо рассказывает: https://www.mql5.com/ru/articles/96


Считаю что с Вашей помощью удалось полностью раскрыть тему не только по работе с реестром, но и с нюансами работы с библиотечными API.

Класс работы с реестром очень удобен для обмена данными как между инструментами на одном графике, так и между графиками и вообще терминалами.

Как-то на форуме высказали что якобы использование реестра для этих целей равносильно забиванию гвоздей лампочкой и предлагают использование виртуальных файлов (mapping). Но я с этим не согласен, ведь реестр, до записи на диск, как раз и является виртуальным файлом. А при использовании атрибута REG_OPTION_VOLATILE значение всегда будет виртуальным. Да и хранить межсеансовые данные в реестре очень даже удобно. ИМХО.

Документация по MQL5: Основы языка / Типы данных / Ссылки. Модификатор & и ключевое слово this
Документация по MQL5: Основы языка / Типы данных / Ссылки. Модификатор & и ключевое слово this
  • www.mql5.com
В MQL5 параметры простых типов можно передавать как по значению, так и по ссылке, в то время как параметры сложных типов всегда передаются по ссылке. Для указания компилятору на необходимость передачи параметра по ссылке, перед именем параметра ставится знак амперсанда Передача параметра по ссылке означает передачу адреса переменной, поэтому...
Причина обращения: