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

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

Страницы: Пред. 1 2 3 4 5 6 7 8 9 10 След.
Горячие клавиши
 
Раз уж QPILE больше не развивается и его всё больше заменяет QLua, давайте перенесём комбинацию Ctrl+F11 с пункта меню "QPILE скрипты" на пункт меню "Lua скрипты". Полагаю, что пользователей, довольных этим нововведением, будет больше, чем недовольных, а реализация от разработчиков терминала практически не потребует усилий.
Один компьютер и несколько брокеров
 
Создаёте несколько папок типа
Код
D:\QUIK_BROKER1
D:\QUIK_BROKER2
D:\QUIK_BROKER3
В каждую из папок устанавливаете соответствующий дистрибутив программы, рекомендованный каждым из брокеров (версии могут быть разными в зависимости от брокера).

Пользуетесь терминалами независимо друг от друга, возможно одновременно.

Для старта этого достаточно. Если хочется одинаковые настройки в каждом из терминалов, придётся делать дополнительные действия и рисковать несовместимостью wnd-файлов настроек из-за разных версий терминалов.
Размеры окон, создаваемых скриптом
 
Это не сообщение о какой-то ошибке или проблеме, наоборот, это сообщение, которое может помочь программирующим на qlua скрипты роботов.

Допустим, что Ваш скрипт создаёт одно или несколько окон на своей вкладке. Если не прилагать усилий и просто создавать окна через CreateWindow, эти окна получают некоторый размер и местоположение, определяемые автоматически. Не всегда это удобно. Можно после создания указать конкретное местоположение и размеры окна с помощью функции SetWindowPos(tableId, x, y, dx, dy). Однако, откуда взять значения x, y, dx, dy? Их можно подбирать методом последовательных приближений, но ведь это неудобно!

Предлагается следующий подход. Сначала Вы располагаете графики, окна Вашего скрипта и прочие элементы так, чтобы было удобно. Потом запускаете предлагаемый ниже код. Он создаёт пустое окно, которое можно перемещать и изменять его размер с помощью мышки, накладывая это окно ровно поверх каждого окна Вашего скрипта. При этом в заголовке накладываемого окна динамически обновляются параметры x, y, dx, dy, которые нужно будет подставить в функцию SetWindowPos(tableId, x, y, dx, dy) в Вашем скрипте. При этом подбор параметров можно осуществить сразу, а не методом последовательных приближений.

Вот такой вот калибровщик положения и размеров окон получается.

Если я изобрёл велосипед, а все нормальные программисты пользуются подобными штуками, отнесусь к этому с пониманием.
Код
--
-- Подгонка размеров окна.
--

local interrupted = false

function OnStop()
    interrupted = true
end

function main()
    local tId = AllocTable()
    CreateWindow(tId)

    local topPrev, leftPrev, bottomPrev, rightPrev = 0, 0, 0, 0
    while not interrupted do
        if IsWindowClosed(tId) then
            break
        end
        local top, left, bottom, right = GetWindowRect(tId)
        if top == nil or left == nil or bottom == nil or right == nil then
            break
        end
        if topPrev ~= top or leftPrev ~= left or bottomPrev ~= bottom or rightPrev ~= right then
            SetWindowCaption(tId, "x=" .. tostring(left)
                    .. ",y=" .. tostring(top)
                    .. ",dx=" .. tostring(right - left)
                    .. ",dy=" .. tostring(bottom - top))
            topPrev = top
            leftPrev = left
            bottomPrev = bottom
            rightPrev = right
        else
            sleep(50)
        end
    end
end
Обращение к DataSource в main-потоке
 
Цитата
Делайте через ssort, работает стабильно.

Спасибо за подсказку!

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

Солидарен.
Обращение к DataSource в main-потоке
 
В принципе, ничего не мешает в каждом коллбэке написать проверку типа: если очередь на выполнение, пополняемая из потока main непуста, выполнить функции из неё. У этого подхода есть недостатки:
1) придётся написать в каждом коллбэке строчку, вызывающую работу с очередью функций;
2) если рыночных коллбэков не происходит (например, торги остановились), main не получит требуемый результат, хотя поток коллбэков свободен.
Обращение к DataSource в main-потоке
 
Просьба к разработчикам терминала обратить внимание на это сообщение и дать свои конструктивные комментарии.

