Алексей (Все сообщения пользователя)

Выбрать дату в календареВыбрать дату в календаре

Страницы: Пред. 1 2 3 4 След.
Cteatedatasource
 
Цитата
s_mike@rambler.ru написал:
Какое решение?

увидеть, что подключен пока только шлюз акций, а нужно получать фьючерс, которого на акциях нет, но который станет доступным позже и по этому поводу останавливать скрипт?

вы про это решение? Это не решение а ерунда какая-то..
Представьте себе, что у Вас нет никакого скрипта, а Вы работаете вручную на Quik. Подойдя в очередной раз к компьютеру Вы с удивлением обнаруживаете, что подключены к серверу брокера, но все таблицы на экране - пустые. Что Вы будете делать? То же должен сделать и скрипт.
Причем описанная ситуация - не гипотетическая, а вполне реальная, по крайней мере из-за моего "шикарного" брокера: он может дать подключиться к серверу (при этом "случится" OnCleanUp), но трансляцию данных может не начать и через 5, и через 10 минут после этого. Такое, правда, случалось только в неторговое время.
И дело здесь не в неправильной работе клиентского терминала Quik, а в "такой" работе сервера брокера.
Мой скрипт 1 минуту ждет старта потока данных. А затем спрашивает у пользователя, что ему делать: прекратить работу с инструментом (т.к. его, возможно, на самом деле уже нет на бирже, и я просто забыл в настройках скрипта сменить его на более поздний), ждать старта трансляции еще "заданное" время, или сменить сервер. Пока скрипт ждет моей реакции, он продолжает каждые 10 секунд проверять начало трансляции.
Очистка таблиц Quikа по OnCleanUp может вырубить скрипт. Как уберечься?
 
Опять столкнулся с этой ошибкой. Но при этом скрипт благополучно продолжил свою работу!
Судя по логам, вызов колбека (в потоке которого случилась ошибка) произошел после OnInit, но РАНЬШЕ старта потока main.
Исходя из этого прошу подтвердить два вывода:

1. Колбеки начинают вызываться после окончания OnInit, но могут выполняться до старта потока main.
2. Ошибки интерпретатора, возникающие между окончанием OnInit, но до старта main, не вырубают скрипт.
работа с фьючерсами
 
Ваш доход в $ определяется в момент "выхода". Для зачисления на Ваш счет рублевого дохода, используется индикативный курс рубля, установленный биржей для ближайшего следующего основного (вечернего) клиринга.
Пример:
Если вход (длинная позиция, 62,50$) и выход (64,23$) были в пределах одной сессии (нет основного (вечернего) клиринга между сделками), то доход будет 64,23$ - 62,50$ = 1,73$. Шаг цены по нефтяному фьючерсу - 0,01$, т.е. Вы заработали 173 шага цены. Стоимость в рублях шага цены, котируемого в долларах США, по которой будет рассчитываться Ваш итоговый доход, определяется при ближайшем следующем вечернем клиринге (18:45) по индикативному курсу $. Индикативный курс $ - это средний курс на валютной бирже на последней минуте торгов (18:30). Индикативный курс, к примеру, на 12.12.17 18:30 равен 59,1267 руб./$. По итогам клиринга с каждого фьючерсного контракта Ваш счет увеличится на 173 шага цены * 0,01$ стоимость шага цены * 10 лотов в контракте * 59,1267 руб./$ = 1022,89 руб.
Подвешивание info.exe через механизм межпоточного локинга
 
P.P.S. И разумеется скрипт хранит не дубликаты таблиц Quikа, а только те поля, которые могут понадобится при последующих обращениях и собственные поля - результаты текущей обработки.
Подвешивание info.exe через механизм межпоточного локинга
 
Антон, В отношении таблицы всех сделок (Таблицы обезличенных сделок) Вы совершенно правы. хранить целиком всю ее копию быссмысленно.
Я писал про "Конкретно приведенная Вами задача", когда "в мейне запрашивается список сделок или заявок". И показал как я решил эту задачу без "критических секций".
Вы хотите подвесить поток Quik пока main занят своим критическим кодом, не допускающим внесение изменений другими потоками в рабочие таблицы скрипта? По мне, так подвешивание потока Quik совершенно недопустимо ни при каких обстоятельствах.
Однако, если скрипту по поступившему через колбек событию необходимо предельно быстро (менее, чем за 0,01 с) принять решение и выдать транзакцию, то весь код принятия решения придется запихнуть в колбек, и тогда пусть весь остальной мир подождет :).
Мое решение позволяет потоку main быть уверенным, что он, в критические моменты, анализирует статический слепок таблицы Quikа, не опасаясь того, что в реальную таблицу Quikа, во это время параллельные потоки могут вносить изменения. Причем этот слепок хранится в виде индексированной по необходимым полям lua-таблицы, поэтому, чтобы найти в ней нужную строку, не нужно перебирать всю таблицу.

Что касается Таблицы обезличенных сделок, то в этой таблице никакая из уже имеющихся строк поменяться не может, в нее могут только добавляться новые строки. Что здесь нужно синхронизировать?
В момент старта "критического" анализа выяснили сколько строк в таблице и занимайтесь ими, игнорируя новые. Хотя я не представляю себе торговой стратегии, при которой необходимо каждый раз заново анализировать Таблицу обезличенных сделок за некоторый исторический период (кроме как один раз на старте скрипта). Поступила новая строка - получили 3 колбека: собственно OnAllTrade (все инструменты в куче), OnParam (все интересующие Вас инструменты и параметры в куче) и пользовательский от CreateDataSource (Quik уже отфильтровал для Вас только интересующий инструмент; применимо, если Вас интересует только цена последней сделки). Обработали поступившую новую цену (или значение другого заказанного параметра) инструмента в колбеке: получили новое состояние "индикатора", например, покупать-продавать-держать (практически любой индикатор теханализа можно вычислить исходя только из его текущего состояния и новой цены). Поток main, когда возникла необходимость, обращается к единственной переменной "состояние индикатора" и принимает решение. Необходимости блокировать какую-либо область памяти на период "критической" обработки не возникает.

