Давайте пошагово распишу, а то как-то процедура совсем не та. Во-первых, подключаться к серверу не нужно, все есть в файлах, если квик уже был подключен до этого хоть раз. Далее 1. Запустили квик. 2. Создали таблицу "состояние счета". В нее загрузится из файлов что есть, нам не надо тут точности, лишь бы было что-то. 3. Открыли настройку экспорта дде. Поставили сервер excel, книга test, лист test, запускать автоматически сняли, вывод после создания поставили. 4. Вот в таком виде закрыли квик. 5. Запустили фейкосервер. 6. Запустили квик, он загрузился и стартанул дде из нашей таблицы согласно галке. 7. Смотрим в сервере, что приехало. 8. Возвращаем квик в рабочий вид, закрываем. 9. Закрываем сервер.
Где заголовки таблицы (а они настроены выводить)? Что за диапазоны негативные? В общем, косяк очевидный.
К автозапуску это отношения не имеет (вопреки всем предположениям выше), это исключительно действие галки "вывод после создания". Как воспроизвести: создать таблицу состояние счета, настроить вывод в эксель с любыми книгой/листом, поставить галку "вывод после создания", закрыть квик. Запустить сервер из поста выше, запустить квик. После старта дде вот это и приедет. Ну или можете своими средствами как-то отмониторить, что едет, если есть такие средства. Кстати, в quik_dde.log все хорошо-распрекрасно, туда даже факт ошибки не попадает, так что я б на него не надеялся.
Игорь написал: при автозапуске выходит ошибка, потом файл открывается уже
Тогда похоже на то, что квик рановано начинает выводить. По итогу резюмируем, что мы тут разрыли: 1. Квик стартует сервер безусловно при установленной галке автозапуска. Обычно программы это умеют обрабатывать и действуют так: нас запустили с файлом, мы ищем, нет ли другого экземпляра с тем же файлом, если он есть - активируем этот другой экземпляр и сами тихонько завершаемся. По идее, конкретно эту ошибку оно вызывать не должно, хотя поведение несколько нестандартное, стандартно сначала пытаться начать экспорт, потом уже при неудаче запускать сервер. 2. Есть ли после запуска сервера вызов WaitForInputIdle? Это только в арке могут посмотреть. 3. Некоторые программы (включая эксель) регистрируют в реестре пожелание передавать им аргументы через DDE (а не через командную строку, как обычно), поэтому когда винда стартует эксель, она сама к нему коннектится и передает имя файла для открытия. Не возникает ли здесь гонка с квиком?
Denis написал: А если цена будет постепенно снижаться?
Дело не в самой цене, дело в том, что будет в стакане стоять, когда туда ваш лимитник влетит. Может и на быстром движении попасть сразу на встречную, может и на медленном (на неликвиде например) повиснуть и ждать чудес. Только ставить хороший запас, а какой - надо смотреть по конкретному инструменту и на конкретных движениях, как там обычно бывает, да и еще прибавлять немного для надежности.
Игорь написал: соответственно данные в ней не менялись
Вот это странно, в таком раскладе квик должен был выплюнуть имеющиеся строки и на этом успокоиться. Выше я малость бред написал, прошу прощения, думал об одном, писал о другом, касаемо вот этих повторов строк надо думать, как и почему квик их обновлял, раз таблица не менялась. Но и вторая "полумысль" насчет макросов тоже стоит проверки (книгой без них). Возможно, они как-то мешают выводу на начальном этапе.
Anton написал: при отправке poke что делает квик, если получено негативное DDEACK?
Вопрос снимается, сам проверил. При получении busy квик немедленно рвет соединение и вываливается в ошибку "сервер занят". Что не очень здорово, конечно, но, с другой стороны, полностью отвергает мое предположение, т.к. в рассматриваемом случае ошибка другая.
Игорь, у меня идеи на данный момент иссякли, остался один неясный вопрос. Вчерашний скрин был сделан при подключенном квике или при отключенном? Если при подключенном (и состояние счета менялось), то многократный вывод одних и тех же строк объясняется их изменением в квике, это нормально. Если же при отключенном, то дергать данные могли только ваши макросы, и тогда можно попробовать создать книгу без макросов и поэкспортировать в нее, будет ли ошибка тогда появляться.
Denis написал: Если цена начнет сильно падать, как поставить стоп чтобы сделка закрылась на 31.
Чтобы гарантированно закрылась не хуже заданной цены - никак, всегда есть шанс, что цену провалят одним движением ниже вылетевшего лимитника, а дальше лотерея, то ли отскочит, то ли нет.
Игорь написал: Впечатление, что вывод из таблиц начинает идти раньше, чем загрузится Excel.
Тогда была бы ошибка "не запущен эксель или и т.д.". Именно что инициация соединения проходит успешно, окно экселя уже существует и документ в него загружен, иначе он бы не ответил на запрос. Вот эта новая информация
Цитата
Файл Excel у меня около 1 Мб, в нем работают свои макросы в 5 модулях. Может файл тяжелый слишком?
еще укрепила мое подозрение, которое я теперь озвучу. Итак, вопрос арке, при отправке poke что делает квик, если получено негативное DDEACK? По идее, квик должен сначала проверить флаг fBusy, и если он установлен, повторить попытку экспорта того же самого блока данных, а если не установлен - тогда уже выпадать в ошибку "сервер отказался и т.д.". Вот у меня подозрение, что флаг не проверяется, соответственно эксель отвечает "занят" и квик сразу фейлит.
Все ж попробуйте в мой сервер вывести с парсером. Скрин уже, видимо, не стоит шарить, бо информация по счету вся будет видна, но там можно и так посмотреть, что все блоки данных идут последовательно, а не вперемешку. Если все же выводятся кашеобразно, это еще плюс один довод в пользу косяка с busy. Только имейте в виду, что сервер простенький и busy не отвечает, что может при неудачном раскладе подвесить квик.
Игорь, и еще одно предположение созрело, где может быть косяк. Попробуйте снять галку "новый поток на отдельный DDE-сервер" в основные настройки - экспорт данных, будет ли ошибка повторяться?
Игорь написал: 3. Запускаю экспорт - и вот тут какая-то недоработка, видимо. Похоже, что притворяется она не очень. Запускается Excel (пробовал убрать название рабочей книги, запускается пустая новая).
По некотором размышлении это действительно недоработка, но не моя, а арки. Как видим, квик безусловно стартует заданное приложение перед началом дде-обмена, а это неправильно, правильно будет сначала попробовать подключиться как есть, и только если ответа нет и установлена галка автозапуска, тогда запустить сервер и пробовать подключиться еще раз.
И ошибки экспорта нет, верно я понял? Квик несколько раз присылает одно и то же, он подключен к серверу в этот момент? В остальном на этом уровне все ок, надо дописывать парсинг данных и смотреть, что там внутри ячеек.
Не совсем. Начиная с некой размерности задачи попытка "в лоб" закодить будет сродни попытке построить "конечный автомат всея квика", то есть (не) получится нечто необозримого объема. Переход тксть количества в качество произойдет и хошь не хошь придется ООП использовать.
Цитата
новичок написал: именно это мной и имелось ввиду. это грубая ошибка. нет сомнений.
Согласен. На форуме лучшее, что можно получить, это ключевики, куда искать. Все равно сколько-нибудь серьезную тему одним-двумя постами не раскрыть.
Игорь написал: попробовал очистить лист, перед закрытием Excel, затем при запуске, после очередной ошибки посмотрел этот лист - естественно там ничего не было
Неудивительно, эксель сразу же отклонил приехавшие данные, вставлять было нечего.
Цитата
Игорь написал: Софтину написать я, конечно же, не смогу
А я смогу, и тут как раз тот случай, когда любопытство перевесило лень. В общем, вот софтинка примитивнейшая, что с ней делать: 1. Убедиться, что эксель НЕ ЗАПУЩЕН. 2. Запустить софтинку, появится черное консольное окошко с надписью сервер работает. 3. Запустить экспорт из квика в эксель (софтинка притворяется экселем). 4. Смотреть в консольном окошке, что приехало из квика, делать скриншоты по желанию. 5. Остановить экспорт из квика. 6. Закрыть консоль.
Для начала я не парсил сами данные, проверяем только тип данных и диапазон приехавших ячеек, если тут все ок будет, допишем еще проверок. Интересно именно сравнить, что приезжает в нормальном случае и в случае ошибки.
Дисклеймер: софтинка ПРИМИТИВНАЯ, может вызывать в некоторых случаях побочные эффекты, включая зависание квика. Так что с осторожностью.
Виталий написал: Кстати, а откуда Вы взяли эти данные/статистику? Есть какие-то исследования на эту тему?
Это просто очевидно. Возьмем C против C++, например. По памяти добавляются RTTI, таблицы виртуальных функций, таблицы исключений, код вызова деструкторов и конструкторов, не говоря уже о поддержке всего этого со стороны стандартной библиотеки. По скорости добавляются виртуальные вызовы, оверхеда немного, но он есть, а в случае dynamic_cast или множественного наследования оверхед уже значительный. В случае с луа ООП делается через метатаблицы, по памяти это плюс сама метатаблица, по скорости это плюс доступ к ней.
Если мыслью по древу растекаться, все упирается в мозги программиста. Теоретически сложную программу вроде квика можно спроектировать как единый конечный автомат, более того, как единый конечный автомат можно спроектировать систему квик-клиент + сеть + квик-сервер. Но практически никто такую модель в голове не сможет удержать, поэтому надо разделять ее на части. Разрезать можно только по коду, сохранив единый вектор состояния ("обычное" программирование с функциями), либо по коду и по вектору состояния (ООП). На практике вектор состояния режется и при обычном подходе, функции работают всегда с какой-то его частью, просто это делается неявно и ничто не мешает залезть из функции на "чужую территорию", ООП же запрещает такие поползновения.
Безотносительно к луа ООП понижает цикломатическую сложность кода в целом, позволяя писать куски кода разным людям или одному в режиме "по частям" и упрощая формальный анализ и покрытие тестами. Профит только в этом, все остальное рекламное бла-бла, в том числе НЕ быстрее, НЕ меньше памяти и даже НЕ меньше кода как такового (а обычно сильно больше). Соответственно, если вас данная проблематика не тревожит, можете не загоняться. По поводу "зачем оно есть именно в луа" - ну так вышло, что можно извернуться и сделать ООП, чего ж не возопить "у нас есть ООП".
Сергей написал: С задачей определения цены, соответствующей положению курсора, QUIK справляется.
Ну ок, вижу, что не добьюсь ничего, примем за ответ "на усмотрение арки".
Цитата
Сергей написал: А на минутках нужно поставить стоп в 4-6 пунктах от выставленной заявки. Пока все эти манипуляции проведешь и форму заполнишь - цена может в убыток улететь. Закрывать потом по рынку при резком движении цены - неизвестно где закроется.
Сергей написал: Так что точность в 1 пиксел - более чем приемлемая.
Опять ответ "никому это не надо", а вопрос - какую конкретно цену в заявку подставлять. Квик же не может заявку "примерно" отправить. Случайную из диапазона? По верхней границе? По нижней? Посередине? Понятно, что "вот где-нибудь здесь", а заявку-то надо "конкретно в граммах" ставить.
Так и рассчитывалось, что один раз заполните и все. Если хотите в реалтайме таблицу обновлять, не надо tbl прибивать. Да и все несколько посложней может быть в этом случае. Это просто пример, в какую сторону думать.
Нда. Там так дальше и идет, каждый i имеет свой отдельный блок? А зачем тогда цикл по SecCode, спрашивается. Ну как-то так я имел в виду, работоспособность не гарантирую, чисто пример
Код
function main()
SecCode = { ... }
-- временная табличка вместо экранной
local tbl = {}
-- то же самое, что у вас в цикле, только заполняем не экранную таблицу, а временную
for i,s in pairs(SecCode) do
-- здесь у вас s - код бумаги, i - индекс в SecCode
-- я намеренно опустил if i==1 then, ибо это жесть
if X>100 then
-- создаем новую "строку" и добавляем во временную табличку
local r = {}
r.direction = "SHORT"
r.name = NAME
r.x = X
table.insert(tbl, r)
end
if Y>100 then
-- создаем новую "строку" и добавляем во временную табличку
local r = {}
r.direction = "LONG"
r.name = NAME
r.x = X
table.insert(tbl, r)
end
end
-- тут цикл по SecCode закончился и в tbl лежат строки в каком-то там порядке, теперь мы их сортируем по столбцу x
table.sort(tbl, function(lhs, rhs) return (lhs.x < rhs.x) end)
-- и вставляем строки из временной таблицы в видимую
for i,r in pairs(tbl) do
local idx = InsertRow(t_id, -1)
SetCell(t_id, idx, 0, tostring(r.direction))
SetCell(t_id, idx, 1, tostring(r.name))
SetCell(t_id, idx, 2, tostring(r.x))
end
-- tbl больше не нужна, прибьем ее, чтобы не лопала память
tbl = nil
-- дальше что там было дальше
end
Не понял, что в примере кода происходит. Я б поменял общий подход, если сортировка нужна: сначала накидать строки в луа-таблицу (по индексу), потом ее отсортировать по последнему столбцу, а потом одним движением перенести в полученном порядке в окно.
Игорь написал: Перезапустил Quik - при запуске сразу появляется ошибка
Цитата
Игорь написал: Да и эта выводится, когда вручную ее запустишь.
Вот это очень важный, по-моему, довесочек. Выходит, квик стартует дде перед тем, как таблицу заполнил. Крайне было б любопытно взглянуть, что ж все-таки приезжает в эксель в первом случае, только софтину надо писать для этого.
Сергей написал: У меня в практике такая проблема не возникала никогда.
Тем не менее, представим, что на графике видно движение процентов так в 30 по бумаге и высота графика по диапазону цен 300 пикселей, то есть один пиксель покроет 0.1% цены. Много это или мало вопрос второй, интересно именно какую конкретно цену должен квик поставить в заявку. Легко представляю себе тему на форуме "я кликнул по месячному графику и купил на все плечи на 100 рублей дороже, чем хотел, какой дурак придумал такой способ ввода" и т.д. и т.п.
Про счет и количество более-менее все ясно как раз.
Сергей написал: нажать левую клавишу мыши на целевом уровне в произвольной точке графика
Прошу прощения, что опять влезаю, но никак нельзя мимо пройти. Обратите внимание, что в зависимости от масштаба графика один пиксель - в который вы кликнули - может покрывать очень разный диапазон цен. Счет и количество можно подставить дефолтные, но нельзя же отправить заявку по диапазону, все равно придется показать нечто для уточнения конкретной цены. Мне интересно ваше мнение, как эту неоднозначность надо разрешать, не показывая дополнительных интерфейсов.
, то квик воспримет код инструмента буквально, без подстановок, и будет искать его как есть. И не найдет, естественно.
Цитата
Дмитрий написал: Моя цель получить некие параметры по TICER = RIM0 из таблицы всех сделок
Навскидку вырисовывается вариант с SearchItems, в колбеке будете получать строки ТВС одну за одной, применять свой шаблон к коду инструмента и, если он подошел, использовать эту строку. См. примеры в qlua.chm, приложение 4, там достаточно близко к тому, о чем я говорю.
Crypto error: Соединение установить не удалось. Возможно, Вы используете ключи, которые не зарегистрированы на сервере. Сообщение об ошибке: "Connection was closed by peer: Can't get message size from net", Crypto error: Соединение установить не удалось. Возможно, Вы используете ключи, которые не зарегистрированы на сервере. Сообщение об ошибке: "Connection was closed by peer: Can't get message size from net"
Андрей К написал: только своп на десктопе выключен
Мэпы файлов в том числе тем хороши, что они свопятся непосредственно в свой файл, им своп не нужен. Out of system memory скорей наводит на мысль о том, что слопан весь невыгружаемый пул в ядре, проблема распространенная и гуглится легко. Может будет полезно вот это еще поглядеть.
Дмитрий написал: Предположу, что переписать надо так: TICER = "RI[%w]"
Тогда уж "RI[%w]*". Но я тут подумал, что если вы рассчитываете в таком виде в квиковские функции передавать, то оно работать не будет (и это правильно). Возвращаясь к теме "чтобы не переписывать код", лучше в начале скрипта объявить название бумаги в виде переменной и потом его везде вставлять. Тогда замена инструмента сведется к замене этой одной переменной. Ну как-то так
Код
local classcode = "SPBFUT"
local seccode = "RIM0"
...
function do_something()
local val = getParam(classcode, seccode, param) -- и так везде, где нужно сослаться на инструмент
end
Дмитрий написал: Добрый день! Возможно ли вводить в коде луа распознавание инструмента по маске. Например есть строка кода: TICER = "RIM0"; чтобы не переписывать код при смене на новый инструмент пробовал варианты: "RI*" и "RI??", но чего-то не фурычит. Может у кого есть какие идеи?
Nikita написал: ( в итоге не видит то что переменная стала равна 1 почему то)
Потому что CreateTable закончилась до того, как присвоили 1 условию, т.е. переменная и не стала равна 1, поэтому и видеть нечего.
Цитата
Nikita написал: (тут еще загвоздка как установить в ячейку значение Х из верхней части кода)
Вытащите это из CreateTable, создайте пустую таблицу в этой функции и все. Дальше вставьте код из первого варианта, только вместо message используйте InsertRow/SetCell в свою таблицу. Когда таблица будет готова, сделайте вечный цикл до нажатия "остановить" или закрытия квика. Перед выходом из main прибейте свое окно.
Виктор написал: Не понимаю, какую db name использовать.
Это название параметра, который хотите получить, типа там "bid", "last" и прочее, в том числе и ГО как-то обзывается, точно не скажу как. К слову сказать, сразу после заказа параметра вы скорей всего все равно ничего не получите, код выполнится раньше, чем данные приедут (если они уже не были заказаны), надо будет в цикле пробовать получать, пока не появятся.
Иван Ру написал: По п.2. - по-сути нужен доступ к одному файлу в отдельной папке и только на чтение, не вижу ничего особо страшного
Проблема в том, что между тем, что администратор хотел сделать, и тем, что он по факту сделал, может быть неочевидный зазорчик, особенно при использовании стороннего софта. Самба и Петя, все такое. Но хозяин барин.
Что-то она не очень простая. Я б завел дешманский хостинг, поставил трехстрочный пхп, который проверяет юзер-агент post или даже get запроса и при его правильности (UUID например или хэш какой-нибудь) пишет тело запроса в файл. А другой примитивный пхп этот файл отдает на правильно сформированный запрос, а на неправильно сформированный не отдает ничего или, если не лень, какую-нибудь заглушку, бесполезный* лендинг, чтобы не будоражить кулхацкеров. И смотреть файл можно откуда угодно браузером или примитивной прогой.
* На практике у меня подобная штуковина (не для квика) на вполне себе полезном сайте стоит, для всех сайт как сайт, а для своего юзер-агента еще и апи.
На вопросы: 1. Путем поглядывания на монитор периодически. 2. Не знаю. Я б вообще поостерегся таких конфигураций, дыряво может получиться.
Андрей К написал: Увеличиллось в 3 раза потребление памяти, теперь памяти должно быть в 3 раза больше
Ну не совсем это корректно же. Диспетчер задач показывает рабочий набор процесса, который включает в себя и мэпы файлов. Как минимум, квик мэпит alltrade.dat, orders.dat, trades.dat, transresult.dat, а также и неочевидные (даже, возможно, разработчикам квика) системные файлы типа кэша шрифтов. Первый из перечисленных сам по себе гиг-полтора запросто может быть. Вот это все и создает большой объем видимый, при недостатке ОЗУ система начнет первым делом выгружать мэпы и ничего ужасного не случится.
Старатель написал: Если вы игрались со списками инструментов для заказа тиков, то да, такое может быть и в идеальном мире
Нет, не игрался в данном случае. Признаться, я не вижу в показанных скринах ничего криминального, это куски данных от разных board, они не обязаны быть упорядоченными. Вот если от одного такая каша поедет, это будет криминал уже. Скоро на фортсе распараллелят, будет и в пределах класса месиво.