Допустим, что у нас есть экземпляр DataSource, который содержит в себе 5-минутные свечки:
Код
local ds = CreateDataSource(classCode, secCode, INTERVAL_M5)

Если ds используется в потоке коллбэков, то есть гарантия, что пока в коде коллбэка идёт работа с этим экземпляром (например, итерирование по индексу от 1 до ds:Size()), данные внутри него (количество свечей, их high, low, close, volume) не меняются.

Вопрос в том, как добиться стабильности внутреннего состояния в main-потоке? Ведь если я запомню в переменной размер DataSource
Код
local size = ds:Size()
перед началом цикла, то в процессе итерирования могут как добавиться новые свечи, так и обновиться старые (скажем, сначала обновилась последняя свеча, а потом добавилась новая). При этом могут возникать неприятные эффекты типа в потоке main прочитали high последней свечи, потом поток коллбэков обновил свечу так, что новое значение close стало больше уже прочитанного значения high, а потом поток main увидел последнее значение close, которое больше прочитанного ранее high.

Не уверен, что будет происходить с содержимым DataSource при смене торговой сессии, скорее всего, ничего хорошего.

Чтобы гарантированно иметь консистентные данные, можно, например, использовать ds:SetUpdateCallback, в котором заранее производить копирование состояния ds или его изменений в другой объект, и складывать в очередь, разгребая которую из потока main до опустошения, можно всегда получить последнее консистентное состояние ds. Сейчас у меня реализован этот вариант, но кажется, что он излишне нагружает скрипт, т.к. свечки нужны в потоке main раз в 5 минут, а обновление свечей в потоке коллбэков идёт постоянно.

Не уверен, что у меня есть 100% рабочий рецепт получения консистентных данных из DataSource в потоке main, но можно пытаться делать многократное чтение данных, когда параметры каждой свечи с номером i читаются до тех пор, пока не окажется, что ds:Size() не изменился и ds:T(i), ..., ds:C(i) совпадают с прочитанными ранее, после чего полагаем, что свеча i актуальна и можно переходить к следующей.

В более сложных ситуациях подобного рода проблему полностью решил бы следующий подход, когда есть возможность запуска функции в потоке коллбэков с API типа следующего:
Код
ExecuteCallback(function() 
  -- обращение к данным ds, которое будет произведено в потоке коллбэков
end)

В языке программирования Java в GUI-приложениях на Swing аналогом является вызов
Код
SwingUtilities.invokeLater(Runnable doRun)

Вопросы/пожелания к разработчикам:
1) рассмотреть возможность введения подобной возможности в терминал;
2) либо отказать, либо реализовать в сжатые сроки.
Последняя доступная версия QUIK
 
Терминал 7.16.3.14: ftp://ftp.quik.ru/public/updates/7.16/quik_7.16.3_upd.zip
Разные бары в QUIK и на сайте биржи (MOEX) на фьючерсах на таймфрейме D1.
 
и самое главное, что делать?

Главное -- понять, что дневная свеча по фьючерсу на Мосбирже строится с 19:00 (вечерняя торговая сессия) до 18:45 следующего дня, и чем это отличается от терминала (с 10:00 по 23:50 в течение суток).
QUIK виснет из-за Таблица изменений параметров
 
У меня такая же фигня. Если в этой таблице установить курсор на первую строку, то всё нормально. Если же смотреть на последние строки, то получается как у Вас. Я как-то видео этого безобразия  записывал и разработчикам отсылал. Только они ничего поделать не смогли.

Если по теме, то кажется, что с рендерингом этой таблицы истории изменения параметров какие-то реальные проблемы.
CreateDataSource, не грузятся данные при формир. через CreateDataSource
 
Логика ожидания полученных данных из ds (объект datasource, для которого был успешен вызов CreateDataSource), но не более timeout секунд, может быть примерно такая:
Код
local function init(ds, timeout)
  local deadline = os.time() + timeout
  while os.time() < deadline do
    if ds:Size() > 0 then
      return true
    end
    sleep(100)
  end
  return false
end
Если функция вернула false, значит что-то пошло не так. Таймаут устанавливается пользователем. Я обычно ставлю 15 секунд.
Заявки не были исполнены по непонятной причине, ошибка в работе демо-версии
 
Форум как-то неинтуитивно реализован, поэтому часто очень забавные скриншоты получаются.  :lol:

Наверное, в диалоговое окно "Вставить изображение" надо сразу кнопку "Прочитать справку, чтобы не накосячить" добавить.
Ошибка после обновление Windows, Как исправить ошибку , после обновления системы Windows
 
Если не хватило памяти под объекты, значит надо чаще терминал перезагружать. Не может он справиться с большим объёмом данных и/или внутренние ошибки происходят.

Разработчикам пора в дистрибутив терминала включить вот такой bat-файл, чтобы простыню из нескольких пунктов про то, что нужно удалить, не писать.
Код
del /F /Q acnt.dat
del /F /Q alerts.dat
del /F /Q alltrade.dat
del /F /Q banners.dat
del /F /Q classes.dat
del /F /Q firms.dat
del /F /Q limits.dat
del /F /Q locales.dat
del /F /Q orders.dat
del /F /Q par.dat
del /F /Q portfolio.dat
del /F /Q scripts.dat
del /F /Q search.dat
del /F /Q sec.dat
del /F /Q tmsg.dat
del /F /Q tradermsg.dat
del /F /Q trades.dat
del /F /Q trans.dat
del /F /Q transresult.dat

del /F /Q info.log
del /F /Q portfolio.log

info.exe -clear
Ошибка при чтении стакана
 
Ещё (у меня очень редко) бывает, что терминал глючит и тогда корректный lua-код начинает работать некорректно. Ощущение, что при долгой или интенсивной работе терминала изредка происходят какие-то внутренние ошибки, после чего ссылки на некоторые функции и поля таблиц портятся. Чтобы этого избежать, перезапускаю терминал раз в 2-3 дня.

Надеюсь, что в Вашем случае это, всё-таки, ошибка программиста, и можно это исправить. Попробуйте переписать код так, чтобы не было вот таких фрагментов:
Код
value.tbl.bid[indexBid].price
а были примерно такие:
Код
local tbl = value.tbl
local bids = tbl.bid
local price = bids[indexBid].price
Это позволит локализовать ошибку и избавит от многократных обращений к таблицам (см. повторяющиеся фрагменты типа value.tbl.bid, это, к тому же, замедляет код).

Также, если indexBid равен 0 или nil, то стакан частично или полностью пустой.

А зачем Вам "дальний край" стакана value.tbl.bid[indexBid].price ? Обычно value.tbl.bid[1].price более важное значение.
Ошибка при чтении стакана
 
В lua есть 2 функции, pcall и xpcall, для перехвата ошибок, которые могут возникнуть при исполнении кода. Посмотрите в документации к языку lua. Например, здесь http://www.lua.ru/doc/5.1.html даётся описание обеих этих функций.
Последняя доступная версия QUIK
 
Разработчики, почему-то, пропустили версию 7.15.

Терминал 7.16.1: ftp://ftp.quik.ru/public/updates/7.16/quik_7.16.1_upd.zip
OnTransReply status, Какие статусы нетерминальные?
 
Я делаю так: если в результате sendTransaction получается результат "", считаем, что транзакция отправлена, будем ждать для неё OnTransReply и OnOrder, иначе рапортуем об ошибке и думаем, что делать дальше (для лимитной заявки слать/не слать новую, для kill-заявки пытаться/не пытаться ещё раз послать kill-заявку).

Когда приходит OnTransReply() / OnOrder(), то разбираемся, что произошло и модифицируем состояние системы. Там логика сложная и в ссылке как-то описана.

Мне сильно помог такой подход: предполагать, что подавляющее большинство транзакций отправлены и обработаны без проблем, а там, где возникли какие-то ошибки, работают "заплатки", разбирающиеся с частными патологиями. Тут всё (OnOrder(), OnTrade() и OnTransReply()) надо использовать.

Реально в коде используется проверка статусов 3, 4, 5 и 13.
OnTransReply status, Какие статусы нетерминальные?
 
> если sendTransaction() возвратил непустую строку, то ошибка, и вызова OnTransReply() не будет.

Вызова OnTransReply() не будет.

> «0», «1» и «15» являются нетерминальными статусами, то есть после их получения будет еще вызов OnTransReply() с другим статусом - так?

Коллбэк OnTransReply() вызывается только один раз. Очень редко, при ошибках сети/сервера/терминала, OnTransReply() может не придти.