Опять написал много буков...:)
Возможно я не верно понял. что Вы подразумеваете под "функционал с синхронизацией"? Я исходил из того, что подразумевается блокирование доступа для других потоков к общим ресурсам (таблицам), когда один из потоков с ними работает.

P.S. SearchItems работает так же, как если бы Вы сами организовали цикл вызовов getItem для строк со start_index по end_index, просто гораздо быстрее. В пользовательский fn попадает копия исследуемой строки (точнее даже не вся строка, а только запрошенные в params поля).
Подвешивание info.exe через механизм межпоточного локинга
 
Цитата
Антон написал:
1) В каждом колбеке будет уникальная ссылка на луа таблицу?
В каждом колбеке Quik передает Вам lua - таблицу, представляющую собой копию строки таблицы хранения/вывода данных Quikа, которая впервые появилась / изменилась / удалилась.
При каждом Вашем запросе на получение информации о какой-либо строке таблицы хранения/вывода данных Quikа, вы получаете копию (слепок) этой строки (в виде lua - таблицы) на момент запроса.
Под запросом я имею в виду запрос универсального типа (по номеру строки произвольной таблицы) getItem или поисковый запрос (по параметрам строки конкретной таблицы), например, getFuturesHolding, getDepoEx, getOrderByNumber и т.п.
Поэтому, если между Вашим считыванием строки таблицы orders и обработкой полученных данных реальное состояние интересующей Вас заявки изменится (о чем придет OnOrder), уже считанное содержимое никак не поменяется: t.balance будет равно 1. О том, что баланс заявки стал 0 поток main может узнать только лишь еще раз обратившись к таблице orders (getItem или getOrderByNumber) или через реализованный Вами специальный механизм от колбека OnOrder.

Важно понимать, что результат вызова getNumberOf является количеством строк интересующей таблицы на момент вызова этой функции. К моменту Вашего вызова getItem количество строк может измениться, причем как в большую, так и в меньшую строну (в меньшую, правда, может только для таблиц FuturesLimit, MoneyLimit, DepoLimit; также все таблицы обнуляются при рестарте Quikа, о чем мы узнаем по OnCleanUp).
Поэтому мой скрипт считывает (по getItem) содержимое интересующих таблиц лишь один раз (на старте в потоке main), а далее поддерживает их актуальное состояние, ориентируясь по колбекам. Причем, как я уже писал в предыдущем своем посте, колбеки не манипулируют с внутренними (дублирующим Quik) таблицами скрипта, а лишь вешают полученные данные в очередь на обработку для потока main (очередь, правда, поддерживает систему приоритетов, но это уже детали реализации). И делается это именно для того, чтобы не возникала ситуация, при которой пока main будет в целом анализировать, например, таблицу FuturesLimit (точнее ее дубликат), ее количество строк, или уже обработанная строка, вдруг поменяются. Лишь закончив такой анализ, main займется разбором накопившихся за это время необработанных данных из очереди, которые ему навешали колбеки, для поддержания своих внутренних таблиц в актуальном состоянии.
То же касается и обработки OnCleanUp: колбек не очищает внутренние (дублирующие) таблицы скрипта, поскольку это закончится катастрофой, если main в этот момент занят анализом такой таблицы в целом. Он лишь вешает на обработку для main задачу их очистить. Разумеется такая задача имеет наивысший приоритет, чтобы main не занимался обработкой данных от колбеков, поступивших до OnCleanUp, поскольку их информация уже не актуальна.
Подвешивание info.exe через механизм межпоточного локинга
 
Цитата
моя задача: в произвольный момент в мейне запрашивается список сделок или заявок. но пока он обрабатываеться могут прийти новые данные (или вообще очистка данных, когда новая сессия пошла). мне нужно сначала обработку завершить. Ставить крит. секцию на все колбеки и обработку данных как то не хочется.
Конкретно приведенная Вами задача вообще не нуждается в многопоточной обработке. Поэтому нет нужды городить огород с пользовательскими колбеками в потоке Quik.
Мое решение: в событийном колбеке quik полученная информация (таблица) просто вешается в очередь FIFO для дальнейшей обработки в потоке main.
Поток main, когда занят критичной задачей (например, ваша обработка списка накопившихся к моменту старта задачи списка сделок или заявок), не отвлекается на обработку поступающих в очередь событий. Завершив критичную задачу, возобновляет обработку накопившихся в очереди данных, которых ему накидали колбеки Quikа, и, после их обработки, помещает в соответствующий список обработанных (сделок и заявок) для дальнейшего анализа возникающими в потоке main задачами.
Заявка не ушла на биржу! Виноват сервер брокера?
 
На самом деле, я хотел от техподдержки Quik не столько инициирование разбора с брокером, сколько получить ответ на вопрос:

<Ошибка создания заявки. [GW][3] "Сейчас эта сессия не идет.".> генерируется сервером QUIK самостоятельно (по часам сервера, при этом заявка не отправляется на биржу) или на основе ответа биржи на все же посланную заявку?
Заявка не ушла на биржу! Виноват сервер брокера?
 
Zoya Skvorcova,
Есть ли какие-то результаты разбора?
Очистка таблиц Quikа по OnCleanUp может вырубить скрипт. Как уберечься?
 
Видимо вопрос остался незамеченным.

Из вышеприведенных наблюдений есть основание полагать, что после возникновения в потоке Quik (в колбеке) ошибки исполнения интерпретатора (допустим, деление на 0 или индексирование nil), управление все же может вернуться в поток main, и там еще некоторое время скрипт будет выполняться.

ВОПРОСЫ:
1. Это действительно так?
2. Если так, то есть ли какие-то критерии, по которым можно оценить до каких пор будет работать поток main? (например, 5 секунд или до первого вызова sleep и т.п.)
Очистка таблиц Quikа по OnCleanUp может вырубить скрипт. Как уберечься?
 
