Для получения стакана в QLua(Lua) служит функция обратного вызова OnQuote(). Эта функция вызывается терминалом QUIK при получении изменения стакана котировок. Для получения данных самого стакана служит функция getQuoteLevel2().
В терминале должен быть открыт стакан по нужному инструменту!!!
Пример:
--- Функция вызывается терминалом QUIK при получении изменения стакана котировок function OnQuote(class, sec ) -- if class == "SPBFUT" and sec == "RIM5" then ql2 = getQuoteLevel2(class, sec); -- Представляет снимок СТАКАНА в виде СТРОКИ QuoteStr = ""; for i = tonumber(ql2.bid_count), 1, -1 do if ql2.bid[i].quantity ~= nil then -- На некоторых ценах могут отсутствовать заявки QuoteStr = QuoteStr..tostring(tonumber(ql2.bid[i].quantity))..";"..tostring(tonumber(ql2.bid[i].price))..";"; else QuoteStr = QuoteStr.."0;"..tostring(tonumber(ql2.bid[i].price))..";"; end; end; for i = 1, tonumber(ql2.offer_count), 1 do if ql2.offer[i].quantity ~= nil then -- На некоторых ценах могут отсутствовать заявки if i < tonumber(ql2.offer_count) then QuoteStr = QuoteStr..tostring(tonumber(ql2.offer[i].quantity))..";"..tostring(tonumber(ql2.offer[i].price))..";"; else QuoteStr = QuoteStr..tostring(tonumber(ql2.offer[i].quantity))..";"..tostring(tonumber(ql2.offer[i].price)); end; else if i < tonumber(ql2.offer_count) then QuoteStr = QuoteStr.."0;"..tostring(tonumber(ql2.offer[i].price))..";"; else QuoteStr = QuoteStr.."0;"..tostring(tonumber(ql2.offer[i].price)); end; end; end; end; end; -- В результате при каждом обновлении стакана по инструменту RTS-6.15 в переменной QuoteStr будет строка, типа: -- "15;86130;17;86120;16;86110;22;86100;16;86090;24;86080;26;86070;29;86060;97;86050;51;86040;99;86030;88;86020;143;86010;140;86000;15;85990;49;85980;58;85970;28;85960;49;85950;36;85940;71;85930;115;85920;95;85910;25;85900;5;85890;13;85880;62;85870;3;85860;36;85850;26;85840;11;85830;9;85820;99;85810;86;85800;41;85790;24;85780;2;85770;36;85760;162;85750;22;85740;44;85730;76;85720;229;85710;121;85700;5;85690;5;85680;2;85670;10;85660;148;85650;119;85640;12;86150;19;86160;26;86170;32;86180;71;86190;49;86200;26;86210;20;86220;91;86230;57;86240;47;86250;25;86260;34;86270;41;86280;21;86290;66;86300;36;86310;57;86320;50;86330;34;86340;38;86350;22;86360;17;86370;15;86380;18;86390;13;86400;3;86410;34;86420;29;86430;80;86440;26;86450;68;86460;226;86470;371;86480;30;86490;64;86500;99;86510;11;86520;2;86530;23;86540;9;86550;3;86560;52;86570;23;86580;25;86590;73;86600;17;86610;88;86620;52;86630;150;86640" -- Такую строку удобно, в последствии, передавать в C# и разделять на элементы -- Функция getQuoteLevel2() принимает 2 параметра: Код класса и Код бумаги, а возвращает таблицу, которая имеет следующие поля: bid_count -- Количество котировок покупки (STRING) offer_count -- Количество котировок продажи (STRING) bid -- Котировки спроса (покупки) (TABLE) offer -- Котировки предложений (продажи) (TABLE) -- Таблицы «bid» и «offer» имеют следующую структуру: price -- Цена покупки / продажи (STRING) quantity -- Количество в лотах (STRING) |
Если у Вас появились какие-то вопросы, задайте их в комментариях под статьей !!!
Подскажите, пожалуйста, а можно ли экспортировать параметры стакана, в частности, например, настроить графическое отображение и экспорт статистики спреда bid-offer, который отображается в шапке стакана цен?
Изображение:

По DDE можно скинуть стакан, например в эксель, а статистики никакой не существует, нужно писать программу и копить ее самому
На данный момент получилось так:

Изображение:
Как видно, внутри дня считается, сохраняется (подкачивается) и история изменения. Осталось построить спред между двумя показателями. Как это можно сделать?
У вас получилась, извиняюсь за выражение - хрень.
Не известно какие срезы цен бид и аск внутри минуток.
Т.е. ничего не видно.
Ни один брокер, ни тем паче биржа, историю стаканов не хранит, и тем более не транслирует.
Нижние кривые это случайные величины, взятые терминалом, на основании цен текущего таймфрейма графика.
Так что ручками пишем робота, который будет хранить историю спредов.
Ни для кого не секрет, что сия информация вам ничего не даст, абсолютно.
Зря потратите время.
Могу скинуть тиковый график - он тоже строится.
Цель данного показателя - не торговая стратегия, а анализ рисков.
Бесспорно строится, на основании тиков будет точнее, но скорее всего терминал задохнется, если длинна тикового ряда будет более 500 тиков, т.е. в моменты повышенной волатильности минуты две.
Стратегия это управление рисками, а все остальные "стратегии" лишь сценарии с паттернами, то бишь с сигналами.
Моя задача - обеспечить выполнение требования осуществления мониторинга объемов торгов и статистики bid-offer по инструментам, а с какой периодичностью и что с этими данными будет дальше - это второй вопрос. Приведенный выше график цен спроса и предложения может отображаться и в свечном виде, показывая максимальные значения хоть на минутках, хоть на часах или днях.
В принципе, в квике это выполняется (показатели объема есть, спред в стакане тоже отображается), но хотелось бы немного углубить задачу, имея возможность обрабатывать эти данные и анализировать статистику.
Буду благодарен, если подскажите как вывести эти данные во внешнюю среду.
Подытожим.
То, что вы видите графически в квике и то, что на самом деле происходит в момент времени - две разные вещи.
Данные по стакану приходят снепшотами по порядку, но никому не известен интервал снепшотов.
Это значит, что вы в стакане будете видеть ВСЕГДА! спред в 0,01%, а на деле между снепшотами были спреды 1-50+++%. Которые очень сильно испортят вам картинку статистики и не дай бог счета.
И что вы понимаете под "внешней средой"? Уборная в огороде тоже в какой-то мере внешняя среда.
Напишите макрос в эксель, который будет реагировать на изменения ячеек бид/аск в стакане, подсчитывать спред и выводить его на отдельный лист и сохранять в файл. И стройте себе графики, и анализируйте что вам нужно.
Как вывести стакан по ДДЕ есть в файле-справке квика.
Здравствуйте. А разве функция OnQuote() не должна получать ВСЕ изменения во ВСЕХ стаканах терминала? Или я что-то не так понимаю?
Дело в том, что внутри функции отслеживаю изменения стаканов срочного рынка(стоит условие по классу). Так кроме фьючерса на индекс РТС ничего не приходит. Я уже ввел условие, чтоб выводился в message тикер бумаги(sec из примера кода) только тогда, когда он не равен "RIZ0", но ни одного сообщения так и не получил.
У меня есть подозрение, что это что-то вроде "rate condition". Только здесь информация об изменениях в других стаканах не успевает вклиниться между очень частыми изменениями по "RIZ0". Только непонятно почему изменения не становятся в очередь на отправку в функцию OnQuote(), а всегда пропускают "RIZ0" вперед.
Понял в чем проблема - "В терминале должен быть открыт стакан по нужному инструменту!!!".
Здравствуйте, подозреваю, что у вас открыт один стакан, если это так, то откройте нужные стаканы
или можете в скрипте заказать события по другим инструментам функцией:
Subscribe_Level_II_Quotes(class_code, sec_code), посмотрите в QLUA.chm.
Либо у вас очень много кода в OnQuote.
События не накапливаются, если OnQuote занят расчетами, то новые события отбрасываются.
Но это мало вероятно, что каждое новое событие, которое попадает в функцию - строго РТС, а остальные были отброшены (вероятность есть, но маленькая).
Добрый день. Подскажите как из стакана вытащить доходность котировки (по облигациям)? Или это невозможно в принципе?
Здравствуйте, из стакана можно только информацию о заявках, которые в нем стоят, вытаскивать.
Каждая заявка(по облигации) в стакане имеет доходность, можно её достать?
Нет, это поле нам не доступно в Lua
Дмитрий (Admin), приветствую! Не могли бы Вы не немного пояснить про взаимодействие Subscribe_Level_II_Quotes с Функциями OnQuote() и getQuoteLevel2()?
Допустим я заказываю в OnInit() несколько стаканов функцией Subscribe_Level_II_Quotes (и проверяю заказались ли они). В функции OnStop() отписываюсь от них соотвественно.
Но мне совершенно не нужно получить данные с OnQuote(), там же их куча целая будет каждую секунду... Мне надо периодически (допустим раз в минуту) снимать состояние ранее заказанных стаканов. Если вообще не добавлять в скрипт OnQuote() стаканы же меняться не будут и без этого getQuoteLevel2() ничего нового не посчитает или работать не будет?
Чтобы ресурсы ПК не отжирать как сделать так, чтобы стаканы смотреть/сохранять допустим раз в минуту? Отписываться и снова подписываться на них раз в минуту?
Я видимо что-то недопонимаю...
Здравствуйте, getQuoteLevel2() будет возвращать текущее состояние стакана независимо от того есть в скрипте OnQuote(), или нет
Как-то не заметил, вот такой пример, Дмитрий - будет создавать задержки получения данных терминалом.
При повышенной волатильности, это может быть заметно визуально.
Особенно не стоит делать какие-то серьезные вычисления в функциях обратного вызова: OnAllTrade, OnParam, OnQuote.
Да и в остальных тоже.
По аналогии обрабатываются остальные функции обратного вызова.
Да, я всегда так делаю, все в массив, а с ним уже в main
kalikazandr, здравствуйте! А как быть в таком варианте исполнения, когда необходимо отслеживать сразу два актива?
Здравствуйте.
Я не автор данного кода, но предложу свои идеи.
Вариант первый, раз в функции OnQuote разделяете на 2 таблицы, тогда в функции main() обрабатывайте 2 таблицы, сначала 1, потом вторую.
У Вас первая уже обрабатывается
while #QuoteTable1 .....
Добавьте обработку второй таблицы ниже
while #QuoteTable2 ....
Хотя я бы вообще не разделял на 2 отдельных таблицы, а все данные отправлял в одну таблицу, а потом в main уже обрабатывал одну таблицу, где разделял бы по бумагам.
Для этого надо переделать функцию OnQuote
Ну и соответственно обрабатываю только таблицу QuoteTable1 в main
Данный вариант возможно не будет работать быстрее, или расходовать меньше памяти. Можете протестировать оба варианта и остановиться на том, который покажет лучшие результаты.
Спасибо за варианты. Думал о подобии второго варианта. Но решил спросить, может есть более оптимальный вариант без потерь)))
Здравствуйте, со стаканом немного не так. Если код не большой, то обработать событие можно сразу в OnOnQuote.
Или так:
local QuoteTable = {}
function OnQuote(class_code, sec_code )
if class_code == "SPBFUT" and sec_code == "SRU9" then
table.sinsert(QuoteTable, {getQuoteLevel2(class_code, sec_code), class_code, sec_code})
end
if class_code == "SPBFUT" and sec_code == "SRZ9" then
table.sinsert(QuoteTable, {getQuoteLevel2(class_code, sec_code), class_code, sec_code})
end
end
function OnQuoteDo(tab )
local ql2 = tab[1]
local class_code, sec_code = tab[2], tab[3]
-- тут обрабатываем стакан ql2
end
local is_run = true
function main()
while is_run do
while #QuoteTable > 0 and is_run do
OnQuoteDo(table.sremove(QuoteTable, 1))
-- вот тут никаких sleep - ов не нужно, обрабатываем, максимально используя проц.
end
sleep(1)
end
end
function OnStop()
is_run = false
return 1000
end
Даже не подумал, что можно сделать так изящно и без создания лишних переменных для передачи из OnQuote!))) Спасибо большое!!!)))
Не за что)
kalikazandr правильно говорит - "обработать событие можно сразу в OnQuote" и не нужно отправлять данные в таблицу QuoteTable.
Если у Вас код обрабатывает данные за 0.005 сек не вижу необходимости выносить обработку в отдельный поток, обрабатывайте в потоке в котором Квик работает, то есть в самой функции OnQuote() и не тратьте ресурсы на запись данных в таблицу QuoteTable, ну подвесите Квик на 0.003 сек и что от этого изменится.
Другое дело, если у Вас происходят серьезные вычисления над данными из стакана и при 100 % нагрузки на процесор, вычисления занимают 3 сек, в этом случае Квик действительно повесится, если будете обрабатывать данные в OnQuote, необходимо отправлять вычисления в отдельный поток, через таблицу, как в коде, и тут в любом случае Вам придется создавать эти "лишние переменные" class и sec чтобы потом разобраться к какой бумаге относятся данные. Не задумывайтесь об этом, создать переменную и внеси в нее значение, это единицы микросекунд.
Но отдельный поток не решает проблему отставания данных, он лишь только разгружает Квик, что бы он не вешался, но данные из стакана все равно будут с задержкой обработаны.
Пример такой:
На обработку данных из стакана нужно 3 секунды. Стакан за 1 секунду изменился 7 раз, это значит что данные нужно обработать 7 раз, по 3 сек, итого нужно затратить 21 сек и это время ни как не уменьшить. Если будете обрабатывать в функции OnQuote, повестите Квик на 21 секунду, если в отдельном потоке, тогда повестите поток на 21 сек. Конечно реализация в OnQuote "запрещена", Квик не отвиснет никогда, потому что пока он будет обрабатывать данные, за эти 21 сек придет еще 49 изменений стакана и он зависнет еще на 3*49=147 сек ну и так далее... В отдельном же потоке данные тоже будут появляться уже с опозданием, то есть алгоритм будет вычислять данные из стакана, который был 147 сек назад, а не реальный стакан. Тогда уже надо на несколько потоков разбивать вычисления, но не думаю что оно Вам надо ....
Вообще выполняйте вычисления прям в OnQuote, как и советует kalikazandr, думаю хватит ресурсов процессора с головой.
Не совсем так. Если функция OnQuote занята расчетом, то новый снепшот будет удален, события изменения стакана будут потеряны.
И вообще расчеты стакана в квик это абсурдная затея. Это не ордербука фастовая, где видно - кто где насра...-выставил свою заявку на всем торговом диапазоне от pricemin до pricemax.
Это снепшоты, которые не показывают всех изменений априори.
По этому - пришел сигнал, допустим, с индикатора- взял стакан посмотрел - нормально! - заявка ушла или не ушла.
К ордербуке и хочу прийти в перспективе. Один или с командой собранной))) Просто нужно оценить стоит ли овчинка выделки)
На счет пропуска снимков, не подумал, действительно никаких снимков не будет, пока функция занята, но с другой стороны в другом потоке эти снимки копиться будут, если проц не будет успевать их обрабатывать...
Ну да, в Квике стакан обрабатывать так себе затея...
А вот OrderBook уже другое дело, но как то думаю дороговато для новичков.
kalikazandr : " У меня бот работает на с++ " - Если не секрет то откуда OrderBook данные получает? И во сколько обходится? Давненько этой темой интересовался, но потом оставил, вроде как около 200 000 руб в год стоило данные получить если ничего не путаю.
Нигде ничего не копится, даже OnOrder не придет, если в нем большой расчет - просто будет изменение внесено в таблицу заявок.
Да, дороговато для не больших счетов, ко-локация + фикс_логин ~16 тыс. на так себе железе, и коннектор использую FIX Antenna C++, лицуха 5$тыс/год.
И никто не берется сделать аналог, как ни плачевно.
А вот данные получить как раз-таки бесплатно, если есть свой коннектор. Я за 5 лет не нашел умельца, кто-бы сделал.
- "Нигде ничего не копится ..."
Я имел ввиду копятся в отдельном потоке. То есть в функции OnOrder снимки отправляем в таблицу, а эту таблицу обрабатываем в main, то есть в другом потоке.
В таком случае получается что если процессор будет успевать обрабатывать 10 снимков за 1 сек, а поступать будет 15 снимков в сек, в итоге таблица будет расти, снимки накапливаться. Или я чего то не понимаю...
Имел ввиду "в функции OnQuote снимки отправляем в таблицу", а не OnOrder .
Жалко нельзя просто сообщение отредактировать.
Если комп слабоват, а расчетов много, то да, таблица будет расти и цикл while #QuoteTable > 0 and is_run do станет бесконечным
В том то и дело, что пока не реализую свой алгоритм полностью в коде, не смогу оценить скорости обработки всех событий. Еще хочу реализовать блок самооптимизации одного-двух параметров. А уже дальше увижу и оценю, стоит ли делать из робота "типа HFT" и апгрейд оборудования и прочей инфраструктуры, либо просто не зависящего от скоростей внутри дневного "торговца". ))
Оно того стоит, если алгоритм генерирует прибыль, достаточную, на отбой затрат на инфраструктуру + чу-чуть себе).
У меня бот работает на с++ под линукс, пока первый в рунете по скорости и стабилен, в отличии от любых lua решений под квик или аля-квик.
Хотя в квике этот алгоритм тоже зарабатывает уже 7 лет, но не везде успевает.
Тем более есть к чему стремиться.
В моем случае скрипт линкует фейковый стакан по несуществующему инструменту RIM88.
Проверка ==nil ничего не дает, параметры tb.bid_count, tb.offer_count имеют значение 0.
Вот результат работы:
[8224] -----
[8224] Main
[8224] -----
[8224] Stakan SPBFUT RIM88
[8224] table: 38EE3DC8
[8224] 22:18:42
[8224] Bid: 0 Offer: 0
Хотел сделать проверку на открытие всех необходимых таблиц до запуска основной логики, но вот так не выходит.
Что посоветуете?
Из файла справки qlua.chm:
TABLE getQuoteLevel2 (STRING class_code, STRING sec_code)
Функция возвращает таблицу Lua с параметрами:
При отсутствии и спроса и предложения функция возвращает таблицу без параметров bid и offer.
Да getQuoteLevel2 в принципе не должна возвращать никакой таблице в этом случае, т. к. параметром передан несуществующий фьючерс RIM88, это в идеале.
Если позволите поясню задачу. Есть список опционов - несколько десятков, а может и больше, который ежемесячно составляется вручную. При такой правке очень вероятны ошибки в названиях опционов - человеческий фактор. И я хотел сделать логическую проверку этих имен опционов и открытие (или хотя бы проверку открытия) соответствующих стаканов. Чем больше проверок до начала торговли, тем меньше сюрпризов во время торговли.
Как мне убедиться что полученное из файла название опциона - действительное, ему соответствует стакан реальных котировок, этот стакан открыт, а если нет, то открыть его, если это возможно из скрипта, или хотя бы выдать сообщение и прервать скрипт.
Думаю, как раз, проверить на ошибку можно проверкой наличия полей bid и offer возвращаемой таблицы, а проверка наличия открытых стаканов, как и их программное открытие, невозможны стандартными средствами QLua, если только WinAPI использовать.
Привет! А зачем же тогда пример неправильный?
За тобой Дмитрий - глаз, да глаз))
Так и норовишь испытание устроить для читателей)
Дак это же просто схема как до данных стакана добраться, а вообще, чем больше я создам читателям испытаний, тем умнее они станут, т.к. думать привыкнут в нужном ключе 🙂
Отнюдь. Если бы церковники не жгли книги, мы бы не пошли по технократическому пути.
А неведение завело нас в тупик. Придумали бога и от его имени поубивали миллионы... Ушатали планету и т.п.
Вот последствие "придумок"
А я считаю, что если бы тот путь был действительно верный, то никакие церковники не смогли бы помешать идти по нему, думаю мы еще не нашли нужного пути и технократия, возможно, является необходимым этапом на нашем пути развития, но только этапом, за который мы должны понять что-то важное, без чего не сможем двигаться в развитии дальше 🙂 А по поводу кода, считаю главной задачей учителя - прививать желание думать, а не убивать на корню у ищущих, творческих личностей их стремления, давая им готовые решения и делая из них обычных иждивенцев, вот как-то так 🙂
Интересное заключение.
Т.е. ты утверждаешь,
что в школе учителя должны дать ученикам Букварь и сказать - вот малыши - буквы, учите буквы, слова и т.д., или идите работать ковырялами.
Ну и для пущей убедительности, объяснить - кто такие ковырялы (собственно примерно так наше образование и построено).
Типа "государству" выгодно растить ковырял - нахера умные? - умные думают и не хотят работать на реально - чертей,
которых расплодил наш бессрочный президент. Все счастливы, по телику, только в миру - нет.
Вякать против него никто не сможет - дурни в кучу не могут собраться, разве что Халява какая позовет.
Ну есть конечно вероятность, что кто-то из малышей станет умным при такой системе образования, только шанс 1:150 000 000 примерно. Зато у власть имущих все в ажуре - ебл-лицо все шире.
Не прав ты Дмитрий.
Ну вот и до политики добрались 🙂 Политика и религия запрещенные темы в общественных местах, так что не буду об этом. А вот в чем я не прав я так и не понял, надеюсь, что ты согласен с тем, что человека нужно учить думать, если хотим чтобы он стал умным и самостоятельным. Что тогда по твоему мнению нужно делать, чтобы человека заставить думать ? В моем понимании, человека нужно ставить перед проблемой, готового решения которой у него нет, но решить которую ему необходимо, только так у него появится необходимость думать, иначе он все время только и будет искать готовые решения, станет иждивенцем и столкнувшись с какой-то нестандартной задачей не сможет ее решить без посторонней помощи, т.к. не научился решать задачи самостоятельно. В чем я здесь не прав?
Интересно девки пляшут,
возьми пахаря 40-ка летнего и скажи ему - вот ядерная электростанция - в ней происходит термоядерная реакция, но она достаточно не стабильна и может рвануть и накроется твое поле радиоактивными осадками и все погибнет.
Т.к. ты пахарь, лицо заинтересованное, то давай - придумай, как сделать термоядерный процесс контролируемым на 100%.
Что из этого получится? Правильно - ничего. Пахарь этот помрет и его правнуки тоже и так и не придумают - как термоядерный процесс сделать контролируемым.
Я считаю, если человек спрашивает, значит ему нужно.
И нужно ценить время этого человека. Конечно это прикольно, когда вбил в проблему пару месяцев и решил - герой,
только нафига изобретать велосипед?
А насчет школы - и обучения в целом частично - да. Но 1 башка хорошо, а 2 лучше и т.д. Тут один в поле не воин и от одного человека ничего не зависит вообще. Циалковский придумал ракету, однако он на ней никуда не полетел. На счет Джастас Уолкер - ну ему то делать совсем нечего он сидит себе дома, не обремененный заработком и сидит воспитывает детей - да он черт. 99% Россиян впахивают с утра до ночи на 3-х работах, что бы оплатить образование - что бы дети чувствовали себя лучше, а образования дети не получают, т.к. нет педагогов, как и врачей - одни фармацевты да барыги.
У Джастаса, кстати, ферма на 100 гектар семейная в Алтайском крае, он точно не бездельник. Знаешь как появлялся данный сайт и данная статья, в частности ? 🙂 Нужно мне как-то в начале моего изучения QLua получить данные из стакана, копался, ковырялся, получилось, чтобы снова потом не копаться, сохранил этот код с пояснениями в виде простенькой статьи, если у меня появляется необходимость перебрать стакан когда-то, я знаю, что у меня есть этот пример, в котором хорошо видна структура стакана, я его смотрю, если нужно, вспоминаю и использую частично в своем коде. Так и все остальные статьи появились и используются мной на данном сайте, как кусочки пазла, из которых можно собрать то, что нужно. Это не готовая программа ВУЗа, это просто мой блокнот, в котором я сохранил все необходимое, но потом, почему-то, его стали просматривать и другие, говорить что им с этим блокнотом тоже жить стало легче, я рад этому, по этому не понимаю что ты пытаешься мне сказать, или в чем упрекнуть 🙂
Пусть каждый останется при своем мнении на счет того как должно происходить обучение и почему в России оно за деньги.
А Джастас Уолкер вообще с какого перепуга заимел 100 га? По логике вещей, он лимита, не имеет никаких прав в нашей стране и должен был работать на стройке, рядом с таджиками и узбеками или янки чем то лучше?
Ах да - баксы же у янок. Трудился он там - звукозапись, пилорама. Родители миссионеры - свои нахер посылали - к нам приехали отбирать у народа гроши последние.
Что то узбеки к нам приезжали и никто не смог занялся фермерством или собственным производством, их вообще за людей то не считали, а гноили на стройках да помойках.
Так что не все так хорошо с этим Джастас, как выяснилось.
А насчет трейдинга и то что он не делает мир лучше, не правда твоя.
Мне в радость честно отобрать ворованные деньги и поделиться с государством, игрушек в садик купить и т.д и т.п.
Я согласен, что у нас в России многое не так, но я считаю самым эффективным способом что-то менять, это только на своем примере показывать как нужно жить, по этому стараюсь никого не винить, а сам становиться лучше и правильнее, трейдинг и программирование роботов для меня, кстати, давно ушли на десятый план, т.к. это не делает мир вокруг лучше, ничего в него не привносит, по этому, вообще этим не занимаюсь уже давно, иногда только индивидуально учу людей как скрипт запрограммить какой-нить и все.
По поводу букваря, считаю, что в школе должны не информацию стандартную в голову запихивать детям, а прививать тягу к познанию, желание и умение думать, самостоятельно решать задачи. Об этом хорошо рассказывает один, на мой взгляд, интересный ютуб блогер Джастас Уолкер, у него целый плейлист есть про семейное образование, там, на мой взгляд, все разумно объясняется, так что не буду его пересказывать, если интересна эта проблема, рекомендую посмотреть и взять на вооружение.
Здравствуйте, у меня вопрос-должен ли стакан быть открыт чтобы луа мог прочитать стакан?
У меня почемуто при закрытом стакане не работает.
Здравствуйте! Либо стакан должен быть открыт, либо его нужно заказывать при помощи функции Subscribe_Level_II_Quotes, ее описание есть в файле справки QLUA.chm
Огромное спасибо за столь оперативный ответ!!!
Всегда пожалуйста!
А еще вопрос, немного глупый, если я заказываю стакан в цикле каждый раз перед его чтением ничего плохого не может произойти?
Его только 1 раз нужно заказывать, но ничего страшного, думаю, не случится.
Еще раз спасибо! Думаю организовать маленький проверочный цикл-мол если стакан он прочитать не может то заказываем и снова по кругу пока не прочитает.
Пожалуйста
Привет. Сделал проверку на nil таким образом, результат - все равно вырубается робот
Привет, если робот из-за nil вырубается, то он ведь должен ошибку показать, есть такое?
да, в 3 стр. пишет ошибка, это возникает после клиринга вечернего - точно - дневной не помню и сегодня с утра терминал запустил как обычно (робот был включен), после обновления данных - отключился
А какую именно ошибку пишет? Ты проверяешь C_Glass.bid[tonumber(C_Glass.bid_count)-1].price на nil, а nil может быть раньше:
C_Glass.bid_count == nil
C_Glass.bid == nil
C_Glass.bid[tonumber(C_Glass.bid_count)-1] == nil
а понял, значит надо все эти строки на нил проверять? я то думал
этого достаточно
Может все и не нужно, надо просто найти где нил пролетает, хотя, можно и не искать, а просто реально на все проверять)
лучше все проверить и все (вспомнил - вчера в стакане после клиринга не было 2й цены - по этому и вырубился)
Согласен
Чё то делал со стаканом год назад, а что делал уже не помню и точно помню его обозвал Glass - поискал не нашел - удалил вероятно - обычно то все сохраняю в папке Примеры - что бы потом с примера уже быстренько вспоминать что к чему и делать - щас вот задача есть стакан смотреть весь - а что к чему все забыл - вот к тебе зашел - и свой же пример увидел - еще раз говорю - ты молодец очень большой - твой ресурс КЛАСС - меня щас люди спрашивают чё да как бы самому научится ботов писать - всех сюда отправляю
Благодарю!
Добрый день!
Не получается считать данные из стакана, код следующий:
Все время идет по варианту ql2 == nil, т.е. выдает сообщение :"Нет покупки в стакане...", стакан открыт и данные в нем меняются. Если убрать сравнение с nil - выскакивает ошибка.
При этом из "Текущей таблицы параметров" все считывается прекрасно - закомментированная часть кода.
Вот так попробуйте:
У Вас здесь, скорее всего, конфликт в названии переменных. В OnParam Вы, кстати, другой инструмент смотрите.
Поменял, теперь выскакивает ошибка: Test3.lua:19: attempt to index field '?' (a nil value).
Этого я совсем не понимаю:(, ведь я ее с nil и сравниваю.
Подскажите, что принципиально меняет символ подчеркивания: "_class" вместо "class"? Я думал, это просто разные названия переменных, но по-видимому я ошибаюсь?
Какой конфликт в названии переменных Вы имеете ввиду? Если: class ="SPBFUT"
sec = "SiH7", то это ничего не меняет, я могу их просто закомментировать.
В OnParam (да и в OnQuote) я смотрел разные инструменты, в том числе и этот, но в 1-м случае читаются все переменные, во вторм ни один:(.
Подчеркивание просто другое имя дает, т.к. у Вас в начале скрипта объявлены переменные с такими же именами, что Вы в функции OnQuote использовали:
строки 3,4
class ="SPBFUT"
sec = "SiH7"
можете вместо символа подчеркивания любую букву использовать, или удалить строки 3,4 просто
По поводу ошибки, то Вы проверяете только ql2 на nil, а он не nil, но, возможно, nil'ом является bid, или bid_count, или price.
Ведь в этой статье есть пример, воспользуйтесь им и подкорректируйте под себя.
Теперь вообще началась мистика!
Вернул все к первозданному виду, но вместо сообщения :"Нет покупки в стакане...", идет ошибка: "Test3.lua:19: attempt to index field '?' (a nil value)."
Как такое возможно??? Квик перегружал - не помогает.
Решил, что где-то ошибся при восстановлении текста - просто скопировал свое первое сообщение отсюда и запустил - снова та же ошибка???
строки 3,4
class ="SPBFUT"
sec = "SiH7"
я просто закомментировал - результат тот-же.
Естественно ql2 не nil, так как стакан полон, и так же естественно, что bid, или bid_count, или price тоже не nil, по той же самой причине. Но почему тогда ошибка: Test3.lua:19: attempt to index field '?' (a nil value).
Если бы они были все не nil, то не было бы ошибки, Вы не гадайте, а выведите каждый из этих параметров в message, только оберните в tostring, потому что иначе nil не выведется. А конфликта переменных значит не было.
разобрался, строка должна выглядеть так:
"gbid = tonumber(ql2.bid[tonumber(ql2.bid_count)].price)"
а то я уже решил, что у меня глюки начались:).
Правда остается непонятным, почему первоначальный код работал по варианту ql2 == nil, ведь стаканы не были пустыми?
И, кстати, вопрос: если первоначально определять переменные class и sec, то function OnQuote(class, sec ) будет срабатывать только в случае указанного стакана или при изменении любого стакана открытого в Квике?
Поздравляю 🙂
При изменении любого.
Здравствуйте!Подскажите,пожалуйста, идентификатор в стакане для параметра Сумма покупки/Сумма продажи.Спасибо.
Здравствуйте! Подскажите что это за параметр такой: Сумма покупки/Сумма продажи ?
То есть Сумма лучших.
по идее, это значение в текущей таблице параметров должно отображаться, но у меня, почему-то, не отображается, значит только в цикле перебирать стакан и считать сумму лотов во всех заявках на покупку, или на продажу
А из стакана почему напрямую нельзя?Нужен объем по стакану(индикатор нарастающего объема).ТТП тут не поможет,она ведь весь стакан не отображает.Получается из стакана только два параметра можно вызвать Цена и Количество?
Уточню,может я плохо сформулировала вопрос,есть два параметра в стакане
price -- Цена покупки / продажи (STRING)
quantity -- Количество в лотах (STRING)
Как называется колонка Сумма лучших(STRING)?Этот параметр отображается в стакане при добавлении Параметра вручную.
такой колонки в QLua нет, ее можно только вычислить самостоятельно
цена и количество, но их можно взять по каждой цене, которая есть в стакане, если посчитать сумму всех количеств в заявках на покупку, находящихся в данный момент в стакане, то получится то, что Вам нужно.
bid и offer это массивы, каждый элемент которых имеет поля price и quantity, вверху же есть пример
Ясно.Спасибо.
Всегда пожалуйста!