Вопросы от начинающих MQL5 MT5 MetaTrader 5 - страница 856
Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Хм... вероятно я не совсем внимательно смотрел API, но не заметил такой функции.... А было бы скорее всего удобно.
Может еще подскажете... возможно вопрос слишком .. нелепый... Как число, например double, перевести в массив char? То есть в некоторых API требуется передавать числа в виде указателя. Указатели передаются в виде одномерных массивов... Со строками понятно, для них предусмотрены функции StringToShortArray и StringToCharArray, а вот с числами я пока не понял как их переводить в байтовые массивы (char).
Может какой-то пример?
Далеко пожалуй ходить не будем. Рассмотрим работу с реестром. В реестр можно помещать как строчные величины, так и числовые (не в виде строки). Передачу в реестр числа и получение обратно указателя на него происходит посредством массивов (согласно Вашему исправлению). Такой пример подойдет?
Изучаю историю тиков. Не всегда получается понять, что происходило на рынке в момент появления тиков.
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. Что происходило вообще на рынке ?
Подобные вопросы лучше оформлять в виде отдельной ветки в разделе "Биржевой трейдинг" форума.
Вкратце, если видите, что у тика есть одновременно флаг покупки и флаг продажи - значит сервер брокера не обновлен и он транслирует сделки неизвестного направления.
На каком сервере смотрите тики?Пожалуйста или перепишите свой вопрос или расставьте знаки препинания, а ещё лучше добавьте на картинке что, где и кто. Иначе получается, что я вижу знакомые буквы, а понять смысл и Вашу мысль не могу.
Вот картинка
Вот картинка
Так, а мою картинку зачем вставили (или это кэш сбрендил?)?
Вот картинка
Уточните: Вы хотите прямо в терминале навести мышку и через правый клик мышки скопировать цену ПОЗИЦИИ?
Далеко пожалуй ходить не будем. Рассмотрим работу с реестром. В реестр можно помещать как строчные величины, так и числовые (не в виде строки). Передачу в реестр числа и получение обратно указателя на него происходит посредством массивов (согласно Вашему исправлению). Такой пример подойдет?
Держите. Я думаю - разберетесь.
Оригинально! Я в сторону 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 в описании функции указывали.
Можете скинуть ссылку на данный раздел документации?
Нужно uint cbData = ArraySize(Data) * 2, если вы передаете массив ushort.
и uint cbData = ArraySize(Data), если вы передаете массив uchar.
В последнем примере в качестве параметра API функции я передаю массив uchar, для полной совместимости с виндовым LPBYTE lpData.Это правильно. Но это добавило возни для преобразования всех данных в байтовый массив.
Посмотрите в последнем коде. Там в реализации сначала идет запрос на получение размера данных, потом задается размер массива, потом забираются все данные целиком.
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/this, https://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 значение всегда будет виртуальным. Да и хранить межсеансовые данные в реестре очень даже удобно. ИМХО.