Анализ показал, что при крайне маловероятном стечении обстоятельств (4 месяца 24/7 все работало нормально), может начаться обработка OnTransReply, когда TEname еще не инициализирована.
Но дело в том, что в логах есть запись об инициализации TEname и абсолютно никак после этого она не может измениться.
Причем между записью значения TEname и записью об этом в лог интерпретатор должен выполнить более 200 строк кода, включая создание нового файла, записи в него и гарантированного сброса на диск по flush. Правда все это происходит в потоке main.
Единственным разумным объяснением произошедшего является то, что поток main еще выполняется достаточно долгое время, даже после того, как lua интерпретатор наткнется на критическую ошибку в потоке Quik (в потоке, где выполнялся OnTransReply()).
Такое действительно возможно?
Очистка таблиц Quikа по OnCleanUp может вырубить скрипт. Как уберечься?
 
Уже хотел ответить Вам, что нечего пенять на TEname, поскольку это argument #2 для find, но решил проверить, и с удивлением обнаружил, что для
tab.brokerref:find(TEname) - это argument #1, а для
string.find(tab.brokerref,TEname) - это argument #2,
хотя это идентичные вызовы функции find, и потому я был уверен, что в диагностических сообщениях об ошибках интерпретатор сообщает нумерацию аргументов именно по их расположению в стеке.
Приношу извинения.
Буду искать как слетел в nil TEname...
Очистка таблиц Quikа по OnCleanUp может вырубить скрипт. Как уберечься?
 
После более спокойного, безэмоционального, анализа возник вопрос:
Quik в OnTransReply() (OnOrder, OnTrtade, равно как и в любой другой колбек) передает адрес блока памяти, содержащего (в виде lua таблицы) новую/изменившуюся строку Таблицы Транзакций (Таблицы заявок, Таблицы Сделок и т.д.) или предварительно делает ее копию, и уже ее адрес передает в колбек? Другими словами, передав в колбек какую-либо таблицу, может ли в принципе Quik потом закулисно обратиться/поменять/стереть (по OnCleanUp) содержимое полей этой таблицы?
Очистка таблиц Quikа по OnCleanUp может вырубить скрипт. Как уберечься?
 
Код
local function Check(tab)
  return tab.brokerref and tab.brokerref:find(TEname) -- умерли здесь
end

function OnTransReply(trans_reply)
-- Для отладки
  if trans_reply.result_msg ~= "Транзакция успешно выполнена." then -- игнорируем служебные транзацкии сбера
    Logt:msg2fileflt(trans_reply, "OnTransReply")
  end
-- !!!!
if Check(trans_reply) or TRCheck(trans_reply) then
    TQ.AddTradeTask(TE.OnTransReplyMain,{trans_reply}) -- помещает в приоритетную очередь задачу вызова обработчика таблицы trans_reply в потоке main
  end
end
Параллельный поток main не еще не имел доступа к таблице trans_reply, поэтому нет смысла его приводить. Другие колбэки, тем более. Косвенным доступом (операциями с глобальным окружением, изменением метатаблиц типов данных и т.п.) скрипт не занимается, таблицу string не переопределяет.
В Logt:msg2fileflt() скрипт не зашел (нет записи в логе, функция всегда заканчивается вызовом io.flush()), следовательно обрабатывалась служебная транзакция обмена информацией терминала и сервера брокера, у которой всегда trans_reply.brokerref == "".

Из текста инструкции
Код
return tab.brokerref and tab.brokerref:find(TEname)
и ошибки
Цитата
bad argument #1 to 'find' (string expected, got nil)
видно, что tab.brokerref не был равен nil, далее, tab.brokerref имел тип string, т.к. интерпретатор успешно обратился к таблице string для индексирования поля find, а вот далее, внутри find, при проверке переданных параметров, обнаружилось, что в качестве первого параметра в стеке оказался nil или ссылка на переменную, содержащую nil, в то время как туда, по идее, должна была быть скопирована ссылка на строку tab.brokerref.
Где-то за секунду до этого в логах был зарегистрирован вызов колбека OnCleanUp(). В момент появления окна с сообщением об ошибке у меня на экране были выведены окна графиков, стакан и таблица текущих торгов. Все они еще были пустыми.
Скрипт работает в неизменном в отношении обработчиков OnCleanUp и OnTransReply виде ежедневно около 4 месяцев, ошибка выскочила впервые. Торги в этот момент еще не шли.
Очистка таблиц Quikа по OnCleanUp может вырубить скрипт. Как уберечься?
 
Столкнулся с таким вот казусом:
Скрипт запускается со стартом Quikа (7.14.1.7), т.е. еще до соединения с сервером.
Однако ничего существенного не делает и ждет OnConnected.
Получив подтверждение связи с сервером, переходит в полноценный режим и начинает, кроме прочего, отрабатывать колбеки OnOrder, OnTrade и т.п., которые вызывает Quik по мере стартового заполнения своих соответствующих таблиц записями о событиях, которые были до включения Quika (мои вчерашние сделки и т.п.)
И тут приходит OnCleanUp...
Ничего, вроде бы, страшного нет, скрипт тоже не слепой, и при необходимости может рестартовать и все заново корректно отработать уже с новой актуальной информацией.

Но вот, что вдруг вылетело:
Скрипт умер внутри колбэка OnTransReply (это был ответ на транзакцию текущего служебного обмена информацией терминала и сервера брокера) на инструкции:
f = tab.brokerref and tab.brokerref:find(TEname)
bad argument #1 to 'find' (string expected, got nil)

где tab - таблица, переданная Quikом в OnTransReply.
Весело получается: когда интерпретатор успешно нашел адрес функции string.find, tab.brokerref еще был строкой, а когда уже стал формировать стек вызова функции find, то tab.brokerref сдох до nil !

Я понимаю, что вероятность второй такой поимки покемона крайне мала, но все же не нулевая.