https://forum.quik.ru/messages/forum10/message11805/topic940/#message11805
Ошибка в контекстном меню, quik 7.14.1.7
 
У себя проверил. Действительно, надпись "Alt+F4" вместо стандартного для Windows-программ "Ctrl+F4" для закрытия внутренних окон приложения.
Цитата
Можно скриншот, на котором видна проблема?

Вам же русским понятным языком написали о проблеме, которую элементарно воспроизвести.
Отработка OnOrder после остановки скрипта
 
Цитата
nero333 написал:
_sk_ , а сможете ли вы запустить скрипт из другого потока и, если да, то каким образом?
Скрипт -- это некий код, часть из которого исполняется в main-потоке, а часть в потоке коллбэков. Запускается скрипт кнопкой "Запустить". После этого начинает выполняться код main() и время от времени будут вызываться коллбэки. Фраза "запустить скрипт из другого потока" кажется некорректной.
Ошибка при переподключении к серверу брокера
 
финамовец, Вам уже пора в командировку съездить в Новосибирск к разработчикам ARQA вместе со своим компьютером. Как вариант -- дать разработчикам доступ через TeamViewer, чтобы они сами всё видели, что Вы видите своими глазами.
Отработка OnOrder после остановки скрипта
 
Цитата
Sergey Gorokhov написал:
Цитата
nero333   написал:
_sk_, спасибо, это хорошая идея, думаю реализовать что-то подобное. Вопрос был к разработчикам относительно кнопки "Остановить", аварийный выход - это всё-таки когда скрипт падает с выводом ошибки в поле "Ошибки выполнения скрипта".
Кнопка "Остановить" это не аварийный выход, а просто остановка скрипта.
Принудительная (в Вашем термине "аварийная") остановка происходит не по нажатию кнопки, а по истечении таймаута 5 сек.
И это не зависит от того что в это время делает main, что-бы Вы туда не написали скрипт принудительно завершится.
Таймаут можно изменить, это делается в return события OnStop (см документацию QLUA.chm)
Если Вам что-то нужно снять заявки перед остановкой скрипта, делайте это в самом OnStop
OnStop -- это последний коллбэк, который будет вызван при остановке скрипта. Однако, чтобы корректно сделать всё, что необходимо для снятия отправленных заявок в общем случае, не получится. Например, если транзакция на постановку заявки отправлена, OnTransReply ещё не пришёл, а пришёл OnStop. Как снять заявку, если мы ещё не знаем и не узнаем её orderNum? Никак.

Кроме того, в OnStop делать завершение неудобно, т.к. логика обработки находится в main-потоке.

Именно поэтому нормальная практика прерывания потока в многопоточном программировании состоит в уведомлении другого потока о том, что надо завершить работу. Эта практика и была предложена.
Отработка OnOrder после остановки скрипта
 
Цитата
nero333 написал:
Он не остановит работу, ведь main продолжает работать. Что вы посоветуете сделать, как выйти из main-a только удостоверившись, что все заявки сняты (а это можно сделать только по результатам колбека OnOrder)?
У меня используется следующая схема. Скрипт создаёт окно, где отображается информация о его работе (позиции, прибыли/убытки и др.). Если его закрывают нажатием на крестик в правом верхнем углу окна, то скрипт понимает, что окно закрыто (IsWindowClosed(windowId) == true), поднимает флаг, аналогичный Вашему IS_STOPPING, снимает необходимые заявки, закрывает файлы, в которые шла запись и т.п., после чего завершает исполнение функции main. Получается, что использование крестика в правом верхнем углу окна -- это штатный выход из скрипта, а нажатие кнопки "Остановить" в окне скриптов -- аварийный выход.
Проблема с уровнями Фибоначчи
 
Не уверен, что после закрытия и открытия терминала проблема с графиками останется. Если останется, то вышлю архив терминала.
Синхронизация между потоком main и потоком, вызывающим OnXxx
 
Когда ещё был старый форум, там это обсуждалось. Пусть кто-нибудь из представителей ARQA дальше по теме видимости изменения переменных отвечает (даёт ссылку на соответствующее обсуждение или заново тут ответит).

Приведённый мною код работает с конца 2013 года без каких-либо проблем.
Цитата
Моя блокировка отличается от такой блокировке только тем, что разблокировка происходит
по уведомлению из другого треда напрямую непосредственно в момент, когда нужно произвести действия.

