-------------------------- Т е декларация разработчиков о том, что QLUA сделано для дилетантов в программировании - это такой шутка --------------------- Примерно так
мда... меня тут только одно интересует. Если я не буду ничего делать с табличкой в коллбеке, но она будет у меня с глобальной видимостью, она будет обновляться, её составляющие можно будет использовать в других коллбеках и в майне? Или мне нужно будет её обязательно скопировать внутри коллбека, чтобы данные остались внутри скрипта?
В Вашем примере Вы ничего не делаете с "fut_pos", а раз ничего не делаете какой к нем смысл. Зачем обновлять таблицу раз Вы с этими обновлениями все равно ничего не делаете. Поэтому в моем примере я убрал ее, тем самым показав что этот параметр не обязателен. Проще говоря, хотите работать с данными которые пришли в колбек, задайте параметр функции, если нет можете не задавать, на ваш вкус.
А если мой пример, и функция main( ), в которой я что-то делаю с fut_pos? Да, в коллбеке пусто, но в майн табличка будет обновляться после коллбека?
Цитата
Да что-то меняется. Флаги описаны в хелпе, глава "Описание битовых флагов"
И что же меняется?
Ясно, что описаны, просто я не совсем понимаю, что делают другие битовые функции, вот и спросил, есть ли способ за одну битовую функцию на этими битами узнать всё и сразу. Ясно, будем тыкать.
Николай Бехтерев написал: т.е. пустой блок функции не пойдёт? Никак нельзя так:Кодfunction OnFuturesClientHolding(fut_pos)
end
Можно, только смысл какой? Можете хоть так написать function OnFuturesClientHolding() message("сработал OnFuturesClientHolding") end
Хорошо, но если в описании функции КоллБека не передать табличку, то она не обновится, верно? Т.е. в моём примере выше, в отличие от вашего табличка с данными обновится, а в вашем нет, по сколько функции не передаётся таблица, верно?
И ещё пару вопросов, у меня вот такого вида код:
Код
function OnOrder(order)
PrintDbgStr(tostring(bit.band(order.flags,4)))
end
У меня выводит две строчки в DebugView как при выставлении, так и при снятии. Т.е. при выставлении заявки КоллБек срабатывает дважды, и дважды при снятии. Что это значит? Что-то меняется? Есть способ выяснить за одну функцию (хелп в этом деле скромный помощник, я чуть ли не методом тыка выведываю всё) сразу все флаги? А то как-то нелепо каждый бит bit.band'ом щупать.
Так, возник вопрос по форме реализации КоллБеков: Допустим есть функция OnFuturesClientHolding(TABLE fut_pos) из описания в хелпе, не совсем понятно, как она (они, коллбеки) работает. То ли мы передаём им табличку, ну т.е. точно передаём и они их заполняют и... нужно что-то ещё? Ведь я правильно понимаю, что fut_pos -- это результат работы коллбека и эта таблица более чем расписанная от и до, почему мы её передаём а не ставим слева от знака равно? Из моих опытов ясно, что табличку достаточно просто обозначить, типа:
Код
fut_pos = { }
какова будет минимально описанная рабочая функция OnFuturesClientHolding обновляющая табличку fut_pos? Мне казалось, что логичная такая конструкция:
Код
fut_pos = OnFuturesClientHolding(
Но в примерах везде другая конструкция. Можно как-то прояснить мне ситуацию с тем, как это работает, чтобы лучше понимать как использовать?
Николай Камынин написал: пардон опечатка Попробую пояснить далее Вот примерный алгоритм Вашего робота: ---------------------------- СОСТОЯНИЯ ( S) 1) свободно 2) торгуем 3) ждем ------------------------- OnQuote S==1 - если нет позы, то покупаем, иначе продаем. Выставляем заявку по лучшей цене , S=3 S==2 - цена в заявке хуже лучшей, снимаем заявку, S=3 ------------------------- OnOrder если заявка активна, то S=2, иначе S=1 ---------------------
Угу, я уже сам понял, что состояния робота фиксируются в глобальных переменных, которые логично менять внутри коллбеков.
Я подведу небольшой итог: 1. КоллБеки поступают последовательно, пока не будет обработан весь коллбек, пусть даже с очень длинным циклом внутри, другой коллбек не поступит в обработку. 2. Майн и КоллБеки работают в скрипте параллельно, при условии многоядерности машины.
Николай Бехтерев написал: sleep( ) прерывается КоллБеками?
Если у вас многоядерный комп, то main и колбэки будут работать параллельно.
Цитата
Николай Бехтерев написал: А что будет если замутить в коллБеке OnQuote( ) цикл while (пока заявка активна) do sendTransaction(убить заявку)
Тут надо включить мозг и подумать над написанным раннее:
Цитата
Старатель написал: вы не получите следующий колбэк, пока не закончите обрабатывать текущий. А чтобы получить новое состояние заявки - снята - терминал должен получить колбэк OnOrder с этим состоянием.
Все колбэки приходят последовательно .
Спасибо! Теперь картинка начинает складываться! А есть возможность убедиться в том, что коллбеки и майн работают параллельно? Просто мало ли... :-Р
А что будет если замутить в коллБеке OnQuote( ) цикл while (пока заявка активна) dosendTransaction(убить заявку) Это не подвесит Quik? Сервер брокера не возмутиться?
Старатель написал: 1. sleep в колбэке с большой долей вероятности приводит к зависанию скрипта и QUIK в целом. Поэтому, использовать sleep в колбэках опасно. 2. Даже если бы это было не так, вы не получите следующий колбэк, пока не закончите обрабатывать текущий. А чтобы получить новое состояние заявки - снята - терминал должен получить колбэк OnOrder с этим состоянием. Поэтому, после подачи транзакции на снятие заявки вам ничего не остаётся, как ждать следующего OnOrder с новыми флагами.
Понятно, никаких sleep( ) кинули sendTransaction и вышли из коллБека, попали в main, где скорее всего sleep( )... вот тут у меня опять вопрос, sleep( ) прерывается КоллБеками? Просто то, что без слипов никак (иначе скрипт не оставить) я уже понял опытным путём. Выше, на мой вопрос, что оставлять в main() если у меня всё может раскидываться по КоллБекам мне порекомендовали цикл со sleep( ), встаёт вопрос о размере переменной для этого sleep( ), если он прерывается коллБеками, то хорошо, можно хоть минуту туда зафигачить, а если нет, то никаких преимуществ в том, чтобы раскидывать всё по КоллБекам я уже и не вижу тогда... Ведь если sleep( ) не прерывается, то он один фиг имеет место быть и робот в этот момент не занят делом и какая тогда разница в КоллБеках у меня логика или из КоллБеков попадает в майн, по-моему никакой.
Николай Камынин написал Не в обиду будет сказано, но Ваш пост свидетельствует о том, что Вы пытаетесь, еще не придуманный свой роман писать сразу на японском, без словаря, спрашивая на форуме, как написать на японском ...то или иное слово и зачем это слово надо писать. ------------------ Примерно так.
Да ладно вам, я же спрашиваю конкретный вопрос про функционал КоллБеков, под конкретную задачу: Выставляем лучшую заявку и обновляем её, пока нашу заявку не сожрут.
Я уже узнал, что всё можно закидать в КоллБеки мне это очень понравилось, этого не было в help'e и я наивно полагал, что коллбеки нужно использовать лишь для получения данных. Я уже смотрю на скрипт qlua другими глазами. Осталось уточнить как работают КоллБеки.
То что робот это состояния, это понятно любому, кто попыхтел над самым маленьким скриптом или программой :)) Но всё равно спасибо за напоминание. Всегда приятно удостовериться, что ты на правильном пути.
Вот я и спрашиваю, после появления состояния "Оффер обновился": -- Нам нужно опять выставиться лучшей заявкой, но для этого нужно снять старую заявку, что мы тут же и делаем при помощи sendTransaction ( ) в КоллБеке OnQuote( ), где мы и узнали про новый "Оффер". У меня появился закономерный вопрос: ставить sleep ( ) ? или довериться новым включениям КоллБеков и новой проверки состояния старой заявки? Что логичнее, или точнее что быстрее сработает?! По сути это вопрос технический, я узнаю как устроен qLua, разве нет?
Николай Бехтерев написал: И такой вопрос, допустим выставление лучшей заявки мы засовываем в коллбек OnOrder, в OnTrade мы получаем информацию о том взята заявка или нет, как исключить момент исполнения двух заявок? Без sleep() и ожидания ответа о том, что заявка снята - тут никак не обойтись, я правильно понимаю?
можно и без speep Например запоминать номер выставленной заявки и перед выставлением новой, проверять исполнилась старая или нет через функцию getOrderByNumber
но ведь всё равно будет какая-то разница во времени между sendTransaction для снятия заявки и коллбеком OnOrder?
Вот вы говорите номер... Ну запомили мы номер первой выставленной нашей заявки, далее, когда в стакане появляется цена лучше нашей, мы проверяем по номеру не снята ли заявка (а может быть и взята рынком), если снята, выставляем новую, а если нет? Если заявка стоит и её надо снять, мы тут же в OnQuote кидаем sendTransaction и? Время же тикает пока заявка будет снята и мы увидим это по флагам. Что в это длящееся время будет происходить в OnQuote?
И такой вопрос, допустим выставление лучшей заявки мы засовываем в коллбек OnOrder, в OnTrade мы получаем информацию о том взята заявка или нет, как исключить момент исполнения двух заявок? Без sleep() и ожидания ответа о том, что заявка снята - тут никак не обойтись, я правильно понимаю?
А ещё у меня ощущение, что без sleep( ) скрипт, даже если засунуть по коллбекам всё, работать не будет. Я прав? Получается в main засовывается sleep всё равно?
Sergey Gorokhov написал: Николай, Никто не говорил что main надо убрать. речь о том чтобы перенести проверку и выставление заявки в колбек OnQuote Без main скрипт отработает один раз и остановится.
какой минимальный набор в main, я чувствую что у меня всё по коллбекам сейчас раскидается. что же оставить в main?
2) При играх в лучшую заявку надо учитывать следующее. На ликвидных бумагах спреда может не буть и ваша заявка будет бить в противоположную лучшую, т е Вы будете двигать рынок. Это обычный прием маркет-майкеров заставить двигать рынок чужими деньгами. Забиваю спред , а подобные Вашему алгоритмы начинают съедать встречные заявки.
Собственно, у меня сейчас простейшая торговая система и если прошла сделка по сигнальному уровню мне было бы логичнее выставляться лучшей и пусть даже лупить по рынку, в любом случае для системы это будет оптимально.
Зачем в main передавать переменную и там ставить заявку когда все можно сделать в OnQuote? Сейчас у Вас как раз код написан не оптимально. Раз есть sleep то значит проверка произойдет с задержкой, а оно Вам не надо Я Вам предлагаю наиболее оптимальный вариант без всяких циклов и sleep. Прислушаться к совету или нет дело Ваше.
Ооо, теперь понимаю. Т.е. по идее вообще никакого main'a может и не быть, вся логика может быть реализована в коллбеках?! Но, я всегда думал, что main нужен в принципе, оттуда скрипт исполняться начинает, а если всё засунем в коллбеки, main можно совсем убрать? Или что туда засунуть то? print("Hello world")?)))) Наличие main обязательно для скрипта?
в main проверяете, если она меньше предыдущей то снимаете старую заявку и ставите новую. Однако, лучше убрать проверку из main и перенести ее целиком в OnQuote, только без sleep
Не понимаю почему проверку в OnQuote если всё равно происходит выставление заявки в main? Т.е. допустим мы в OnQuote будем иметь два ценовых уровня OFFER и LAST_OFFER допустим мы сравнили и выяснили, что наша заявка не лучшая, тогда нам всё равно эту перемену как-то нужно передать в main и получится уже два if-then, а значит большая вычислительная мощность, разве нет?
Sergey Gorokhov написал: К сожалению из описания все еще не до конца понятно что именно требуется реализовать. Вот Вы ставите заявку по лучшим ценам +- шаг цены и...? Опишите что именно требуется
Про выставление с двух сторон пока рано, там посложнее для меня. Для начала простой пример решу.
Фёдор Сухов написал: Поясните точнее, что имеете в виду, когда пишите: "как реализовать выставление лучшим пока не взяли нашу?" Если я правильно понял, то просто прибавьте или отнимите 1 руб. в заявке перед выставлением лимитника.
Ну, выставиться лучшей -- это уже ясно как, учитывая наши с вами конструкции: просто прибавить шаг цены и sendTransaction. Но рынок может не взять лучшую, а двинуться дальше (если, например, инструмент с дальней экспирацией и там очень разряженный стакан с большим количеством желающих стоять первым в очереди). Т.е. должен быть цикл пока коллбэк ОnFuturesClientHolding( ) не вернёт изменение позиции по фьючу. Или как-то ещё?
Здравствуйте, К сожалению из описания все еще не до конца понятно что именно требуется реализовать. Вот Вы ставите заявку по лучшим ценам +- шаг цены и...? Опишите что именно требуется
Хорошо, перефразирую, хотя я уже примерно понимаю конструкцию, но любопытно сравнить свои "карты" с чужими. Полезно иногда бывает ;) Задача: Стоять лучшим OFFER пока заявку не возьмут по рынку, если заявка перестала быть лучшей - снова встать лучшей. Я вижу это примерно так:
Код
function OnQuote(class, sec)
if class == "SPBFUT" and sec == "SiM6" then
stock = getQuoteLevel2(class, sec)
OFFER_PRICE = stock.offer[1].price
BID_PRICE = stock.bid[20].price
end
end
function OnFuturesClientHolding(fut_pos)
if fut_pos.sec_code == "SiM6" then
totalnet = fut_pos.totalnet
end
end
function OnOrder(order)
if order.code == "SiM6" then
--здесь проверка на биты снята ли заявка или нет, пока не очень понимаю как это сделать.
-- вот я пока не сложил в голове общую схему, какие коллбеки и как использовать
end
end
function main()
while is_run == 1 do
while totalnet >= 0 do
if (OFFER_PRICE < LAST_OFFER_PRICE) then
--sendTransactio("ТУТ УБИВАЕМ ПРЕДЫДУЩУЮ ЗАЯВКУ")
-- while не выясним убили мы заявку или нет, не выставляем новую.
--sendTransaction
LAST_OFFER_PRICE = OFFER_PRICE
end
sleep (???)
end
end
end
Примерная конструкция, я её по сути тут, на форуме накропал, так что пробовать её нет смысла, кучу ошибок допустил наверняка.
Фёдор Сухов написал: Поясните точнее, что имеете в виду, когда пишите: "как реализовать выставление лучшим пока не взяли нашу?" Если я правильно понял, то просто прибавьте или отнимите 1 руб. в заявке перед выставлением лимитника.
Ну, выставиться лучшей -- это уже ясно как, учитывая наши с вами конструкции: просто прибавить шаг цены и sendTransaction. Но рынок может не взять лучшую, а двинуться дальше (если, например, инструмент с дальней экспирацией и там очень разряженный стакан с большим количеством желающих стоять первым в очереди). Т.е. должен быть цикл пока коллбэк ОnFuturesClientHolding( ) не вернёт изменение позиции по фьючу. Или как-то ещё?
мне кажется, это вопрос времени-ресурсов (уровня знаний) и требований системы торговли. Если есть знания C# то писать что-то под Quik вообще большого смысла нет. Если сравнивать QPILE с QLUA, то выбор очевиден. На счёт возможностей Qlua, то я видел даже какие-то скальперские варианты.
function OnQuote(class, sec)
if class == "SPBFUT" and sec == "SiM6" then
stock = getQuoteLevel2(class, sec)
OFFER_PRICE = stock.offer[1].price
BID_PRICE = stock.bid[20].price
end
end
В offer_price и bid_price имеем цены для лучшего предложения и спроса соответственно. А вот как реализовать выставление лучшим пока не взяли нашу? Вообще имеет смысл реализовывать такое на луа, не слишком ли это медленно для Луа+Квик?
Это тарифы для брокеров. Про отдельный сервер: к трем оброкерам обращался ( в т.ч. к БКС) - никакого толку. Кто нибудь пользует "прямые соединения", вроде обещаемых БКСом "плазы и тд."?
Возможно, что при использовании прямых подключений минуя Quik надобность в брокере отпадает напрочь. Ведь это уже собственный "терминал" (робот, программа) зачем для этого кому-то платить? Проще купить фирму с лицензией и оформиться как надо, не?
Что-то у меня такой простецкий код не идёт, я даже ошибку не пойму, вроде про синтаксис, но всё же правильно:
Код
Stops = {}
Index = 0
i = 0
function main()
Index = getNumberOf("stop_orders")
while Index >= 0 do
Stops = getItem("stop_orders", Index)
if Stops.sec_code = "SiM6" then
if Stops.withdraw_time == 0 then
KeyOrder = Stops.order_num
i = i+1 --счётчик активных заявок по инструменту
if i >=2 then
message("ERROR,3")
end
end
end
Index=Index-1
end
end
Что-то поиск (по всей сети, не только тут) ничего не дал, а как работает из документации представляется смутно (и почему было сразу не писать пример в документации?). Что за аргумент такой передаётся- form_id ?
Дело в том, что у меня берётся номер стопа, чтобы иметь его возможность снять и как раз в момент снятия в переменную попадает номер уже снятого стопа. Как оформить OnStopOrder( ) в скрипте, чтобы избежать этих накладок? у меня пока такая простецкая конструкция прописана:
Код
function OnStopOrder(stops)
KeyOrder = stops.order_num
end
Попадание старого номера, кстати, странно учитывая такую очерёдность функций:
Код
KillStop (Class, fut, ID+1, KeyOrder) --убиваем стоп (тут KeyOrder дублируется старым значением в OnStopOrder())
StopS (lastPrice-razmerS, ID+1, Class, lots, fut) --после этого новый вызов OnStopOrder() и новое значение у KeyOrder
sleep(500) -- уже и слип пожирнее сделал, но нет нет, да и попадёт в KeyOrder предыдущий номер. Где косяк никак не пойму.
message("trans_stops.order_num of StopS is "..tostring(KeyOrder))
Может сервер убивает иногда дольше, чем выставляет? Я так понимаю, что нужно смотреть stops.withdraw_time?
Ну и маленький вопросец по OnInit( ) Вот так запускаться не захотела функция:
Код
function OnInit("/home/bart/.wine/drive_c/Quik_6.17.3/ROBO2/")
А вот так пошла:
Код
start = "/home/bart/.wine/drive_c/Quik_6.17.3/ROBO2/"
function OnInit(start)
В чём разница и что даёт выставление пути скрипта?
Вячеслав + написал: Да что ж за день сегодня такой...
Код
-- открываете файл
local f = io.open ( "myfile.txt" , "r" ); -- или "rb" если хочется читать в "бинарном" режиме
-- читаете
message (f:read( "*l" ), 1 )
А как в этом же скрипте произвести чтение из него этой же записи в новую переменную? Как я только не крутил io.read, у меня так и не вышло, мануалы вообще в этом деле не помогли.
SDL написал: См. колонку "Код клиента" таблиц портфеля и лимитов (для фондового рынка). А вообще всё очень просто. Возможные значения представлены в списке выбора поля "Код Клиента" окна ввода заявки. Как правило, для фондового рынка это номер соглашения, для срочного - номер торгового счета. UID - это код терминала, т.е. клиента сервера QUIK. К одним торговым счетам могут иметь доступ разные терминалы с разными кодами. И наоборот.
Спасибо за быстрый ответ! А теперь самое смешное, я вообще не смог выставить заявку, даже в ручную, попробовал всё, что предлагал диалог "FORTS:Фьючерсы Ввод заявки" -- результат всё та же ошибка с "неверный код клиента"!! Мде...
Добрый день.
Вы выставляете транзакцию на срочном рынке и в поле кода клиента указываете код? На срочном рынке данное поле должно быть пустое, указывается только торговый счет. Также если в сообщении "неверный код клиента" присутствует номер ошибки, то ее возвращает биржа.
У меня и было пустое, со стороны брокера что-то решили и я смог выставлять заявки.
SDL написал: См. колонку "Код клиента" таблиц портфеля и лимитов (для фондового рынка). А вообще всё очень просто. Возможные значения представлены в списке выбора поля "Код Клиента" окна ввода заявки. Как правило, для фондового рынка это номер соглашения, для срочного - номер торгового счета. UID - это код терминала, т.е. клиента сервера QUIK. К одним торговым счетам могут иметь доступ разные терминалы с разными кодами. И наоборот.
Спасибо за быстрый ответ! А теперь самое смешное, я вообще не смог выставить заявку, даже в ручную, попробовал всё, что предлагал диалог "FORTS:Фьючерсы Ввод заявки" -- результат всё та же ошибка с "неверный код клиента"!! Мде...
У меня в таблице для функции выставления заявок вообще не было параметра CLIENT_CODE потому что даже в демо-режиме всё работало без него (демо Finam, ARQA). А теперь не в демо-режиме (брокер ALOR) терминал ругается: "Неверный код клиента". Попробовал в CLIENT_CODE продублировать значение ACCOUNT, не помогло. Выставил UID который светится в наименовании окна-терминала - глухо. Что же там писать?
Позабавило, что Стопы система принимает, но в момент исполнения вылетает та же ошибка.
Тоже интересует вопрос переноса переменных через сессию (мало ли какой ребут случится, да и просто комп многозадачен) встал вопрос о файле-хранилище, интересует кто как решал эту задачу, может уже есть готовые куски кода? Мне как новичку самостоятельно разработать функции и идею хранения пары int переменных в файле(ах) будет сложна)))
Николай Бехтерев написал: Функция OnTransReply() показывает, что после sendTransaction() в таблице trans_reply значение у order_num равно nill. Это прелести демо-режима? Не хочется искать ошибку там, где её нет))))
Добрый день.
Николай, уточните, а какая именная транзакция Вами подается?
Отправлялся стоп. Но брокер у которого демо уже вроде всё исправил, так что спасибо, всё работает.
Функция OnTransReply() показывает, что после sendTransaction() в таблице trans_reply значение у order_num равно nill. Это прелести демо-режима? Не хочется искать ошибку там, где её нет))))
присоединяюсь к вопросу! За одно вопрос к вам sweg а для Linux есть что-то в виде расширения для Lua, дабы свои окошки рисовать и Linux'овые функции использовать?