Уважаемая техподдержка QUIK!
Прошу сделать так, чтобы QUIK, перед очисткой своих внутренних таблиц по OnCleanUp, убедился, что вышел из всех колбеков lua скриптов, и вызывал OnCleanUp скриптов только после завершения своей полной очистки.
Или дайте иное объяснение произошедшего.
Запись в таблицу - вопрос.
 
Цитата
Optimus1 Optimus1 написал:
То есть, когда в данном случае выполнилось условие If then, сама таблица t_id по сути еще не создана ?
Да

Цитата
Optimus1 Optimus1 написал:
А при каком тогда заходе интерпретатор заглянет внутрь функции ?
В общем случае: тогда, когда интерпретатор встретит команду собственно вызова этой функции (main(), CreateTable() и т.п.). Вызов самой первой функции программы делается из тела (body) стартового модуля. Далее команды вызовов функций будут уже отрабатываться по мере нахождения их интерпретатором внутри текущей исполняемой функции.

В QLua: для Quik Вы пишете не самостоятельную (имеющую собственную точку старта) программу, а лишь описание набора колбеков, которые QUIK по мере необходимости будет вызывать.
На стартовом проходе интерпретатор QLua выполняет инструкции body вашего модуля только лишь для того, чтобы в результате получить в глобальных переменных с зарезервированными именами (OnInit, main, OnStop, OnOrder и т.д) адреса написанных Вами функций-колбэков. Если QLua в результате не получит в переменной main адреса функции, то на этом все и закончится. Остальные зарезервированные функции определять не обязательно. Потом он вызовет OnInit(), если найдет там адрес функции (в Вашем случае вызова не будет, т.к. у Вас эта функция не описана). Далее Quik создаст отдельный поток для Вашего скрипта, из которого вызовет main(). В своем потоке Quik, по мере необходимости, будет вызывать остальные ваши колбеки, и т.д.

Может быть Вам проще будет понять действия интерпретатора, если Вы внимательно изучите синтаксис Lua.
Дело в том, что в исходном синтаксисе Lua нет такого такой команды:
function myCode()
...
end
Такая запись - это так называемый синтаксический "сахар", упрощение записи инструкций для приведения их к более привычному для программиста виду.
Реально, до начал интерпретации, эта запись преобразуется к виду:
myCode = function()
...
end
И тогда становится ясно, что интерпретатору, встретив такую инструкцию, просто незачем лезть внутрь тела функции. Вы же всего лишь поручили ему запомнить адрес функции в переменной myCode.

И таких синтаксических "сахаров" в Lua не мало. Изучите их, и писать программу сразу станет проще.
Запись в таблицу - вопрос.
 
Для начала, уточните для себя базовые принципы работы lua-интерпретатора.

Присвоение переменных G1, q, g и т.д., а также блок if..then..end у Вас находятся в теле (body) модуля.
Все эти команды выполняются интерпретатором один раз при первом проходе исходного текста текущего модуля lua, т.е. на этапе, когда интерпретатор даже не заглядывает внутрь текста описанных в модуле функций, а только запоминает адреса их входных точек (другими словами, на этом этапе интерпретатор лишь присваивает глобальным переменным main и CreateTable адрес соответствующей функции, но, повторюсь, внутрь функций он при этом не заглядывает).

Таким образом, Ваш блок if..then..end, находящийся в body модуля, выполняется интерпретатором один раз еще даже до вызова OnInit, не говоря уж об main.
Заявка не ушла на биржу! Виноват сервер брокера?
 
Ошибся с датой в предыдущем сообщении.

Цитата
Zoya Skvorcova написал:
Алексей  ,добрый день.
Сообщите нам кто Ваш брокер,  дату выставления заявки, номер заявки, Ваш uid.
Брокер - Сбербанк. Транзакция на выставление заявки (class_code = "SPBFUT") отправлена клиентом Quik 23.11.2017 18:44:45 (по часам моего компьютера) 18:45:17 (по часам сервера Сбербанка), uid = 60172. Номера заявки - нет, т.к. она не попала на биржу (flags = 0x00040001, result_msg = Ошибка создания заявки. [GW][3] "Сейчас эта сессия не идет.", date_time = 23.11.2017 18:45:17.789)

Убедиться в том, что часы моего компьютера выставлены достаточно точно по отношению к часам биржи можно по заявке:
Транзакция (class_code = "SPBFUT") отправлена клиентом Quik 23.11.2017 14:59:57 (мои часы) 15:00:29 (часы сервера); ответ OnTransReply пришел 14:59:58 (мои часы), 15:00:30 (часы сервера) о выставлении заявки 28607143197 в 14:59:57.363 (часы биржи)

Кстати, сегодня часы сервера брокера выставлены точно.
Заявка не ушла на биржу! Виноват сервер брокера?
 
Цитата
Zoya Skvorcova написал:
Алексей  ,добрый день.
Сообщите нам кто Ваш брокер,  дату выставления заявки, номер заявки, Ваш uid.
Брокер - Сбербанк. Транзакция на выставление заявки (class_code = "SPBFUT") отправлена клиентом Quik 24.11.2017 18:44:45 (по часам моего компьютера) 18:45:17 (по часам сервера Сбербанка), uid = 60172. Номера заявки - нет, т.к. она не попала на биржу (flags = 0x00040001, result_msg = Ошибка создания заявки. [GW][3] "Сейчас эта сессия не идет.")

Убедиться в том, что часы моего компьютера выставлены достаточно точно по отношению к часам биржи можно по заявке:
Транзакция (class_code = "SPBFUT") отправлена клиентом Quik 24.11.2017 14:59:57 (мои часы) 15:00:29 (часы сервера); ответ OnTransReply пришел 14:59:58 (мои часы), 15:00:30 (часы сервера) о выставлении заявки 28607143197 в 14:59:57.363 (часы биржи)

Кстати, сегодня часы сервера брокера выставлены точно.
Заявка не ушла на биржу! Виноват сервер брокера?
 
Сегодня "поймал" неприятную историю: заявка, отправленная на последних секундах торгов, не ушла на биржу.
Есть основания полагать, что это ошибка СЕРВЕРА QUIK.