Конечно, так и надо делать. Только в стандартном Lua для этого нет средств, а в QLua, наверное, через sinsert как-то можно извратиться и реализовать Lock. На практике же повелось так, что в main-потоке большинство пишет цикл, совершающий нужные проверки/действия и засыпающий, если это надо/есть возможность.
Синхронизация между потоком main и потоком, вызывающим OnXxx
 
Код написан с учетом Ваших опасений
Цитата
В коде выше чтение и запись в submit/get не синхронизированы. Что  случится, если вызов будет произведен одновременно на двух родных  потоках (мейн и колбек)?
Например, колбек вызовет submit, который уже модифицирует очередь  при присвеоении, но еще не завершит операцию, а get уже начнет из нее  читать?

submit меняет только tail, get меняет только head. И указатели двигаются только в те моменты, когда структура готова. За видимость переменных из разных потоков разработчики QLua уже подумали.
Цитата
Все же, хотелось бы избежать копирования всего и вся из коллбеков в очередь.

Передавайте только те данные, которые нужны. Полагаю, что если использовать что-то блокирующее, у Вас производительность понизится.

Как эвристику можно использовать следующее наблюдение: если при чтении из очереди она оказалась пуста, можно поставить sleep с аргументом побольше, если же непуста, то вообще не вызывать sleep.

Если очередь разгребается быстрее, чем пополняется, то в памяти растёт только массив, на базе которого реализована очередь. Этот  массив занимает в памяти относительно небольшой размер, а перезапуск скрипта, который происходит раз в несколько дней, приводит к старту с малого размера массива.
Проблема с уровнями Фибоначчи
 
Наблюдаю проблему в терминале 7.14.1.7 уже второй раз.

Строим графики цен нескольких инструментов в одном окне на низком таймфрейме (5 мин, например). Накладываем уровни Фибоначчи на график одной из цен. Ждём некоторое время, пока появляются новые свечи и график не сдвинется так, что уже не видно тех точек, по которым уровни Фибоначчи были построен. У меня обычно это наступает на следующий день после построения уровней. Возможно, надо чтобы был рестарт сервера, когда графики исчезают, а потом снова появляются.

В результате видим вот такие два графика. Первый -- это если проскроллировать график цен в прошлое, чтобы были видны точки, по которым строились уровни, а второй -- если проскроллировать график цен обратно. Когда большая свеча уходит из окна, график цен меняет свой масштаб по вертикали и при этом уровни уносит чёрт знает куда.

Первый график:


Второй график:

Наверное, надо такое чинить.
Синхронизация между потоком main и потоком, вызывающим OnXxx
 
Один из вариантов кардинально решить проблему многопоточности при программировании на QLua описан ниже.

В потоке main делаем всю логику торгового робота, а из потока коллбэков только передаём данные в поток main через очередь. Очередь решает задачу синхронизации, коллбэки завершают свою работу максимально быстро, не тормозя UI терминала.

Реализация очереди функций на базе массива позволяет в потоке коллбэков указать, какие данные нужно использовать, и как именно. При получении функции в потоке main остаётся лишь запустить её.
Код
--
-- Реализация очереди из функций и их исполнения.
--

local Executor = {}

--- Конструктор.
-- @param self объект
local function new(self)
    local queue = {
        head = 1,
        tail = 0
    }
    setmetatable(queue, self)
    self.__index = self
    return queue
end

Executor.new = new

--- Поместить функцию в очередь на выполнение.
-- @param self объект
-- @param f функция
local function submit(self, f)
    if type(f) == "function" then
        self[self.tail + 1] = f
        self.tail = self.tail + 1
    end
end

Executor.submit = submit

--- Получить очередную функцию из очереди.
-- @param self объект
-- @return функция
local function get(self)
    if self.head > self.tail then
        return nil
    else
        local f = self[self.head]
        self[self.head] = nil
        self.head = self.head + 1
        return f
    end
end

Executor.get = get

--- Выполнять функции из очереди либо пока они там есть, либо пока не будет выполнено указанное количество функций.
-- @param self объект
-- @param max максимальное количество исполняемых за один раз функций
local function execute(self, max)
    max = max or 1000000
    while max > 0 do
        local f = self:get()
        if f == nil then
            return
        else
            f()
            max = max - 1
        end
    end
