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

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

Страницы: 1 2 3 4 5 6 7 8 9 10 11 ... 27 След.
Работа OnClose
 
Есть колбек OnClose. Казалось бы, он должен помочь понять, что терминал остановлен. Но явно что-то пошло не так.

Берем простой скрипт. Закрываем терминал через "крестик".

Ожидание - 1. OnClose, сбрасываем флаг. 2. выходим из main.
Код
local sleep  = _G.sleep
local isRun  = true
local AddLabel          = _G.AddLabel
local GetLabelParams    = _G.GetLabelParams
local logFile

local function log_tostring(...)
    local n = select('#', ...)
    if n == 1 then
    return tostring(select(1, ...))
    end
    local t = {}
    for i = 1, n do
    t[#t + 1] = tostring((select(i, ...)))
    end
    return table.concat(t, " ")
end

local function log(...)
    if logFile==nil then return end
    logFile:write(tostring(os.date("%c",os.time())).." "..log_tostring(...).."\n");
    logFile:flush();
end

function _G.OnStop()
    isRun = false
    log("Script Stoped")
    if logFile then logFile:close() end
end

function _G.OnClose()
    isRun = false
    log("Script OnClose")
    if logFile then logFile:close() end
end

function _G.main()

    logFile = io.open(_G.getScriptPath().."\\labels_test.txt", "w")

    local t_id = _G.AllocTable()
    _G.AddColumn(t_id, 1, 'test', true, _G.QTABLE_STRING_TYPE, 20)
    _G.CreateWindow(t_id)

    local tag = 'virt_test'
    local label_params = {}
    label_params.YVALUE = 324
    label_params.TEXT = 'TEST    |||||||||||||||||||||||||||||||||||||||||||||'
    label_params.HINT = 'Еще текст'
    label_params.DATE = 20260512
    label_params.TIME = 135000
    label_params.FONT_FACE_NAME = 'Arial'
    label_params.ALIGNMENT = 'RIGHT'
    label_params.FONT_HEIGHT    = 10
    label_params.TRANSPARENT_BACKGROUND    = 1
    local data = {price = 324}
    local l_id = AddLabel(tag, label_params)
    sleep(1000)
    
    while isRun do
        local i = 1
        while isRun and i < 10 do
            label_params = GetLabelParams(tag, l_id)
            if label_params then
                data.price = tonumber(label_params.yvalue) or 0
            end
            log(os.clock(), i, 'IsWindowClosed', tostring(_G.IsWindowClosed(t_id)), 'label_params', tostring(label_params), tag, 'l_id', l_id, tostring(data.price))
            i = i+1
        end
        log(os.clock(), 'sleep')
        sleep(100)
    end
end

Выводит метку на график, создаём окно. Далее выводим данные метки с графика и закрыто ли окно. Смотрим лог:

Tue May 12 15:07:59 2026 30.832 sleep
Tue May 12 15:07:59 2026 30.946 1 IsWindowClosed false label_params table: 00000205F30168A0 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.947 2 IsWindowClosed false label_params table: 00000205F3016BA0 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.947 3 IsWindowClosed false label_params table: 00000205F3017BA0 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.947 4 IsWindowClosed false label_params table: 00000205F3017160 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.947 5 IsWindowClosed false label_params table: 00000205F3018020 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.947 6 IsWindowClosed false label_params table: 00000205F30171A0 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.947 7 IsWindowClosed false label_params table: 00000205F30171E0 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.947 8 IsWindowClosed false label_params table: 00000205F3017F20 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.948 9 IsWindowClosed false label_params table: 00000205F3017A60 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.948 sleep

Окно ещё не уничтожено, но графика уже нет и данные метки не получены.
Tue May 12 15:07:59 2026 31.061 1 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 2 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 3 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 4 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 5 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 6 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 7 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 8 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 9 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 sleep

А здесь уже и окна нет
Tue May 12 15:08:00 2026 31.173 1 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 2 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 3 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 4 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 5 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 6 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 7 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 8 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 9 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 sleep

Только сейчас OnClose
Tue May 12 15:08:00 2026 Script OnClose

Сама по себе схема, вроде, корректна, если бы OnClose мог выполнится параллельно, не обращая внимания на работу main. Но это не так. В итоге OnClose вызывается когда уже уничтожено окно скрипта и нет графика. Т.е. некоторое время (а точнее пока не вызовется C функция) у нас есть подвешенное состояние - мы не знаем окно, график закрыты пользователем или нет.
В итоге, если в это время считаем метку, а её нет, можем принять не верное решение. Аналогично и по окну скрипта.

Что хотелось бы: вместо колбека иметь глобальный флаг, состояние или иное, сигнализирующее, что терминал закрывается. При этом он должен быть установлен быстро, перед уничтожением объектов терминала. Аналогия из электротехники - логическое 1 или 0 на контакте. Если 0, то уже всё, логика работы совершенно иная.

Текущая же реализация может работать, если бы OnClose вызывался до уничтожения объектов.
Робот, торгующий опционами
 
Цитата
Сергей Че написал:

А вот и нет. Шаг цены фьючерса на нефть = $0.01. Лотность фьючерса = 10. А страйки идут с шагом $1.
Да. Но не забывайте про округление до "красивых чисел" для шага страйка. Впрочем, как писал, в теории ничто не мешает ему быть дробным. Здесь уже, видимо, как сама биржа решает. С целыми числами банально проще работать и могут решить, что не стоит и усложнять.
Робот, торгующий опционами
 
Цитата
Сергей Че написал:
Цена фьючерса на нефть имеет шаг 0.01 (то есть 0.01$, так как цена измеряется в $).
Но опцион на фьючерс на нефть имеет шаг 1$, то есть в 100 раз больший, чем шаг БА (базовый актив).
Вопрос. Шаг опциона - это всегда целое число или оно может быть дробным, как шаг его БА?
Исходя из спецификации кодировки страйка, там число = цена БА * Лотность.

Для опционов на фьючерсные контракты в поле "страйк" указывается котировка базового актива (котировка фьючерсного контракта). В свою очередь, котировка фьючерсного контракта – это произведение цены базового актива фьючерса на размер лота фьючерса.

Лотность обычно приведёт его к целому числу. Но в теории, может быть и дробное. У нас на бирже таких вроде нет, т.к. лотность перекрывает точность цены. Шаг же страйка имеет ещё округление в формуле, т.е. тоже не даёт дробных.
Робот, торгующий опционами
 
Вопрос был о другом: Как программно узнать текущую цену (премию) опциона?

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

Если задача просто узнать сколько можно купить продать по текущей цене, то для этого есть методы в QLUA: CalcBuySell, getBuySellInfoEx (см. документацию по ним).

Если же задача найти неэффективности, то уже необходимо самому считать цену на базе своей модели. Например, ММВБ считает по формуле Блэка-Шоулза. Поэтому рассчитав по IV свою цену можно будет увидеть неэффективность и принять решение. Но это для покупателей опционов.

Продавцы же платят ГО. И здесь уже всё сложнее - расчет гарантийного обеспечения (ГО) по опционам осуществляется по методике, аналогичной системе SPAN (Standard Portfolio Analysis of Risk)

Спросим любой чат:

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

Для начала важно отметить: по купленным опционам ГО не списывается (уплачивается только премия). ГО взимается только с продавцов опционов.

Ниже приведена логика и аналитические формулы расчета.

1. Концептуальная формула (для одной короткой позиции)

Математически гарантийное обеспечение по короткой позиции по опциону равно максимальной стоимости этого опциона в стрессовых сценариях:

ГОshort​=max(V1​,V2​,...,Vn​)   где Vi​  — теоретическая стоимость опциона в i -м сценарии риска.

На практике Клиринговый центр (КЦ) Мосбиржи разделяет это ГО на две составляющие: Премиальную маржу (ПМ) и Рисковую маржу (РМ).  

Формула выглядит так:  

ГО=ПМ+РМ  

  • Премиальная маржа (ПМ) — это текущая рыночная (или теоретическая) стоимость опциона. То, что вы уже должны рынку, если бы позицию нужно было закрыть прямо сейчас. ПМ=V0​  (где V0​  — текущая стоимость опциона).
  • Рисковая маржа (РМ) — это резерв на случай неблагоприятного изменения рынка до следующего клиринга. РМ=max(Vi​)−V0​   Если подставить это в формулу, получим:  ГО=V0​+(max(Vi​)−V0​)=max(Vi​)
2. Как строятся сценарии (Vi​ )?

Чтобы рассчитать

max(Vi​) , Мосбиржа генерирует сценарии изменения цены и волатильности базового актива (фьючерса).  

Для этого рассчитываются интервалы риска:

  1. Интервал риска по цене (IR) — насколько может упасть/вырасти фьючерс. IR=F0​×RF​      где F0​  — текущая цена фьючерса, RF​  — ставка риска по фьючерсу (зависит от актива, например, 8-12% для валют, больше для акций).
  2. Интервал риска по волатильности (IV) — насколько может измениться подразумеваемая волатильность. IV=σ0​×RV​      где σ0​  — текущая волатильность, RV​  — ставка риска по волатильности.

Затем КЦ Мосбиржи моделирует до 16 (и более) сценариев, сдвигая цену фьючерса на доли интервала

IR  (например, +1/3IR , −2/3IR , +IR , −IR ) и волатильность на +IV , −IV  или 0 . В каждом сценарии по формуле Блэка-Шоулза (модифицированной для фьючерсов) считается новая цена опциона Vi​ .

3. Формула для портфеля (Базовое ГО)

В реальности у вас может быть купленный пут, проданный колл и купленный фьючерс. ГО портфеля не равно сумме ГО отдельных инструментов.

Для портфеля рассчитывается Базовое гарантийное обеспечение (БГО):

БГО=max(L1​,L2​,...,Ln​)   где Li​  — совокупный убыток всего портфеля по одному базовому активу в i -м сценарии.

Убыток в сценарии считается как изменение стоимости портфеля:  

Li​=∑k​(Vi,k​−V0,k​)×qk​  где qk​  — количество k -го инструмента (со знаком: минус для коротких, плюс для длинных).

Благодаря этому подходу риски взаимно зачитываются. Например, если вы продали опцион Call (большой риск роста), но купили фьючерс (даст прибыль при росте), ГО портфеля будет значительно меньше, чем ГО просто по проданному Call.

4. Итоговое ГО с учетом спредов

После расчета Базового ГО, КЦ применяет скидки за межтоварные спреды (если у вас позиции по коррелируемым активам, например, фьючерсы на акции Сбера и ВТБ) и минимальное ГО.

Итоговая формула:  

ГОитог​=БГО−Скидкаспреды​   При этом действует жесткое ограничение: ГО не может быть меньше минимальной маржи (обычно это половина от Базового ГО или фиксированная сумма в зависимости от типа спреда).

Резюме: где посмотреть точные параметры?

Аналитически посчитать ГО дома на коленке сложно, так как постоянно меняются:

  1. Ставки риска RF​  и RV​  (КЦ меняет их при изменении волатильности на рынке).
  2. Количество сценариев.
  3. Правила взаимозачета для сложных спредов (стрэддлы, конверсии, реверсы).

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

Робот, торгующий опционами
 
Цитата
nikolz написал:
Это самый рискованный инструмент для торговли.
Он менее рискован чем линейные фьючерсы. А если не совершать продажи, так вообще безопасней некуда. Откуда взялась эта байка - не понятно.
Робот, торгующий опционами
 
Цитата
Сергей Че написал:
То есть я беру текущую цену фьючерса, умножаю на его лотность, и от этой цены иду в сторону увеличения цены с шагом цены фьючерса, и на каждом шаге составляю строку с потенциальным кодом опциона, и затем проверяю, существует ли он. Так?
Да. Если алгоритм формирования кода корректный, то и проверять не обязательно. Но это просто хорошая практика проверять входные данные в функции.
Робот, торгующий опционами
 
Цитата
Сергей Че написал:
Шаг страйков совпадает с щагом цены базового актива или нет?
Он определяется биржей https://fs.moex.com/f/4606/optimum-strike-step.pdf

Вся информация есть на сайте биржи.
Робот, торгующий опционами
 
Цитата
Сергей Че написал:
Как программно узнать список всех страйков для заданного инструмента, скажем RI, и стакан для каждого страйка?
Т.к. опцион содержит цену страйка в своем коде, т.е. это и есть страйк (https://www.moex.com/s205), то никак. Тем более, что в теории цена базового актива ничем не ограничена, раз уже и отрицательные цены есть. Смотрите пример спецификации кода для нефти.

Вы можете исходя из текущей цены фьючерса, с неким шагом цены, строить коды опционов по спецификации и проверять наличие такого инструмента. По факту, когда вы открываете доску опциона, то так и работает - указываете инструмент, шаг страйка и число страйков. В итоге, от центрального строятся с шагом страйки. Так что методика построения массива кодов опционов в коде такая же. После получения кода опциона получение стакана аналогичное как для любого другого инструмента по его коду.
Робот, торгующий опционами
 
Не очень понятен вопрос, т.к. это просто инструмент, такой же, по сути, как RIM6 SPBFUT. Методы получения данных те же, метода работы с заявками тоже.
Страйк это не какой-то параметр, а данные инструмента, т.е. каждый страйк это отдельный инструмент. Поэтому необходимо просто посмотреть спецификацию формирования кода опциона и выбирать необходимые.
Тот же RIM6 - это код инструмента. RI - контракт на фьючерс РТС. M - месяц экспирации (июнь). 6 - год. С опционами также, но просто методика формирования кода более сложная.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Он и опрашивается, через запомненный индекс записи в таблице. Когда ордер найден в таблице, то повторно его иска не надо, просто получить запись в таблице с свежими данными.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
Йцукен написал:
Изменение параметров заявки не приводит к изменению количества записей в таблице. Об этом вы узнаете только через колбэк, либо через регулярный опрос уже существующих записей в таблице.
Да. Датчик температуры ничего не скажет об её изменении. Спросите - скажет.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
nikolz написал:
На самом деле все совершенно иначе.
Это не все иначе, а просто другой подход. Есть колбеки - ок. Используйте. Никто не мешает. Но это не означает, что нельзя делать иначе.
Я привык делать как опрос датчика, например температуры.

А колбеки я использую если данные из Квика обрабатываются через межсетевое взаимодействие. Например тот же торговый алгоритм, написанный на GO.
Но если внутри терминала, где данные есть и доступны всегда, то колбек (именно в этой реализации что есть в Квике) не является единственным и идеальным решением.
Коллбек OnTrade
 
С учетом того, что торги на бирже в первую очередь необходимы "финансовым институтам", т.е. крупным участникам, то и лоты сделаны для них. Физические лица, как обычно, не являются значимыми.

Если просто спросить, то вот ответ:


[*]Первые акции (начало XVII века): В 1602 году Голландская Ост-Индская компания  выпустила первые в мире акции. В то время сделки были штучными, а  понятие фиксированного «лота» в современном понимании (пакет из 10, 100  или 1000 бумаг) еще не было жестко стандартизировано.
[*]Стандартизация (XIX век):  С развитием телеграфной связи и ростом оборотов на таких площадках, как  Нью-Йоркская фондовая биржа (NYSE), возникла необходимость в ускорении  расчетов. Тогда появился «круглый лот» (round lot), традиционно равный 100 акциям. Это упрощало учет и отчетность.
Коллбек OnTrade
 
Цена всегда за акцию. Лот - это минимально возможное число единиц для покупки на основной секции. Т.е. можно купить 1 лот, где 10 акций. Значит необходимо заплатить цена*10.
Есть ещё специальная секция для торговли неполными лотами, т.е. можно совершать сделки не лотами, а единицами акций.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
VPM написал:
Так как я уже задумался про обработку таблицы всех сделок этим способом
Таблицу обезличенных сделок, как разбор стакана, делать только через main. Через колбеки - это плохая затея.

Если же говорить о нагрузке, то вызов getNumberOf("trades") хоть раз в 2 млс - это не то, о чём стоит говорить. Стоит думать о том, какой цикл выполнения функции main. Если это 100 млс, для примера, то ручной разбор сделок будет неотличим от колбека, если говорить о временной составляющей. Даже скорее быстрее, что я показал в одной из веток при анализе одного брокера.

Если же цикл main секунда и более, то уже стоит думать о сокращении этого времени, т.к. колбек хоть может и придёт, но действия по этому колбеку всё равно будет в main, а он медленный.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Так реализация банальна. Запоминаете число записей в таблице при прошлом запросе. При новом проверяете число записей и если оно изменилось, значит есть новая сделка. А дальше уже можете просто перебрать с прошлого индекса до нового или вызвать поиск тоже с прошлого индекса. Ничего необычного. Может даже назначит функцию колбек на новую запись и будет вам свой колбек, а не системный. Причем его никогда не пропустите, т.к. при старте скрипта опросите таблицу.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
VPM написал:
Nikolay,  Кажется уловил Вашу идею, все дело в буффере. Именно он опять возвращает в событийную модель через опрос + буффер, вместо callbacks + буффер?
И решаются вопросы тайминга?
Можно и так сказать. Вы можете просто ждать колбека. А можете постоянно опрашивать таблицу. Именно, что постоянно. Естественно через проверку числа записей в таблице как триггер.
На вопрос - это же накладно. Ответ - большую часть времени скрипт ничего не делает, так что проверить число записей в таблице - это можно сказать что ничего.

Т.к. я привык к такой модели: есть датчик, получаем данные с него постоянным опросом, то это вполне естественное поведение и здесь. Кому-то это может показаться "устаревшим", "неудобным" и т.д. Но колбеки - это просто абстракция над точно такой же моделью поведения, просто скрытой от глаз. Да, раз они есть, их можно использовать. Но - это уже вопрос привычки.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
VPM написал:
Что смущает? Заявлено в подходе "можно просто прочитать таблицу сделок через SearchItems”  Когда делаешь: SearchItems("trades", ...)  получаешь текущее состояние таблицы НО НЕ полную историю изменений?
Меня смущает этот вопрос. Really?

Мы же про сделки говорим. Вы получите все сделки ордера. Это и есть ВСЯ история сделок. Сделка - это законченное, неделимое целое с точки зрения таблицы Квик. Чем будет отличаться полученное если это через колбеки или через таблицу сделок? Или здесь вопрос в времени запроса? Хотя и оно будет одинаковым до долей. Содержимое-то не изменится.

Что же касается остального - все подходы по учету дублей такие же. Сделку прочитали - записали, то зачем её ещё раз учитывать, если второй раз читаете? Точно также как с колбеком - пришел раз, второй уже не учитываешь.

Частичные исполнения в динамике - да также. Увидел, что баланс изменился - посмотри сделки.

Мы здесь разбираем пример работы с ордерами. Но сделки, на самом деле, учитываются независимо, через накопление в буфер. Сделка необходима для расчета своей позиции скрипта, независимой от другого скрипта.
Поэтому сделки контролируются просто постоянно. А уже при проверке ордера мы обращаемся к источнику сделок. Если же позиция контролируется не через сделки, то да, источник - сама таблица сделок.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
VPM написал:
А что это за ограничения? У брокера? Но даже на этой скорости исполнения заявок 1000 мс / 50 = 20 мс. нужно четко корректное исполнение. Что не так то?
Да, у брокера. Причем у большинства это не 50, а 30.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Она ломается, т.к. есть попытка организовать алгоритм, основанный на последовательности. Но т.к. порядок прихода колбеков, да и в целом приход данных с сервера брокера - не имеет определенного порядка.

Да, сделки могут прийти первыми, до ордера. И что это ломает.

Вы просто выполняете свой алгоритм:

Отправили транзакцию.
Ждем появления ордера по номеру транзакции. Хоть по колбеку, хоть сканируя появления записи в таблице ордеров.
Получили ордер. Смотрим на его состояние. И здесь опять не важно как: колбеком или чтением данных с "датчика".
Если состояние изменилось, то переходите к шагу для текущего состояния.
Исполнен - смотрим на сделки. Можно в лоб прочитать таблицу сделок через SearchItems (номер ордера же уже есть). А можно накапливать буфер прошедших сделок, и уже читать из этого буфера. Т.о. не важно пришла ли сделка первой или второй.
Не активен - проверяем какой баланс, и если отличается от количества, то еще необходимо получить сделки до снятия.

Т.о. алгоритм - это State Machine, конечный автомат. Вы просто переходите между состояниями, проверяя данные. Как эти данные получены - не важно.
Если же алгоритм сильно зависит от порядка получения данных, то это плохо. В клиент-серверном приложении точно, когда OnOrder может прийти через минуты после OnTrade. В алгоритме, который просто проверяет данные, он просто будет ждать пока не будет получен весь набор данных, влияющих на переход в следующее состояние.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Этих проблем нет. Ощущение, что просто ищется любое, чтобы оправдать колбеки.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
VPM написал:
Но ведь QUIK скорее event-driven система
Это не так. Это просто попытка сделать как было модно, лет 15 назад. Использовать колбеки или нет - это ваше дело. Сейчас разработчики утверждают, что колбеки гарантированы, и можете их использовать, не думая, что пропустите. Но это не избавляет от необходимости опрашивать таблицы, при старте, очистке таблиц брокером, актуализации состояния и др. Так что в любом случае будет и контур колбеков (если они используются), и контур опроса таблиц. Причем без первого можно работать, а вот без второго - уже никак.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
VPM написал:
вся информация о сделках есть в таблице orders (поля balance, qty)
Это не вся информация. Сделки по конкретному ордеру необходимы чтобы:

- узнать время сделок.
- узнать цену и объем сделок

Торговля одним лотом - это замечательно, но совсем не показательно. Также есть ордера "по рынку" и цену исполнения такого ордера Вы не узнаете из самого ордера.

После того как прочитали, что состояние ордера изменилось - просто вызываете поиск сделок по номеру ордера.
Всплывающая подсказка рядом с указателем - как редактировать окно?
 
Добавлю - вы, конечно, можете зарегистрировать пожелание, но корректная реализация была бы поддержкой HiDPI дисплеев и системных настроек Windows.
А также, наконец, реализовать возможность изменения размеров многих системных окон, типа Lua скрипты, Ввода заявки и т.д.

Можно сказать что понимаем, что разработка началась ещё в 90-х, но в текущих реалиях намного важнее не "темная тема" (на самом деле вредная для глаз), а корректная работа на современном "железе" и современных OS.
Одна надежда, что в будущих версиях Windows наконец уберет поддержку "из коробки" ANSI win1251 кодировку (и заставит устанавливать доп. патч если все же она нужна) и возможно это заставит все же реализовать поддержку UTF8.
Как задать комментарий в заявке?
 
Длина комментария ограничена. Сначала проверьте в окне ввода заявки.
Также есть один брокер, который обрезает данное поле и не транслирует далее в OnOrder, OnTrade
Гарантируется ли вызов колбэка при получении Квиком новых данных?, Вопросы разработчикам QUIK
 
Цитата
TGB написал:
для того, чтобы события коллбеков при этом не терялись, в QUIK должна быть внутренняя служебная(ые) очередь. Эта очередь может гарантировать отсутствие потерь событий только при  
Цитата
TGB написал:
v1 <= v2
Не только очередь, а еще ack флаги. Сама очередь ничего не гарантирует.
Причина очень медленной загрузки QUIK
 
Цитата
Йцукен написал:
Можно предположить, что основной поток был чем-то занят, поэтому колбэк OnTrade был вызван с опозданием. И терминал в это время не мог принимать и отправлять данные на сервер, в связи с чем получил информацию по заявке только через две с половиной минуты.
Это даже не надо предполагать, это так и есть. Когда в следующий раз на рынке будет бада-бум, просто отправьте транзакцию прямо из терминала. И посмотрите когда в таблице ордеров появится ордер. Только нажимайте на команду один раз, т.к. очень часто многие совершают ошибку: нажал купить - ничего. Наверно не отправилось, нажму ещё раз. Нажал еще раз кнопку купить - опять ничего. Что же такое? Еще раз - опять ничего.

А потом все эти три ордера прилетают.

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

Так что даже в банальное открытие рынка часто подвисает, т.к. сразу проходит много сделок.
БКС терминал Quik, подключение к серверам БКС
 
 А что простой ping или tracert говорит?
Пожелание по развитию форума QUIK, Идея
 
Цитата
Alexey Ivannikov написал:

Добрый день.

Пользователь попросил, за следующие 8 дней никто здесь не написал что ему не нравится что и как было предложено. Почему сразу было не высказать своё несогласие? В таком случае у нас было бы время учесть и Ваше мнение.
Это как пришел один и попросил поднять налоги всем на 10%, сделал это через форму подачи заявлений, которая хоть всем и доступна, но предполагает, что её все должны читать. Раз никто не возразил, значит все согласны.

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

Видим цифру 100. И что? Руками отсчитывать эти 100 сообщений? Хотя уже давно, почти во всех площадках, есть переход на последнее прочитанное сообщение - хочешь, читай все пропущенное. Хочешь - пропускай. А то, что есть непрочитанные и так было видно ранее. А вот то, что есть теперь цифра не избавит от необходимости искать где был последний раз.
Пожелание по развитию форума QUIK, Идея
 
Цитата
Alexey Ivannikov написал:

Добрый день.

Пользователь попросил - мы добавили. В чём проблема?
Попросил именно в таком виде? А спросить у остальных, устраивает это или нет? Многие вопросы касательно форума не решаются, а такое "вырви глаз" - сразу...
Причина очень медленной загрузки QUIK
 
Цитата
Йцукен написал:
Цитата
Nikolay написал:
В  итоге сканер сделок по таблице увидел новую сделку от 14:57:01, сканер  состояния ордеров через таблицы увидел изменение состояния ордера на  исполнен в 14:59:31 - две с половиной минуты от сделки.
Это разные скрипты или один?
Один.

Такая задержка не новость. В марте 2020 были и больше, но там было ясно, что сервер брокера не справляется. В 2022 тоже самое. В 2011, 2014, 2016 - любой год можно назвать.
Откуда на фьючерсах расчеты T1?
 
Готовятся

https://www.moex.com/ru/derivatives/unified-trading-session
Причина очень медленной загрузки QUIK
 
Вчера, после выключения электричества на длительное время, один терминал и  скрипт был перезапущен в 14:42:38. При старте найдены запомненные  ордера. Далее брокер начал активно обмениваться сообщениями типа:

OnTransReply  result_msg: Справочник отправлен. status: 3 trans_id: 19 order_num: 0  price: 0 qty: nil account  client_code  firmid nil brokerref

В  итоге сканер сделок по таблице увидел новую сделку от 14:57:01, сканер  состояния ордеров через таблицы увидел изменение состояния ордера на  исполнен в 14:59:31 - две с половиной минуты от сделки.
При этом колбеки OnTrade и OnOrder пришли в 14:59:32, т.е. на секунду позже.

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

Этот  брокер всегда отличался особой неспешностью. Запуск терминала в  14:42:38. В 14:43:01 состояние ордера было прочитано как активен. Сделка  в 14:57:01.

В 14:59:30 до сих пор идут транзакции вида : OnTransReply result_msg: Справочник отправлен.

По  факту исполнения ордера была отправлена транзакция, на зеркальный ордер  в 14:59:31. И в итоге за 120 секунд так и не пришел ответ транзакции и  ордер. Т.е. эффект полного отказа сервера брокера. Ответ пришел только в  15:02:41 - три минуты.
Только в 15:02:35 ответы стали приходит за адекватное время - 20 минут после старта.

Можно винить брокера, он резервный и не особо важен, но сам факт такого поведения на 12-ой версии печален.
Пожелание по развитию форума QUIK, Идея
 
Не очень понятно зачем вообще ввели эти странные символы, особенно на красном фоне. Было вполне рабочее решение - выделение жирным. А если уж решили браться за данные изменения, то вместо вывода числа непрочитанных сообщений, лучше бы открывали ветку на месте последнего прочитанного сообщения - это было бы действительно удобно, т.к. не надо искать что последнее прочитал.
Деинсталяция, QUIK не удаляется!
 
Просто удалить каталог. Можно еще почистить реестр, чтобы не светились ярлыки, но все лежит в каталоге.
Свободное перемещение графика
 
Цитата
Йцукен написал:

Дарю идею:
В терминале QUIK добавляете таблицу "Пожелания пользователей", в которой отмечаете присвоенный приоритет и количество проголосовавших.
Каждый пользователь может проголосовать один раз за любое пожелание. Все голоса сохраняются на сервере брокера, который периодически присылает в ARQA файл с голосами. Вы сводите отчёты всех брокеров воедино и рассылаете им обновлённые списки.
А то сейчас я даже не представляю, как вы определяете сколько человек заинтересованы в той или иной доработке.
Если будут вопросы, - обращайтесь
Вы неправильно оцениваете клиентов компании ARQA. Это брокеры и проф. участники. Розничные спекулянты - это клиенты брокеров. Их можно послушать, особенно в части найденных ошибок, но точно не в части курса развития разработки.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
VPM написал:
ни кто не по беспокоит, ни какие колбеки не прилетят, пока зависимости в модулях не установлены
Если это беспокоит, то работа с колбеками организован некорректно. Приход колбека должен быть не прерыванием, а добавлением события в очередь. Когда завершите всю работу с инициализацией, то разберете колбеки что пришли, если пришли. А порядок инициализации не испортится, если это сделать не в OnInit. Вы же сами его задаете, вызывая последовательно модули. Хотя и здесь, если вдруг потребуется его изменить, придется переписывать код.

Также, как я уже сказал выше, передача модулей по ссылкам выглядит "коряво".

OrderManager.init({ExecutionLedger = ExecutionLedger, Logger = Logger})

Если бы каждый модуль сам подключал библиотеки через require, то и передавать их не придется. Например, какой-то модуль для своей работы требует библиотеку, которая больше нигде не используется. Почему же модель сам не подключит ее и будет работать с ней. Если он один, то скажете: хорошо, тогда там и подключу его через dofile. А если таких модулей два? В итоге Вы вынуждены подключать их в одном месте и передавать как параметры.

Хотя задача решается элементарно:
Код
------------------------------
my_module1.lua
------------------------------

local  log = require('log')

local  M = {}

M.method1 = function(x)
   log.info(x)
end

return M


------------------------------
my_module2.lua
------------------------------

local  log = require('log')

local  M = {}

M.method2 = function(y)
   log.info(y)
end

return M


------------------------------
main_file.lua
------------------------------

local  m1 = require('my_module1')
local  m2 = require('my_module1')


function main()

m1.method1(5)
m2.method2(10)

end


Где подключать my_module1, my_module2 и в каком порядке - вопрос второй. Но смысл в том, что каждый модуль несет ответственность за свой контекст.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Здесь не так использование dofile, что и заставляет использовать так. Я не вижу все файлы, то проблема dofile в том, что он каждый раз локализует и исполняет файл. Что кардинально отличается от require. Также dofile работает в глобальном контексте, не позволит подключить один и тот же файл один раз в разных модулях, например, тот же модуль логирования. Вы же из-за такой схемы передаете модули как параметры и будет вынуждены так и гонять контекст туда-обратно. Также если метод  utils.safeParam - это оболочка для getParamEx, то в OnInt не стоит его вызывать, это уже не технологический запрос, а логический к данным.

А сам OnInit в таком виде - не нужен. Я меня также его нет, просто вызываю в начале main свой метод on_init, где выполняю технологические операции при старте скрипта.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
А теперь представьте, что у вас запускаемый скрипт не содержит main. Т.е. тот файл, что выбирает в Квик - это скрbпт без main. Единственное, что этот скрипт делает - это подключает библиотеки и устанавливает параметры, имеет свой искатель библиотек (если нужно).

А как же это работает? Просто - подключая какую-то библиотеку через require, выполняется тело библиотеки. И в какой-то есть main.
Т.о. этот запускаемый файл и выполняет роль инициализатора скрипта. Почему - это не в OnInit. Ответ прост - это намного гибче, т.к. пока дойдем до выполнения main уже выполнится много кода, инициализирующую среду исполнения. Причем в зависимости от скрипта, инициализация разная, может быть сложная, в может простая. Каждая подключаемая библиотека тоже что-то свое подключает.

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

Также достаточно просто посмотреть на схему выполнения Lua скрипта в документации, где видно, что сначала выполняется body, а потом OnInit скрипта. Т.е. с точки зрения main они равнозначны  - выполняются до main. А вот у же с точки зрения OnInit отсутствие body - это недостаток, т.к. когда проект состоит из десятков файлов со своей инициализацией, то контроль за процессом запуска только в OnInit - это сложно.

И с таким подходом, OnInit - совсем не обязательная сущность.
Цитата
VPM написал:
3.2. Загрузка сохраненного состояния (persisted state). В OnInit удобно:* восстанавливать позиции;* читать журнал;* восстанавливать FSM состояние;* загружать последние известные заявки (last known orders)
Возможно я не понял это, но максимум, что можно сделать до main - это прочитать что-то с диска. Ни о каких восстановлении состояния речи не может быть, т.к. восстановление подразумевает и актуализацию после подключения к серверу. Если это просто чтение, то да. Но и это я тоже не делаю в OnInit, т.к. скрипт может не останавливаться и работать сутками без выключения терминала. Это значит, что OnInit вызвался вчера, а сегодня что? Надо же после восстановления связи с сервером и обновления таблиц тоже актуализировать состояние, проверить что случилось, что есть в данных и т.д. И делать это надо при старте каждого дня пока скрипт работает. А работать он может месяцами.

Поэтому OnInit - это технический колбек, просто сигнализирующий, что код исполненный выше в body скрипта при его запуске, не привел к ошибкам. Ничего более. Делается это один раз при запуске. Поэтому там и могут быть только сугубо технические действия именно при запуске скрипта и ничего более.
свободные средства для срочного рынка на едином счете
 
Цитата
VPM написал:
Nikolay, Да решение классное на этот момент оптимальное!  ::  Я тоже сбежал.
Но у меня там приличный портфель, и "срочка" иногда нужна. НО по фондовому тоже ни чего не работает. Из приложения приходится рулить.
Ну видимо, т.к. я ушел с срочки давно, то и проблема не коснулась. Хотя меня уже объединяли в один терминал по нескольким брокерским счетам, т.к. у меня их не один у Сбера.
Там осталась фонда и ИИС.
свободные средства для срочного рынка на едином счете
 
Цитата
VPM написал:
А если серьезно, возможно у кого еще было подобное? Возможно что то нужно поменять в настройках, рабочего места?
Лучше проще. Я банально перестал совершать сделки на срочной секции у брокера Сбер. С такими комиссиями, спасибо, не надо.
свободные средства для срочного рынка на едином счете
 
Цитата
Kilor написал:
Но в окне запись же по-прежнему есть - неужели ее невозможно достать? И как-то странно, что функция не может ее вернуть.
Ну и если "в портфеле", то это getPortfolioInfoEx? Что в ней смотреть, и какое по смыслу событие аналогично OnFuturesLimitChange?
Выведите все записи таблиц futures_client_holding, futures_client_limits, money_limits, depo_limits, account_positions, account_balance

И банально посмотрите на данные. Иногда это проще и быстрее, чем ждать ответ.
Функция getDepoEx может приводить к зависаниям терминала
 
Цитата
Вы это проверили, запустив скрипт в квике из архива?
На своем.
Функция getDepoEx может приводить к зависаниям терминала
 
Цитата
Йцукен написал:
Изменил скрипт в таком виде
Ну это, конечно, ошибка если зависает. Если мне нужен простой скрипт для расчета и завершится, то я не ввожу main и любые колбеки. Просто тело скрипта.

Запустил Ваш скрипт у себя, изменив данные и дату limit_kind на сегодняшнюю. Нет проблем. И с вашими данными, очевидно не подходящими, тоже нет проблем.  
Функция getDepoEx может приводить к зависаниям терминала
 
Цитата
Йцукен написал:
Вы код смотрели? При чём тут sleep?
При том, что его там нет. Именно это и приводит к "зависанию" терминала.

Опять читаем документацию
Цитата
Вызов функции sleep() внутри цикла потока main() обязателен. Значение аргумента функции sleep() может быть равно 1, но в этом случае задержка приближена к значению прерывания системного таймера (по умолчанию 15.625мс).
Цитата
Йцукен написал:
Ну а мне очевидно, что между OnInit и main может вклиниться какой-нибудь колбэк.
Вот именно. Поэтому определение стартовых данных в событийной модели целесообразно делать до main.
И вклинился, и что? Если под этим подразумевается, что в коде вообще не предусмотрено получение вручную данных из таблицы depo_limits, то, конечно, другого варианта как считывать данные в колбеке нет. Но тогда все равно не ясно зачем это делать в служебном колбеке OnInit. Делайте в специализированном OnDepoLimit. Он, если судить по предоставленной событийной модели в документации, все равно вызовется после OnInit. Дайте провести инициализацию скрипта, пусть запустится main. В нем можно считать данные начала. А потом все обрабатывать по приходу OnDepoLimit. Если OnDepoLimit вызовется раньше чем код дойдет до места в main где вызывается getDepoEx, то это ни на что не повлияет, т.к. getDepoEx уже получит актуальные данные.
Функция getDepoEx может приводить к зависаниям терминала
 
Цитата
Йцукен написал:
Но, несмотря на отсутствие в main цикла скрипт не завершает свою работу самостоятельно и нагружает один поток процессора на 100%.
Это давно известный факт, и я про него написал выше "если убрать sleep, терминал "умрет""

Цитата
Йцукен написал:
Чтобы узнать, есть ли данные в терминале, необходимо выполнить запрос. Сюрприз.
Не совсем. Сначала необходимо узнать есть в таблице записи, запросив размер таблицы. Это все же разные запросы, хоть и тоже метод qlua

Цитата
Йцукен написал:
А если скрипт запускается при установленном соединении?
Если запускается при установленном соединении, то да данные есть. Но обычно, все же, скрипты пишутся для работы во всех режимах, а не в одном.

Цитата
Йцукен написал:
Очевидно, что если определять стартовые позиции в main, то есть риск неверной работы скрипта, если в это время будет вызван колбэк OnDepoLimit.
Не очевидно совсем. Этот колбек вызывается очень часто, и не только при изменении позиции. Более того, в определенные моменты торговой сессии, там могут быть некорректные данные. Т.е. необходимо не просто брать данные, а понимать можно ли их брать в этот момент времени. Также, корректно сделать ручной запрос перед принятием решения, зависящего от данных в таблице depo_limits. Колбек - это хорошо, но я очень много раз видел, как в терминал пришли сделки, а позиция в depo_limits обновляется с существенной задержкой. Или, что тоже часто, есть сделки выхода из позиции, по идее можно установить обратно ордера на открытие позиции, а брокер не дает и пишет что денег нет. Т.е. данные еще не обновились.

Так что можете использовать колбеки, никто не мешает. Но речь же про OnInit, а не все колбеки как таковые.
Функция getDepoEx может приводить к зависаниям терминала
 
Цитата
Йцукен написал:
Так может вообще запретить вызывать qlua-функции в колбэках? Только сюрприз: они все стучатся в основной поток, и main будет ждать завершения функции.
Так любой синхронный код, на то и синхронный, что пока вызов идет, то дальше код не исполняется. Здесь ничего нового. И опять - я не знаю как выполняются qlua методы, вызываемые из main. Но если читать документацию
Цитата
Во время выполнения функции main() Lua скрипт не мешает работе основного
функционала РМ QUIK, таким образом, внутри функции main() использование функции
sleep() не приводит к «подвисанию» РМ QUIK и позволяет периодически
приостанавливать скрипт и возобновлять его работу через некоторый промежуток
времени.
можно предположить, что все же вызов методов qlua из main организован без вызова основного потока. Но и не без проблем, т.к. если убрать sleep, терминал "умрет".
Функция getDepoEx может приводить к зависаниям терминала
 
Цитата
Йцукен написал:
А где вы предлагаете определять стартовые (при запуске скрипта) позиции по бумагам и деньгам при использовании событийной модели?
Можно и в колбеках, если угодно, но не в OnInit точно. Начальное заполнение можно выполнить и при запуске main, в начале тела функции. Это не будет сильно отличаться по времени от OnInit.

Но, по хорошему, прежде чем выполнять какие-то запросы, необходимо дождаться, что данные есть в терминале. Если скрипт стартует вместе с терминалом, а брокер вызывает OnCleanUp, то пока данные не загрузятся, вызывать getDepoEx не имеет смысла. Поэтому - сначала старт скрипта, потом проверка наличия данных, потом запрос данных. Но точно не в OnInit когда вообще даже подключения к серверу может не быть.

Если говорить о событийной модели как таковой, то здесь опять нюансы. Если бы это были управляемые колбеки, созданные самим скриптом, с нормальной поддержкой многопоточности, то да, можно и в них совершать действия. А если это событийная модель в прямом смысле, т.е. это именно событие, которое мы отправляем скрипту в main для обработки, а сам колбек легко нагружает приложение, то уже не так очевидно, что там стоит выполнять что-то.

Когда проверять позицию - это вопрос субъективный. Можно по колбеку OnDepoLimit, но стоит учитывать, что будут постоянные вызовы не связанные с изменением позиции. Можно по новой сделке. А если требуется смотреть не только позицию, то и по изменению в таблице ордеров, например. Все зависит от задачи.
Функция getDepoEx может приводить к зависаниям терминала
 
Цитата
Йцукен написал:
Для меня странно выглядит сам факт зависания.
Во-первых, в руководстве ничего не сказано, что getDepoEx нельзя вызывать внутри OnInit.
Во-вторых, если есть ошибка в функции getDepoEx, приводящая к зависанию, мы не знаем, где она может ещё всплыть.

Здесь вопрос самой концепции. OnInit - это сигнал, что скрипт запускается и прямо сказано, что перед вызовом функции main(). А т.к. это колбек, то и в потоке интерфейса терминала.
Т.е. это некий пограничный момент. Т.к. реализацию работы с потоками мы не знаем, то вполне может происходить некий конфликт - скрипт стартует, формируется доп. поток main. А здесь ему пинок - иди выполни qlua метод. Да, любое зависание основного окна приложения - это ошибка, баг. С этим не поспоришь.
Функция getDepoEx может приводить к зависаниям терминала
 
Возможно это и проблема, но, честно говоря, вызов getDepoEx внутри колбека OnInit выглядит странно.  
Страницы: 1 2 3 4 5 6 7 8 9 10 11 ... 27 След.
Наверх