Детали: Скрипт отправил заявку Forts в 18:44:45 по часам моего компьютера.
Могу со 100% гарантией утверждать, что время моего компьютера отличается от времени биржи не более, чем на 0.5 секунды. (исходя из логов OnTrade, OnOrder и т.п.)
Часы сервера брокера сегодня спешили на 32 секунды, т.е. по часам брокера заявка поступила к нему в 18:45:17
В результате, заявка не ушла на биржу, пришел OnTransReply датированный 18:45:17.789  с формулировкой <Ошибка создания заявки. [GW][3] "Сейчас эта сессия не идет.".>,
Однако, исходя из логов трансляция обезличенных сделок прекрасно продолжалась еще 15 секунд, информация о последней обезличенной сделке поступила в 18:45:00.328 по часам моего компьютера (еще одно подтверждение хорошей синхронизации моих часов с биржевыми).

Правильно ли я понимаю, что сервер брокера решает, когда заканчивается торговая сессия по своим часам, а не по реальному состоянию торгов на бирже?

Прошу техподдержку Quik прокомментировать произошедшее.
Кто как решил вопрос уведомления о сделках?
 
Ответ уже был:
Цитата
Алексей написал:
Эта ошибка вызвана тем, что ssl.dll пытается запустить lua модуль https.lua, который lua-интерпретатор не смог найти.
https.lua должен находится в папке ssl, которая, в свою очередь, должна находится в одной из папок, перечисленных в package.path.
Поскольку в package.path, как правило, прописан, в числе прочих, путь: .\?.lua, то https.lua можно поместить в папку D:\QuikFinam\ssl\

В свою очередь, ssl.dll должен "валяться" не где попало, а в одной из папок, перечисленных в package.сpath
Помогите с логикой
 
Если кроме orders и trades Вы еще собираетесь отслеживать ответы trans_reply на свои транзакции, то имейте в виду, что у некоторых брокеров обмен служебной информацией между сервером брокера и вашим клиентским quik-ом также идет путем обмена транзакциями и trans_reply с заполненным полем TRANS_ID. Чтобы гарантировано отличить свои trans_reply от служебных, еще используйте CLIENT_CODE в транзакции и отслеживайте это значение в ответах в поле brokerref. Опять же, если Вы будете отслеживать ответы trans_reply на свои kill_order транзакции, то здесь тоже есть засада: в транзакции нет CLIENT_CODE и отследить однозначное соответствие пришедшего trans_reply вашей транзакции можно только по паре trans_id : order_num.
Синхронизация 2 графиков
 
валерий,
Действительно, о влиянии этой настройки я не подумал, когда безапелляционно написал "ДА, можно быть уверенным".
Но, если помнить (как я уже писал в т.ч. в последнем своем развернутом посте), что Index в OnCalculate - это просто номер позиции на диаграмме для вывода значения индикатора, то ничего удивительного в описанной Вами ситуации нет. Наоборот, было бы странно, если бы было иначе.
Вы еще посмотрите, что quik Вам будет подсовывать в качестве значений свечек инструмента, если начнете играться с настройкой Дополнительно->Процентное изменение :))
Многомерные массивы и получение CreateDataSource
 
Код
T = {}
local function storeDateTableByIndex(index, ya, mn, d)
  local date = {
    year = ya,
    month = mn,
    day = d
  }
  T[index] = date
end
Синхронизация 2 графиков
 
Цитата
rinat написал:
а если второй инструмент малоликвиден и для некоторых свечей данных не существует?
Именно для проверки таких Index позиций свечек существует функция CandleExist, при этом для такой позиции (несуществующей у конкретного инструмента) свечки Вы прекрасно можете получить правильное время T(Index). Диаграмму можно так настроить (показывать пустые интервалы), что для вывода значений индикаторов будут предоставлены такие позиции свечек, для которых ни у одного из инструментов нет свечек.
Я имел в виду, что у всех индикаторов, выводимых в одной или разных областях одной диаграммы единое пространство нумерации позиций свечек и, потому, можно быть уверенным, что внутри OnCalculate любого из индикаторов T(index) будет гарантировано выдавать одно и тоже время для конкретного значения Index. Это пространство нумерации позиций используется в функциях getNumCandles, getCandlesByIndex и т.п.
Но, разумеется, это пространство нумерации позиций свечек почти гарантированно НЕ совпадает с нумерацией свечек в CreateDataSource. В таблице данных о свечках инструмента, возвращаемой этой функцией, содержатся именно значащие свечки конкретного инструмента. Даже свечка под номером 1 вполне вероятно окажется другая: в DataSource - это действительно первая свечка из (чуть более 3000) транслируемых сервером для данного инструмента (например, для 11:00:00 07/08/2017 в часовом таймфрейме), а в OnCalculate это может оказаться свечка 10:00:00 01/09/2017, если в настройках диаграммы установлено: Диапазон данных за период с 01/09/2017.
CreateDataSource возвращает пустую таблицу, если использовать параметр param
 
Цитата
Andrei2016 написал:
Дмитрий Минеев  ,

Не совсем понятно, на что указывает ваша стрелка, так как изображение сокращено.
Поясните, что вы хотите сказать.
Он имеет в виду, что если убрать <<, 'bid'>>, то все работает.

Andrei2016, myFunc - это глобальная переменная, значение которой (ссылка на сам текст функции) присваивается при первом прохождении qlua интерпретатором body скрипта, т.е. еще до вызова OnInit и main.
Синхронизация 2 графиков
 
Цитата
валерий написал:
Если два графика расположены в двух областях одной диаграммы, то нужно ли бары обязательно синхронизировать по времени баров или можно быть уверенным, что если индексы совпадают, то и время тоже?
Ответ просто: ДА, можно быть уверенным.
Index в индикаторе это, правильнее будет сказать, не номер свечки графика инструмента, а номер ее позиции на диаграмме с учетом возможных пропусков свечек того или иного инструмента.
Во всех областях одной диаграммы, равно как и у всех индикаторов одной области единое "пространство" позиций для свечек с единой сплошной нумерацией без пропусков.
Кто как решил вопрос уведомления о сделках?
 