end

Executor.execute = execute

return Executor

Используется это примерно так.
Код
local tradeCounters = {} -- таблица[secCode], содержащая количество обезличенных сделок по каждому инструменту

В потоке коллбэков пишем, например:
Код
function OnAllTrade(t)
    executor:submit(function()
            tradeCounters[t.sec_code] = (tradeCounters[t.sec_code] or 0) + 1
    end)
end

В потоке main пишем цикл, достаточно часто вызывающий функцию execute, т.е. что-то типа:
Код
while not interrupted do
    ....
    executor:execute()
    ....
end
В результате в потоке main выполнится функция, которую мы задали в потоке коллбэков с данными, которые в тот момент были доступны.

Удачи!
Новый расчет комиссии биржи
 
Готовы зарегистрировать пожелание по доработке для трансляции точной комиссии, просьба уточнить необходимость данной доработки.

Зарегистрировать нужно обязательно и реализовать как можно быстрее, пожалуйста.
Новый расчет комиссии биржи
 
Обновление терминала до 7.14.1.7 ничего не изменило. Ждём ответа от разработчиков терминала.
Последняя доступная версия QUIK
 
Терминал 7.14.1.7: ftp://ftp.quik.ru/public/updates/7.14/quik_7.14.1_upd.zip
Новый расчет комиссии биржи
 
Посмотрел комиссию по SRZ7. Сейчас терминал 7.12.1.10 пишет комиссию 1.22 руб, на сайте 1.18 руб.
Новый расчет комиссии биржи
 
Цитата
ISR написал:
Цитата
_sk_   написал:
Где правда?
Не знаю, у меня в 7.14.1.7 для SRZ7 (сбер) совпадает с рассчитанной и с сайтом = 0.59.
По SRZ7 у меня тоже совпадает. Я писал про SiZ7.

В отчёте от биржи за вчерашний день комиссия за сделку по SiZ7 указана 0.82 руб. В терминале (создать окно -> сделки -> редактировать таблицу + добавить столбцы про комиссию) видим 0.91 руб с утра и 0.92 руб во второй половине дня. В торговых роботах из коллбэков OnTrade приходит комиссия 0.91/0.92 руб.

Настоятельная просьба к разработчикам терминала оперативно пояснить, какая комиссия по SiZ7 правильная? Если проблема в терминале/сервере -- укажите. Если проблема в том, что биржа так транслирует данные -- тоже укажите.

Несоответствие данных -- это критичная ошибка.
Новый расчет комиссии биржи
 
Сейчас терминал (7.12) транслирует комиссию по SiZ7 равную 0.91 руб/контракт, а на сайте биржи указано, что должна быть 0.82 руб/контракт. Где правда? Это биржа так транслирует данные?
Последняя доступная версия QUIK
 
Терминал 7.14: ftp://ftp.quik.ru/public/updates/7.14/quik_7.14.0_upd.zip
Номера сделок идут не в соответствии со временем сделок
 
Прикольная ошибка. Время должно быть 195911.999640. Похоже, что из-за округления такое произошло. Кто виноват, биржа или терминал, неясно.
Последняя доступная версия QUIK
 
Терминал 7.13: ftp://ftp.quik.ru/public/updates/7.13/quik_7.13.0_upd.zip
Насколько уникален order_num?
 
Если торгуете на Московской бирже, то class_code + order_num уникальная комбинация.
Ошибка not enough memory, сегодня скрипт впервые упал с такой ошибкой -- как выявить причину?
 
Очень хочется, чтобы хоть у кого-то получилось понять, как гарантированно воспроизвести проблемы, подобные описанным выше. У меня не получилось, хотя я даже некий скрипт специально писал и отправлял разработчикам для тестов. Пока не будет чёткого алгоритма воспроизведения проблемы разработчики нам вряд ли помогут, к сожалению.
Ошибка not enough memory, сегодня скрипт впервые упал с такой ошибкой -- как выявить причину?
 
Цитата
Отключение тиковых графиков проблему не решает, а вот отключение  трансляции обезличенных сделок -- по первым ощущения ее устраняет. Мне  они категорически нужны, не понимаю что делать.

Похоже, что есть некоторые ошибки в терминале, которые проявляются только под нагрузкой (и, может быть, только в некоторые дни, скажем, связанные с экспирацией или ещё какими-то событиями). Трансляция обезличенных сделок таковой является.