Вы пробовали запустить Ваш скрипт из ZeroBraneStudio, ничего не меняя в path и cpath?
Если такая же задержка с первым пакетом, то дело, скорее всего, в почтовом сервере, к которому Вы обращаетесь, или в Вашем скрипте. Пройдитесь отладчиком ZeroBraneStudio по вашему скрипту.
Если же при запуске из ZeroBraneStudio задержка не превышает 5 секунд, а из quik - 5 минут, то Вы, возможно, неправильно собрали модули.
1. Рекомендую libeay32.dll, ssleay32.dll и lua51.dll (копия quik-овского lua5.1.dll !!! Ни в коем случае не из ZeroBraneStudio) переложить в папку quik (где лежит info.exe).
2. Из clibs нужны только ssl.dll, mime\core.dll и socket\core.dll.
2. Уберите с компьютера всё дублирование вышеперечисленных Вами файлов (оставить только "родной" пакет ZeroBraneStudio и копии необходимых из него файлов в Вашем C:\MY-ROBOT).
3. Проверьте значения path и cpath при запуске из quik и убедитесь, что скрипт никаким способом не сможет наткнуться на какой-либо другой lua51.dll, кроме положенного в папку quik.

У меня, обычно, задержка и из ZeroBraneStudio, и из quik составляет не более 0,5 сек при обращении к серверу телеграмм (а это тот же POST пакет).

P.S. OnInit выполняется в основном потоке quik. Зависли в OnInit - завис quik.
main выполнятся в выделенном потоке. Зависание в нем никак не тормозит работу quik.
Кто как решил вопрос уведомления о сделках?
 
И попробуйте сначала все это запустить из под какого-нибудь lua интерпретатора, а когда устойчиво заработает, перенесите в quik.
Кто как решил вопрос уведомления о сделках?
 
Цитата
Сергей написал:
Я взял https.lua из luasec 0.7 alpha.. Похоже, что-то не так с либами OpenSSL. Нужно ли что-то дополнительно ставить в систему для обеспечения работы luasec?
1. Вы взяли просто https.lua от 0.7a или в паре с соответствующей версией ssl.lua и ssl.dll?
2. Попробуйте в ssl.lua в local function wrap закомментарить строку -- sock:setfd(core.SOCKET_INVALID)
Кто как решил вопрос уведомления о сделках?
 
Сергей,
Ваш скрипт случайно не переопределяет глобальную переменную TIMEOUT модуля socket\http.lua на слишком большое значение?
Кто как решил вопрос уведомления о сделках?
 
Эта ошибка вызвана тем, что ssl.dll пытается запустить lua модуль https.lua, который lua-интерпретатор не смог найти.
https.lua должен находится в папке ssl, которая, в свою очередь, должна находится в одной из папок, перечисленных в package.path.
Поскольку в package.path, как правило, прописан, в числе прочих, путь: .\?.lua, то https.lua можно поместить в папку D:\QuikFinam\ssl\

В свою очередь, ssl.dll должен "валяться" не где попало, а в одной из папок, перечисленных в package.сpath
Насколько уникален order_num?
 
Sergey Gorokhov,
Большое спасибо за разъяснения!
Насколько уникален order_num?
 
Sergey Gorokhov,
Цитата
Бирж много и у каждой свои правила. QUIK умеет работать с очень большим количеством бирж.
Но умение это взялось не из-за какого-то уникального AI, встроенного в программное обеспечение, а из четко заложенных разработчиками для каждого class_code своих схем данных обмена командами и информационных потоков с соответствующей торговой площадкой.
Цитата
Как уже было сказано бирж много, у каждой свои правила и свои транзакции и даже если транзакции разных бирж делают одно и тоже, у них могут  быть разные параметры.
Именно поэтому, в идеале, хотелось бы увидеть для каждого class_code свой справочный файл с описанием полей отправки транзакций и полей потоков OnOrder и OnTrade (для торговых поручений). Ведь наименования и информационное наполнение этих полей не являются копией протоколов биржевых шлюзов, а являются собственной разработкой ARQA. Эту документацию не обязательно поставлять в составе Quik, но хотелось бы иметь возможность получить ее хотя бы по запросу для конкретного class_code.
Но это все, конечно, мои "хотелки", а вовсе не претензии к разработчикам :)
Цитата
К слову, чтобы узнать как называется нужный параметр "на русском", достаточно добавить нужную транзакцию в карман транзакций и сохранить от туда в tri файл.
Именно по отношению к этой, неоднократно встречающейся на форуме рекомендации, я написал:
Цитата
Алексей написал:
разработчики ... предлагают экспериментальным путем выяснять как работает их продукт.
А теперь, вернемся к конкретике.
В форме ввода для ручной подачи заявки forts есть возможность выставить "многодневную" (как это названо в руководстве spectra plaza) заявку c временем жизни "по дату".
В руководстве Qlua об этой возможности я ничего не нашел.
Цитата
Да это и не нужно так как эти параметры есть в правилах торгов которые есть на сайте нужной Вам биржи.
В руководствах spectra plaza я увижу описание потока информации по шлюзу между биржей Forts и сервером брокера, но я не увижу какие параметры нужно заполнить в таблице для sendTransaction и в каких полях OnOrder я смогу увидеть информацию, связанную, например, с ежедневным перевыставлением заявки.

Через карман транзакций я выяснил какие параметры нужны для sendTransaction, и они были на русском.
Цитата
Дело в том что в английском интерфейсе терминала, эти же параметры будут "на английском".
В описании *.tri файла я не нашел подходящего параметра. Но может быть, все же, в английском варианте есть поле, соответствующее ["Переносить заявку"]? (Или для выяснения этого я должен переключить язык интерфейса клиентского места? Опять же, в региональных установках у меня только одна возможность выбора языка - это "Russian[Standard Set]").

Опять же, главная проблема не в этом.
А главная проблема в том, что при разработке скрипта нельзя гадать, какой столбец Quik-овской Таблицы Заявок соответствует какому полю lua таблицы, получаемой в OnOrder. Это надо четко видеть в руководстве разработчика Qlua. Например, откуда берется информация для столбца "Расширенный статус"? Из ext_order_flags? Но об этом нигде ни слова, как и о собственно значениях битов этого флага. Между тем, оттуда можно подчерпнуть информацию о том, что заявка "отменена по закрытию сессии", что бы убедится, что она не "слетела" по каким-то иным причинам. Ведь во всем остальном для скрипта ответ OnOrder в этой ситуации выглядит так, будто заявку отменил сам пользователь вручную. Как скрипту связать перевыставленную после клиринга заявку с исходной? По linkedorder или в exchange_code, где мы можем увидеть исходный order_num заявки (и заодно первоначальную дату выставления заявки)? Но это лишь мои предположения. Где можно найти об этом информацию? В руководстве Qlua об этом ни слова. Или нужно искать linkedorder, exchange_code и т.д. в описании протокола обмена информацией между биржей и сервером брокера? Так там совершенно другие наименования полей. А заниматься гаданием, при написании приложений, управляющих реальными деньгами, - непозволительная роскошь.

Я не докапываюсь до отсутствия описания какой-то малоиспользуемой, частной особенности выставления и работы с заявкой на forts. Я говорю об общем подходе к описанию OnTransReply, OnOrder, OnTrade и параметров таблицы для sendTransaction. На форуме неоднократно уже говорилось, что странно, что о некоторых ограничениях в работе с заявками из lua оказывается надо узнавать из описания Qplie. Странно, что в руководстве не упоминается, что поле class_code не заполняется в ответах OnTransReply на Kill_Order транзакции. И этих "странно" очень много на форуме. Просто смешно наблюдать, когда пользователи на форуме начинают гадать, какая информация содержится в exchange_code, там ни одного вразумительного ответа.
Пожалуйста, дополните, насколько возможно, описание Qlua.
И, пожалуйста, расшифруйте значения битов ext_order_flags хотя бы для фондовой и срочной площадок московской биржи. (Хотя в описании столбца "Расширенный статус" указано 8 вариантов, никак не связанных с конкретной торговой площадкой).
Насколько уникален order_num?
 
Уважаемая техподдержка Quik!
Уже можете не отвечать. Разобрался экспериментальным путем.
Но я первый раз встречаю программный продукт, допускающий возможность разработки пользовательских расширений своего функционала, разработчики которого не желают представить действительно полное описание своего API, а предлагают экспериментальным путем выяснять как работает их продукт. Игра с черным ящиком на деньги опаснее, чем в три наперстка на привокзальной площади.

С другой стороны, заранее прошу прощения у разработчиков за свой эмоциональный пост, возможно, я просто по невнимательности не нашел в руководствах Quik раздел, посвященный выставлению средствами lua лимитированной заявки на рынке Forts с возможностью автоматического перевыставления её на последующие торговые дни до указанной даты. Интересно было бы посмотреть описание поведения для такой заявки полей таблицы orders: trans_id, exchange_code, linkedorder, ext_order_flags и т.д., а не выяснять это экспериментальным путем.
Также я не нашел полноценного описания формата *.tri файла с ключами на русском языке, обладающего большей функциональностью.
Открытие по рынку
 
Lena Po,
На самом деле не все так страшно, как написано выше, просто надо четко понимать, что Вы получаете, выставляя "рыночную" заявку на рынке FORTS, и связанные с этим риски.
Действительно, Мосбиржа (срочная секция FORTS) не поддерживает рыночные заявки.
Когда Вы выставляете рыночную заявку на FORTS, сервер quik конвертирует её и выставляет на биржу ОДНУ лимитированную заявку по заявленной Вами цене с режимом исполнения заявки KILL_BALANCE (снять остаток). Чтобы сымитировать поведение такой заявки, как рыночной, в документации Quik указано, что необходимо указать цену минимально или максимально возможную для вашего инструмента – в зависимости от направленности сделки (см. колонки Максимально/Минимально возможная цена Таблицы текущих торгов). Вы же можете указать наихудшую цену, по которой готовы заключить сделку.
Строго говоря (в соответствии с документацией Quik) указывать цену 0 нельзя. Но в действительности некоторые брокеры настраивают свои серверы так, чтобы они принимали такие заявки с нулевой ценой, и, перед отправкой на биржу, подставляют в заявку правильную предельную цену. Но, видимо, это не Ваш брокер. Отсюда и ошибка (недопустима цена 0).
Возможно эту ошибку еще может вызывать включенная настройка клиентского места Торговля->Заявки->Проверять попадание цены в диапазон.
Насколько уникален order_num?
 
Цитата
s_mike@rambler.ru написал:
Цитата
_sk_   написал:
Если торгуете на Московской бирже, то class_code + order_num уникальная комбинация.
в течение одного торгового дня
Как ведет себя order_num лимитированной заявки forts, выставленной средствами qlua, после перехода через клиринг, если она выставлена с условием ["Переносить заявку"] = "Да" и указанием даты экспирации? Если он меняется, то как скрипт может узнать какой новый номер присвоен заявке? Придет OnOrder со старым trans_id, но новым order_num?
Кто как решил вопрос уведомления о сделках?
 
"LuaSec 0.6" (ssl) нужен, только если Вы собираетесь использовать https протокол
Кто как решил вопрос уведомления о сделках?
 
Цитата
Иван Ру написал:

Теперь, после добавления нужной буквы получаю такое сообщение
error loading module 'mime.core' from file 'C:\QuikFinam\scripts\core.dll':
Попробуйте, все же сделать так, как описано в приведенной мною выше ссылке (а именно взять готовые пакеты "LuaSocket 3.0-rc1" (core), "LuaSec 0.6" (ssl) из ZeroBraneStudio).