Для минимизации вероятности проблем можно перезапускать терминал каждый день или через день.

Конечно, хотелось бы, чтобы разработчики пофиксили причину, поскольку регулярный перезапуск терминала делать неудобно.
Подсобите с битовыми флагами на примере выяснения позиции из таблицы OnTrade( )?
 
Если посмотреть внимательно на вопрос, то станет ясно, что он был об обезличенных сделках (OnAllTrade), а не о сделках пользователя терминала (OnTrade).

Не знаю, что надо делать с мордами невнимательных комментаторов.

Отдельные биты, как я понимаю, были сделаны разработчиками терминала из-за того, что в обезличенных  сделках, представляющих собой данные по индексам, оба бита нулевые.
Подсобите с битовыми флагами на примере выяснения позиции из таблицы OnTrade( )?
 
Код
local SELL_FLAG = 1
local BUY_FLAG = 2

function OnAllTrade(allTrade)
    ...
    local buySell = 0
    if bit.band(currTrade.flags, BUY_FLAG) == BUY_FLAG then
        buySell = 1
    elseif bit.band(currTrade.flags, SELL_FLAG) == SELL_FLAG then
        buySell = -1
    end
    ...
end
Ошибка not enough memory, сегодня скрипт впервые упал с такой ошибкой -- как выявить причину?
 
Стандартная схема работы виртуальных машин:
1) выделяем какой-то объём памяти для работы;
2) работаем, периодически вызывая сборщик мусора (мелкая гребёнка);
3) если после сборки мусора осталось мало свободной памяти, выделяем больше памяти (периодическое повышение объёма) и продолжаем работать с пункта 2).
Продвинутые виртуальные машины умеют уменьшать объём выделенной памяти, если потребность в ней снизилась. Похоже, что виртуальная машина lua к таким не относится.
Удаление элементов в больших таблицах., Крайне медленная работа table.remove и возможные обходные пути для быстрого удаления большого числа элементов крупных массивов/таблиц.
 
Судя по написанному, Вам нужно реализовать в своём скрипте циклический буфер (кольцевой буфер) на базе массиве.

https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BB%D1%8C%D1%86%D0%B5%D0%B2%D0%BE%D0­%B9_%D0%B1%D1%83%D1...

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

Пример реализации на lua (не ручаюсь за качество): https://gist.github.com/johndgiese/3e1c6d6e0535d4536692
Ошибка not enough memory, сегодня скрипт впервые упал с такой ошибкой -- как выявить причину?
 
Упс, цитаты забыл поставить, а форум не даёт редактировать своё сообщение.
Ошибка not enough memory, сегодня скрипт впервые упал с такой ошибкой -- как выявить причину?
 
Я думал  collectgarbage()  оценивает память используемую всем терминалом, я не прав?

Нет, это память, используемая lua-машиной отдельного скрипта.

Я так понимаю, Вы вызываете сборщик мусора в цикле вложенным в main  используя счетчик времени или используете setpause"и setstepmul. Можете  привести элемент кода с этой операцией?

Создаём файл Timer.lua примерно такого содержания:
Код
--
-- Реализация таймера.
--
-- Пример использования:
-- local Timer = require("util.Timer")
-- local timer = Timer:new()
-- timer:setInterval(10)
-- ...
-- if timer:isTimeout() then ...
--

local Timer = {}

--- Конструктор.
-- @param self объект
local function new(self)
    local timer = {
        deadline = os.time()
    }
    setmetatable(timer, self)
    self.__index = self
    return timer
end

Timer.new = new

--- Задать интервал, по прошествии которого считается, что таймер сработал.
-- @param self объект
-- @param duration число секунд, через которое должен сработать таймер.
local function setInterval(self, duration)
    self.deadline = os.time() + duration
end

Timer.setInterval = setInterval

--- Задать момент времени, по прошествии которого считается, что таймер сработал.
-- @param self объект
-- @param date таблица, задающая дату, когда должен сработать таймер.
local function setDate(self, date)
    self.deadline = os.time(date)
end

Timer.setDate = setDate

--- Узнать, через сколько секунд осталось до момента срабатывания таймера.
-- @param self объект
-- @return количество секунд оставшееся до срабатывания таймера или 0, если время срабатывания прошло
local function getSecondsLeft(self)
    return math.max(0, self.deadline - os.time())