Ваша ошибка вызвана тем, что core.dll пакета (модуля) socet не находит core.dll пакета (модуля) mime.
Кто как решил вопрос уведомления о сделках?
 
Посмотрите в этой теме, может поможет.
https://forum.quik.ru/messages/forum10/message24016/topic1097/#message24016
Функция отбора (обратного вызова) для SearchItems
 
Спасибо за пояснения!
Вопрос был вызван тем, что я (клиент Сбербанка) до сих пор вынужден сидеть на quik 7.6.
В документации к нему про nil не упоминается. Отсюда и возник вопрос. Скачал документацию к 7.14.
ОК. Вижу более полное описание для fn. Но писать скрипт надо так, чтобы работало и под 7.6 (со всеми его багами) и под 7.14.
Придется впредь метаться между этими версиями документации, пытаясь угадать, где имеем неполную документацию, а где - пока (для 7.6) нереализованный функционал :(

Поэтому вопросы остаются:
1. Для quik 7.6 ситуация с реакцией на возврат nil из fn - забыли упомянуть в документации или еще не реализованный функционал?

2. Можно ли из fn вместо true возвращать любое значение, отличное от nil и false? (в lua при проверке результатов выражений любой результат, отличный от nil или false, интерпретируется как true)
Функция отбора (обратного вызова) для SearchItems
 
Подскажите, пожалуйста, должна ли функция обратного вызова для SearchItems возвращать строго true - false, или можно возвращать (как это обычно принято в lua) для отрицательного результата возвращать false или nil, а для положительного результата - любое другое значение.
метатаблица для OnInit
 
В QLua, как и в обычном Lua все эти "изыски" прекрасно работают. Единственное, с чем эти номера не проходят, это с колбеками QLua. Причину я уже назвал выше: Quik перед вызовом проверяет, что в переменной (с зарезервированным именем колбека) содержится ссылка именно на функцию (видимо как-то так, переводя этот код на Lua: If OnTrade and type(OnTrade) == "function" then OnTrade(trade) end).
Вы же пытаетесь в зарезервированное имя колбека записать ссылку на таблицу или пользовательские данные (получится type(OnInit) == "table" или type(OnInit) == "userdata" и т.п.).
Что Вам мешает сделать так:
function OnInit()
 MyOnInit()
end
MyOnInit = {}
ну и далее все, что Вы хотели сделать с OnInit делайте с MyOnInit.
метатаблица для OnInit
 
Quik, скорее всего, перед вызовом пользовательских колбеков проверяет, чтобы в переменной (с зарезервированным именем колбека) хранилась ссылка именно на функцию.
В вашей реализации получается, что в переменной с зарезервированном именем OnInit хранится ссылка на таблицу. Вот Quik ее и не вызывает.
Что Вам мешает сделать просто OnI nit = a?
FOK и IOC заявки
 
"FILL_OR_KILL" - исполнить немедленно, только если в момент выставления заявки на биржу, предложения достаточно. Если предложения недостаточно - снять заявку.
"KILL_BALANCE" - исполнить немедленно в объеме предложения, имеющегося на бирже в момент выставления заявки, оставшийся объем - снять. По моему, это то, что Вам нужно.
Насколько уникален order_num?
 
Если в течение торгового дня для разных классов на бирже (на разных площадках) могут быть зарегистрированы разные заявки с одним и тем же order_num, то почему же в OnTransReply на снятие заявки нет class_code?

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

Проблема в том, что для KILL_ORDER транзакции brokerref не заполняется, однозначности в trans_id - никакой, т.к. клиент quik сам беспрерывно обменивается с сервером кучей своих служебных транзакций с непредсказуемо заполненными trans_id, а тут еще выясняется, что и order_num - тоже не однозначный идентификатор. Что остается? Заниматься еще анализом firm_id и client_code для однозначной идентификации к какой торговой площадке относится пришедший OnTransReply от KILL_ORDER?
Распределенность обработки вызовов OnOrder
 
Чтобы уж точно не зависеть от того в одном потоке исполняются колбеки или в нескольких, я не обрабатываю в них информацию, а только фильтрую нужные и ставлю их в очередь. Обработкой же занимается исключительно поток main в той очередности, в какой были вызваны соответствующие колбеки (OnTransReply, OnOrder, OnTrade). При этом я не отбраковываю OnOrder с неизвестными trans_id и uid, т.к. к моменту их прихода зачастую уже известно соответствие order_num и trans_id из ранее пришедших OnTrade или OnTransReply.
Что касается редких парных (в единичных случаях тройных) вызовов OnOrder при снятии заявки, то по анализу моих логов выходит, что в первом (втором) из них всегда не достает какой-нибудь информации и лишь в последнем имеется все информация, а именно: uid, trans_id, flags - заявка неактивна-снята, "правильный" balance (соответствует ранее пришедшим OnTrade и OnTransReply на снятие заявки), withdraw_datetime, canceled_uid. Бывает, что приходит canceled_uid - заполнен, а withdraw_datetime - еще нет, хотя OnTransReply для транзакции на снятие заявки с успешным статусом уже пришел. Вот когда все эти поля заполнены - тогда мой алгоритм считает, что пришел последний OnOrder о снятии заявки.
 
Насколько уникален order_num?
 
Спасибо!
Насколько уникален order_num?
 
Транзакция на снятие заявки требует указания не только номера заявки, но и кодов класса и инструмента.
Отсюда возникает вопрос: насколько уникален в течение торговой сессии номер заявки?
Он действительно уникален или уникален в пределах класса инструментов (class_code + order_num) или уникальной является лишь комбинация class_code + sec_code + order_num?
Локальные переменные
 
Цитата
Иван Джеммер написал:
Цитата
Если локальные переменные уничтожаются при выходе из функции, почему тогда мы сможем прочесть локальную переменную 'var'
Таким образом, вызывая func_2 (или var_func) Вы не читаете переменную var, а обращаетесь к копии её значения, сохраненной в стеке функции func_2
Страницы: Пред. 1 2 3 4 След.
Наверх