end

Timer.getSecondsLeft = getSecondsLeft

--- Узнать, наступил ли момент срабатывания таймера.
-- @param self объект
-- @return true/false
local function isTimeout(self)
    return os.time() >= self.deadline
end

Timer.isTimeout = isTimeout

return Timer

Используется примерно так:
Код
local function printMemoryUsed()
    logger:debug("Memory used: " .. math.ceil(collectgarbage("count") / 1024) .. "M")
end

local function run()
    while not interrupted do
        ...
        if garbageTimer:isTimeout() then
            printMemoryUsed()
            logger:debug("Collecting garbage...")
            collectgarbage()
            printMemoryUsed()
            garbageTimer:setInterval(600)
        end
        ...
    end
end

function main()
    ...
    run()
    ...
end
Ошибка not enough memory, сегодня скрипт впервые упал с такой ошибкой -- как выявить причину?
 
Цитата
Ребят, вы поймите, квик - 32х битный процесс, он не может использовать больше 4гб от слова никак.
И ему без разницы 16 у тебя или 32 гб рам.

Про ограничение 4Гб я в курсе (https://forum.quik.ru/messages/forum1/message25429/topic2913/#message25429). Реально там даже меньше.
Цитата
Чтобы исчерпать всю память надо написать очень плохой скрипт.

Или использовать один терминал для интенсивной торговли по большому количеству счетов и инструментов. По-хорошему, надо переходить на что-то более адекватное, но пока (из-за дешевизны решения) приходится мириться с недостатками терминала.
Ошибка not enough memory, сегодня скрипт впервые упал с такой ошибкой -- как выявить причину?
 
У меня компьютер аналогичный, только памяти 16 Гб и так было несколько раз при запуске нескольких скриптов сразу.
Цитата
1. Подскажите, какова возможная причина проблемы?
2. У кого были похожие ситуации, с чем они связаны и как удалось избавиться от проблем?

Виртуальным Lua-машинам не хватает памяти. Например, сборщик мусора не успевает справляться или есть какая-то утечка памяти в скриптах. Иногда это из-за внутренних ошибок терминала.

Лучший вариант по надёжности -- это перезапускать терминал перед началом торгов (после смены торговой сессии), раз в 5-15 минут в каждом скрипте вызывать collectgarbage() для сборки мусора.
Цитата
3. Как самостоятельно попытаться идентифицировать источник проблемы  и оптимизировать код?  
4. Есть ли возможность использовать для LUA какие-либо программы отладки, которые анализируют.

Программы для отладки мне неизвестны. Можно периодически писать в лог потребление памяти каждым скриптом (функция collectgarbage("count") выдаёт количество выделенной памяти в килобайтах) до сборки мусора и после неё. Так, возможно, поймёте, в чём проблема.
Сделка RIU7 2017-07-11 23:50:00.000
 
Почему-то не видно комментариев разработчиков терминала. Несоответствие объёма в свече и суммарного объёма по сделкам этой свечи кажется критичным багом.
Сделка RIU7 2017-07-11 23:50:00.000
 
В таблице всех сделок наблюдаю, что во время вчерашней вечерней сессии прошла последняя сделка по RIU7 объёмом 1 контракт:
Цитата
1823763950,23:50:00,RIU7,МБ Деривативы: Фьючерсы,RIU7,99730,0.00,1,121514.02,,,0,,,T1,B
Пусть на совести биржи останется тот факт, что сделка прошла ровно в момент 23:50. Однако, вопрос к разработчикам терминала: почему на графике RIU7 свечка, начинающаяся в 23:50, имеет объём 2, когда в сделке был объём 1?

Где правда?  :wink:

Если серьёзно, то это ошибка терминала, ведь свечи строит терминал, а не биржа.
Пределы терминала QUIK (память, количество вкладок, графиков, lua-скриптов)
 
Цитата
Для диагностики, более детального разбора все таки потребуется ваше  рабочее место QUIK, без ключей доступа и файла chm. Это ускорит решение  проблемы.

Как уже было указано выше, боевую систему, понятное дело, прислать нет возможности. Оправил электронной почтой стенд для тестирования.
Страницы: Пред. 1 2 3 4 5 6 7 8 9 10 След.
Наверх