Алена написал: Добрый день. Столкнулась с проблемой, есть 2 разных квика, один установлен давно, второй установлен недавно. Два разных пользователя. На конкретном примере: акции компании ММК, на таймфрейме М15 у пользователя (старый квик) история отображается с сентября 2020 года, у второго пользователя (новый квик) история отображается с августа 2021. Это колоссальная разница, и для анализа инструмента очень критична. Подскажите, как можно расширить историю, и подгрузить более старые данные. Перезаказ данных уже делала, и это не помогло. Заранее благодарю за ответ.Отправитель письма запросил подтверждение о прочтении письма.
все верно. Если Вы не обновляли данные, то история хранится с момента первого обращения к данной бумаге. Если есть желание, то скопируйте файлы истории из квика первого в квик второго и будет Вам одинаково.
Павел Bosco написал: Простенький скрипт, который отправляет заявку на 1 лот в Quik_Junior по сберу так, чтобы она заведомо исполнилась. В нём определены два колбэка, OnTransReply и OnOrder
В результате вижу, что OnOrder вызывается по-моей заявке два раза (она имеет 1 лот и исполняется сразу). Причём, очевидно, так бывает не всегда. Но заметил что такое получается чаще, если делать перед этим реконнект с сервером. Код:
Вопрос, это разве нормально? Чем обусловлено? Кто сталкивался? Как боретесь? Номер транзакции - не статический, для теста генерится рандомом от 1 до 1000
вопросу в обед -100 лет. и столько же ответу. ------------------- Где Вы прочитали, что не может быть несколько ответов с сервера? ----------------------------------- Ответ - "мне кажется" или "я думал" не учитывается.
Anton написал: local for_OnParam = 2 -- Множитель local N_OnParam = 0 ---- function OnParam(p1, p2) for i = 1, for_OnParam do N_OnParam = N_OnParam + 1 end end --- -------- IsRun = true function main() local J local OnParam_begin ------------------- while IsRun do ------ do OnParam_begin = N_OnParam J = 100000000 while ( J > 0 ) do J = J - 1 end -- ### Проблема здесь. "Чистый" байт-код, но в QLua 5.3 здесь переключаются потоки (! в 5.4 этого нет)---- -- for i = 1, 100000000 do end -- Это в QLua 5.3 работает нормально ---
if N_OnParam ~= OnParam_begin then -- Счетчик N_OnParam может исмениться только в OnParam message ( ' Переключение колбека и потока main: N_OnParam - OnParam_begin = ' .. tostring(N_OnParam - OnParam_begin)) end end ----- sleep(10) end ------------------ end
Вариант возможной ошибки. ---------------------- цикл for i = 1, 100000000 do end - пустой. Оптимизирующий компилятор его просто выкинет. ---------------------- Переменная N_OnParam меняется внутри колбека, т е внутри основного потока. ------------------ эта переменная определяет параметр OnParam_begin для if сообщения в потоке main. ------------------------------ Проверка условия и смена параметра асинхронны. ------------------------------- Т е в зависимости от активности на бирже и загрузке процессора условие может не выполнятся никогда. -------------------------- т е будем получать редкие глюки в зависимости от активности торговли и загрузки процессора. Что собственно и наблюдается. ------------------------- Все верно?
Рустам написал: В смысле не существует ГОСТа? Есть одна единственная формула по которой находится средневзвешенная цена. Эти значения должны показывать одно и тоже
Попробуйте ответить на следующие вопросы и будет понятно, что не так в этих значениях. 1) Какая конкретно формула , где Вы ее взяли и как узнали что именно по ней это все считается?. 2) В любой формуле есть параметры. Вы уверены, что параметры в приведенных Вами расчетах средней цены одинаковые? Какие?
Рустам написал: Три разные значения средневзвешенной цены за прошлую сессию. Кому верить?
сложно понять по картинке что с чем Вы сравниваете. Но ,очевидно, что формулы расчета этих цен различные, так как не существует ГОСТА на эту величину. Рекомендую сравнить формулы.
Вы вообще-то ничего не путаете? ---------------------- Колбек - это функция, которая вызывается при наступления асинхронного события. --------------------- Причем здесь задачи, которые не выполняются средствами QLua?
Дам совет начинающим робовладельцам. --------------------- В любом бизнесе есть понятие срока окупаемости вложений в организацию этого бизнеса. ---------------------- Реальный бизнес не может окупиться за время меньше 1-3 лет. ---------------------- Предположим, что Вы мечтаете окупить робота за один год. --------------------- Осталось лишь сказать сколько Вы хотите получить прибыли за год. ----------------- Полагаю, что не 10 тысяч рублей , а скажем миллион рублей. --------------------- Если так, то Ваши затраты на строительство робота составят не менее этого миллиона рублей. ------------------- Поэтому , сколько заплатите за робота, столько он Вам и заработает за 1-3 года, если удачно войдете на рынок с этим роботом. ---------------------------------- Но если неудачно войдете в рынок с роботом с интернет помойки, то слить он может любое количество Ваших денег. ----------------------- Поэтому мне прикольно читать объявления на заборе, а форум это и есть забор , о желании найти аля-кулибина, который знает десять языков со словарем и один , но не цензурный, без словаря, который сделает Вам то, сами не знаете точно что.
попробуйте сначала сформировать все что хотите записать в виде строки а потом запишите это в файл одним обращением. При этом рекомендую ставить метку времени в каждой записи.
Владимир написал: BlaZed, Я хороший алгоритмист. Кроме того, классика: "Чтобы узнать, что яйцо тухлое, не обязательно съесть его целиком". ::
Господи, да я понятия не имею, что такое SMA, а что EMA! Ага, понятно. Ни та, ни другая нафиг не нужны: сам смысл свечей именно в том, чтобы сглаживать случайные колебания, отрезать текущую "мышиную возню", а потому всё это "скольжение" только засирает это усреднение текущими колебаниями. НА КОЙ это надо? Ха-ха-ха! "Чтобы дать больший вес новым данным, была создана экспоненциальная скользящая средняя (EMA)". Нарочно не придумаешь! А свечи более лёгких таймфреймов на кой? Они-то и дают ПОЛНУЮ картину происходящего, дают столько информации, сколько этой несчастной EMA и не снилось.
Да очень просто! Сумма накапливается, пока не заполнен период, данные укладываются... ну, скажем, в циклическую очередь. А дальше - как я сказал. Что делать с этой придурочной EMA, я не знаю - мож, для неё действительно нужен цикл. Но сама она уж точно нафиг не нужна!
Вообще-то сам смысл свечей совершенно в другом. Во-первых, смысл в том чтобы неравномерную временную ось заменить равномерной Во-вторых, чтобы сжать информацию, заменив множество сделок на интервале пятью точечными значениями. При этом нет никакого сглаживания, кроме суммы объема. --------------------
nikolz написал: и время расчета нового значения не зависит от периода EMA
Так у меня время расчета тоже от периода не зависит
тогда поясните зачем это: --------------------------- for i = 1 ,datasource: Size () do -- Пробегаемся по всем свечам if i = = 1 then ema_cache[i] = datasource:C(i) -- EMA Close первой свечи else ema_cache[i] = k * datasource:C(i) + ( 1 - k) * ema_cache[i - 1 ] -- EMA Close всех остальных свеч end end ------------------------- и от чего зависит этот цикл?
БорисД написал: Народ прошу подсказать кто из опытных посетителей этого сайта может посодействовать в написании роботов по моим алгоритмам за разумную плату с продолжительным сотрудничеством на долгие годы за процент от прибыли.
Покажите результаты тестов алгоритма. Если алгоритм интересный, то напишу по нему советник бесплатно. Если советник не сольет депозит, то обсудим варианты сотрудничество.
Алгоритм не один а несколько , и почти все они известны и опробованы на просторах интернета многими трейдерами . Это : сетка заявок ; Мартингейл ; отлов прострелов ; МаркетМейкинг ; заявки по средней скользящей ; валютная переоценка и другие кроме арбитражных сделок которые лично я не рассматриваю . Робот интересует не советник а самостоятельно торгующий , и поэтому он должен быть с устойчивой связью с брокером и биржей , иметь риск-менеджемент , иметь собственный учет исполненных и ожидающих исполнения заявок с возможностью их снятия и перевыставления а также собственный учет состояния своего портфеля по дням ,часам, месяцам ( дневник трейдера ). Для обсуждения вариантов сотрудничества сейчас через личку напишу свои контакты и телефон.
Вы удивитесь, но все известные на просторах алгоритмы торговли - убыточные по определению. Это примеры для дилетантов из разряда - "Мама мыла раму". Рекомендую почитать что-нибудь более серьезное, чем книжки на тему 'Как стать миллионером на бирже". Все эти книжки написали те, кто торгует на чужие деньги за процент от оборота .
БорисД написал: Народ прошу подсказать кто из опытных посетителей этого сайта может посодействовать в написании роботов по моим алгоритмам за разумную плату с продолжительным сотрудничеством на долгие годы за процент от прибыли.
Покажите результаты тестов алгоритма. Если алгоритм интересный, то напишу по нему советник бесплатно. Если советник не сольет депозит, то обсудим варианты сотрудничество.
BlaZed написал: Дмитрий, ну пример для изучения вы явно не самый удачный нашли.. точнее совсем уж неудачный ибо кривой и нерабочий, в нем даже и комментировать нечего
Лови мою функцию расчета EMA Close вместе с примером использования
Код
function main ()
ema_cache = {} -- Кзш со значениями EMA Close
period = 15 -- Период EMA
ds,error_desc = CreateDataSource ( "SPBFUT" ,"SiZ1",INTERVAL_H1) -- Создаем датасурс
n = 0 -- Счетчик
while (ds: Size () = = 0 ) and (n < 100 ) do sleep ( 100 ) n = n + 1 end -- Ждем загрузки датасурса
if (n = = 100 ) then message ( "Ошибка:" .. tostring(error_desc)) return false end -- Если не дождались - выход
ema(ds,period) -- Вычисляем EMA, заполняем кзш
message ( "EMA " .. ema_cache[ds: Size ()]) -- Пример получения EMA последней свечи
message ( "EMA " .. ema_cache[ds: Size () - 1 ]) -- Пример получения EMA предпоследней свечи
end
function ema (datasource,period) -- Расчет EMA Close
local k = 2 /(period + 1 ) -- Коэффициент взвешивания
for i = 1 ,datasource: Size () do -- Пробегаемся по всем свечам
if i = = 1 then ema_cache[i] = datasource:C(i) -- EMA Close первой свечи
else ema_cache[i] = k * datasource:C(i) + ( 1 - k) * ema_cache[i - 1 ] -- EMA Close всех остальных свеч
end
end
end
не используйте цикл. Это зло в прогах реального времени. Если Вам надо рассчитать EMA с периодом 1000 таймов скока времени будете считать? Можете не успеть до получения следующего значения. При этом Вы для каждого нового значения повторно обсчитываете предыдущие 999. ------------------- Прикольно. ----------------- В правильной программе и кеш никакой не нужен и время расчета нового значения не зависит от периода EMA.
function main ()
while is_run do
local identifier = "Si_macd_long"
local count = 10
local offset
local n
local t,n,l = getCandlesByIndex ( "Si_macd_long" , 0 , 0 ,count,offset)
if # t > 1 then
message ( " #t = " .. # t, 2 )
end
sleep ( 500 )
end
end
Что не так тут почему таблица нил, все проверил
У вас в этом примере не задано значение offset - и оно будет nil - а это число запрашиваемых свечек. Ну Вы получаете, то что запросили. Все верно?
Есть некая функция, надо что она вызывалась строго 1 раз в минуту. Основная функция main работает с задержкой sleep (500)
так как у вас есть sleep( 500 ) то вам надо лишь добавить счетчик и вызывать по нему вашу функцию. --------------------- Пример: --------------- function fX() --... end -- эту функцию надо вызвать 1 раз в минуту ------------------- function main()
if count then count=count+500; if count>=60000 then fX(); count=0; end else count=0; end
Nikolay написал: Нет, линии не обязательны конечно. Просто старые значения не должны исчезнуть с графика, поэтому вывод линий, пусть даже и одной, должен учитывать это.
вообще-то пересчет графиков взад - это бессмысленная затея. --------------------------------------------------- "После драки -кулаками не машут"
А если профиль из линий рассчитывать и отрисовывать только последний час, на начало нового часа убрать линии профиля и оставить только maxVol сформированный (TYPET_BAR), кога начинается новый час расчет начать проводить заново. Получится ежечасный maxVol и один профиль. Я нечто похожее видел в NT-7 вот ссылка Индикатор POC уровней .
Вы имеете ввиду столбик числе у свечки? Если да, то так можно сделать.
nikolz написал: Вы может сами добавить сколько хотите функций обратного вызова.
Вы что, не поняли и то, что в приведенном мною примере демонстрируется возможность создания таймерных событий столько, сколько потребуется?
понял, но пример у вас очень громоздкий. ----------------------------------------- все решается гораздо проще на таймерах ожидания ядра либо событиях. При этом реакция ОС составляет не более 1 мкс. =============== Оотносительно колбеков и одновременно таймера. --------------------------- Реализовал это, создав пул событий на основе WaitForMultipleObjects. --------------------------------- В итоге бесконечный цикл запускается через заданный в функции ожидания интервал, т е это тайме собаки, либо при срабатывании любого колбека QLUA или любой функции пользователя, для которой описано событие. ----------------------------------- При возникновении события запускается соответствующий ему колбек. ---------------------- Количество событий- любое Количество колбеков- любое. Все события контролируются OC. ================= Примерно так.
local function f( .. .)
local arg = { .. .}
arg.n = select( '#' , .. .)
return arg.n
end
print (f( 1 , nil , nil ))
Зачем Вам это извращение в скриптах и индикаторах квика? Вы же теряете ресурсы для раскрутки неопределенных параметров. А смысла в переменном числе параметров именно в скриптах торговых роботов нет.
На самом деле Вам не надо вызывать 1529*8=12232 раза так как список Ваших инструментов грузится при старте и отображается в текущей таблице. У Вас будет проблема со скоростью вашего железа. Но полагаю , если Вы торгуете по 1529 инструментам, то у вас железо должно быть очень крутое. На рынке халявы нет и на плохом железе нечего делать с таким количеством тикиров.
Ну, начнём с того, что тикеров у меня не 4, а на сегодняшний момент 1529, и их состав немного "плавает", и код скрипта это, разумеется, никак не затрагивает. Интервалов у меня тоже вдвое больше - мелкие свечи я считаю сам, но они ведь тоже должны где-то храниться и далее обрабатываться по общему алгоритму..
Теперь инициализация: что делает хреновина вида "ds[tikers[j][1]]=ds[tikers[j][1]] or {}" я не знаю, да и знать не хочу. Для меня не подлежит сомнению, что обращение к данным тикера должно быть по его айдишке (его порядковому номеру в таблице), а уже в полях этой таблицы должен лежать и код тикера, и код класса, его валюта, статус, количество закупленных лотов, размер лота и вся прочая хрень. В том числе, одно из этих полей должно содержать информацию о свечах по разным таймфреймам: младшую часть я инициализирую и поддерживаю в актуальном состоянии сам, а вот вторая половина должна получать её как раз через CreateDataSource. Итак, мне предлагается при старте вызвать эту конструкцию 1529*8=12232 раза, а уж опосля... впрочем, что-то мне подсказывает, что никакого "опосля" уже не будет - на этом скрипт и сдохнет. ::
Теперь насчёт Size: СКОЛЬКО свечей она мне даст по каждому интервалу? Повторяю: мне нужна ОДНА, последняя. Ну, для страховки, ДВЕ. А эта падла сколько их туда насуёт? И, насколько я понимаю, будет всё время дописывать? Или даже и дописывать не будет?
Нет, я не понимаю: Вы ВСЕРЬЁЗ предлагаете подобную хрень реализовать или прикалываетесь?
Реализуется это примерно так. Надо читать с сервера самый мелкий интервал. Долее на каждый тик будет примерно 10 операторов Считаем всегда последнюю. Сохраняем столько , сколько надо. Если надо одну то в архиве будет всегда одна на каждый инструмент и одна - открытая
BlaZed написал: Владимир, Не ожидал :: Тут же даже кулинарить нечего, все и так очевидно
Создать датасурс и выдернуть из него последнюю свечу проблем нет никаких (см. пример в первом посте). А как в цикле пробежаться по заданным интервалам и инструментам думаю сами догадаетесь.
Вопрос то у вас в чем?
вообще-то Вы ошибаетесь Свеча - это четыре индикатора цены и один объема. Т е для любого интервала надо считать close,Low, High, Volume. Просто Выдернуть не получится . --------------------- Open - это первая свеча после открытия интервала High и Low - это локальные экстремумы на данном интервале Value - сумма значений на интервале Close - это последняя сделка перед закрытием интервала. ------------------- На мало ликвидном рынке надо учитывать тот факт, что на интервале может не быть сделок вообще. --------------------- А теперь все это для различных интервалов и множества инструментов. Когда писал это чудо. Попробуйте написать. ------------------------------- Полагаю, что вопрос в этом.
Незнайка написал: упаковать значения в две таблицы, а потом объединить их
Но есть косяк: если функции могут возвращать nil, то unpack работает криво. Когда таблица сразу заполняется при создании, то распаковывается нормально:
не ставьте перед переменными local. они будут глобальными в первой функции считаете 4 параметра которые изначально не определены во второй функции считаете следующие 4 параметра при выводе просто перечисляете их например так : ----------------------------- function fun1(k) x1=k+1; x2=k+2; x3=k+3; x4=k+4; end ------------------------------ function fun2(k) x5=k+5; x6=k+6; x7=k+7; x8=k+8; end ---------------------------- function onCalculate(i) .... fun1(i); fun2(i); return x1,x2,x3,x4,x5,x6,x7,x8; end
Предлагаю для скриптов LUA реализовать: 1) колбеки QLUA в виде asynchronous procedure call (APC)для потока main; 2) в одном скрипте создавать несколько потоков и с помощью APC распределять по ним обработку данных из терминала КВИК.
Nikolay написал: Нет, линии не обязательны конечно. Просто старые значения не должны исчезнуть с графика, поэтому вывод линий, пусть даже и одной, должен учитывать это.
вообще-то пересчет графиков взад - это бессмысленная затея. --------------------------------------------------- "После драки -кулаками не машут"
_sk_ написал: Добавить функцию обратного вызова OnTimer(), которая будет вызываться терминалом с некоторой периодичностью
В данном комментарии выложен модуль работы с таймерными событиями в отдельном потоке и шаблон его использования. ---- API работы с таймерными событиями: 1) Start_Timer() - запуск отдельного потока обработки таймерных событий. 2) <Ключ события> = Set_Timer ( {<Имя события>, <Интервал в млсек.>, <Функция обработки события>,{<Список парвметров функции>}} ) - запрос таймерного события. Через <Интервал в млсек.> будет запущена в отдельном потоке <Функция обработки события> со <Списоком парвметров функции>. 3) delete_Timer (<Ключ события>) – удаление при необходимости запрошенного собы-тия. ---- Модуль и две dll (service53.dll и service54.dll) , скачанные по ссылке: https://cloud.mail.ru/public/i3Y7/kQHBvs7um необходимо положить в папку хранения info.exe. --- Модуль OnTimer (для QLua 5.3 и 5.4):
Код
-- Модуль таймерных событий OnTimer ---
-- Подключение C-пакетов service53, service54: https://cloud.mail.ru/public/i3Y7/kQHBvs7um
local WorkingFolder = getWorkingFolder ()
package.cpath = package.cpath .. ';' .. WorkingFolder .. '\\?.dll' .. ';' .. WorkingFolder .. '\\?53.dll' .. ';' .. WorkingFolder .. '\\?54.dll' .. ';' .. WorkingFolder .. '\\?51.dll'
.. ';' .. WorkingFolder .. '\\?3.dll' -- C - пакеты ----
if _VERSION = = 'Lua 5.3' then
require ( 'service53' ) -- Подключает библиотеку service.dll, расположенную в корневом каталоге терминала QUIK (там где info.exe) ----
else
require ( 'service54' )
end
local GetMilliseconds, Start_thread = service.GetMilliseconds, service.Start_thread
--- Функции работы с очередями ---
local new = function ()
return {first = 1 , last = 0 }
end
---
local push = function (self, v)
local last = self.last + 1
self[last] = v
self.last = last
return last
end
---
local pop = function (self)
local first = self.first
if first > self.last then return nil end
local v = self [first]
self.first = first + 1
self[first] = nil
return v, first
end
--------- Создание очереди ------
local Queue_Timer = new() --- Таймерные события -----
local Queue_Timer_Sl = new() --- Очередь отмены событий ---
-------------------------------------------
--- Заказ таймерных событий ----
--- Таймерное событие: {<Имя события>, <Интервал в млсек.>, <Функция обработки события>,{<Список парвметров функции>}}
local function Set_Timer (self)
if type(self) = = 'table' then
if # self > = 3 then
self [ 2 ] = self [ 2 ] + GetMilliseconds()
return push (Queue_Timer, self)
else
message ( '!!! Ошибка. Должно быть: {<Имя события>, <Интервал в млсек.>, <Функция обработки события>,{<Список парвметров функции>}}' )
end
else
message ( '!!! Ошибка (параметр не таблица). Должно быть: {<Имя события>, <Интервал в млсек.>, <Функция обработки события>,{<Список парвметров функции>}}' )
end
end
-----
local function delete_Timer (kl)
push (Queue_Timer_Sl, kl)
end
------
local function Timer ()
local ms, first_q
while IsRun do
--- Обработка удалений событий ---
ms, first_q = pop (Queue_Timer_Sl)
while ms do
if Queue_Timer [ms] then Queue_Timer [ms] = nil end
ms, first_q = pop (Queue_Timer_Sl)
end
--- Чтение очереди заказанных событий[ -----
for k, v in next, Queue_Timer do
if type(k) = = 'number' then
if v [ 2 ] < = GetMilliseconds() then
Queue_Timer [k] = nil
if v[ 4 ] then
pcall ( v[ 3 ], table.unpack (v[ 4 ]))
else
pcall ( v[ 3 ]) -- функция без параметров ---
end
end
end
end
-------------------------------------------------------
sleep ( 2 )
end
end
---------------------------------------
local function Start_Timer ()
Start_thread (Timer)
end
------
return {Set_Timer = Set_Timer, delete_Timer = delete_Timer, Start_Timer = Start_Timer }
---------------------------------------------
Шаблон использования модуля:
Код
-- Шаблон использования модуля таймерных событий
local OnTi mer = require ( 'OnTimer' ) -- Подключение модуля обработки таймерных событий ---
local Set_Timer = OnTimer.Set_Timer
local delete_Timer = OnTimer.delete_Timer
local Start_Timer = OnTimer.Start_Timer
IsRun = true
local function call_Timer (kl)
message ( 'call_Timer = ' .. kl)
end
local function call_Timer1 ()
message ( 'call_Timer1 () ==============' )
end
function main ()
Start_Timer()
local kl
--- Заказ таймерных событий ----
--- Таймерное событие: {<Имя события>, <Интервал в млсек.>, <Функция обработки события>,{<Список парвметров функции>}}
kl = Set_Timer({'Set_Timer', 100 , call_Timer, { 100 }})
kl = Set_Timer({'Set_Timer', 1000 , call_Timer, { 1000 }})
kl = Set_Timer({'Set_Timer', 5000 , call_Timer, { 5000 }})
kl = Set_Timer({'Set_Timer', 3000 , call_Timer1})
-- delete_Timer (kl)
-------------------
while IsRun do
---- Обработка в main остального -----
kl = Set_Timer({'Set_Timer', 1000 , call_Timer, { 1000 }})
delete_Timer (kl)
---- Конец Обработка в main остального -----
sleep ( 500 )
end
------------------
end
function OnStop ()
IsRun = false
DestroyTable (TableQUIK)
DestroyTable (TableQUIK1)
return 10000 -- !! По истечении этого интервала времени (в млсек.), данного скрипту на завершение работы, функция main() завершается принудительно.
-- При этом возможна потеря системных ресурсов. ! Если функция не выдает значение, то по умолчанию оно 5000 (5 сек.)
end
Попробуйте использовать таймеры ожидания (таймеры ядра) Такое решение и проще и лучше. Не надо создавать новые потоки. Квант таймера 0.1 мкс. Программирование гораздо проще, чем ваша скатерть-самобранка.
Алексей написал: Уважаемые форумчане, добрый день. Подскажите, пожалуйста, контакты хорошего программиста, который сможет за недорого написать торгового робота на заказ по предоставленному алгоритму для работы в QUIK. Благодарю. ))
Могу за недорого доказать, что робот по Вашему алгоритму сольет Ваш депозит в реальных торгах.
sleep позволяет усыпить main не менее чем на 1 ms что примерно в 50 раз больше времени активации main колбеком. Но чтобы ядро не грело воздух зря, надо ставить sleep на 100 ms. А это уже в 5000 раз больше времени активации main. --------------------- кроме того, интервал прихода информации с сервера брокера составляет примерно 70 ms (у меня) Поэтому при sleep 100 ms может не только пропускать колбеки, но и создать затор поступающей информации с торгов. т е легко получить тормознутый робот. ------------------
В предыдущем тесте в вычислении времени включено время преобразования значений счетчиков в строку Поэтому время немного завышено Вот показания лог файла чистой задержки активации main колбеком: .... 21>0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,37,0 31>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,37,0 22>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,38,0 23>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,39,0 21>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,40,0 20>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,41,0 21>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,42,0 21>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,43,0 23>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,44,0 21>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,45,0 20>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,46,0 21>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,47,0 20>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,48,0 33>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,49,0 20>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,50,0 20>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,51,0 21>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,52,0 20>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,53,0 20>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,54,0 21>0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,55,0 28>0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,55,0 ... Т е это время менее 30 мкс .
Полагаю , что останов функции main c помощью sleep неудачное решение разработчиков. -------------------------------- Сам использую останов потока системным событием Event. Неоднократно предлагал разработчикам реализовать останов потока системным событием Event. Но воз и ныне там. ------------------------------ Чтобы показать наглядно эффективность предлагаемого способа реализовал следующий тест. ----------------------- Во всех колбеках поставил счетчик вызова и старт таймера. В функции main поставил останов таймера и запись в лог счетчиков событий всех колбеков и прошедшее время с момента вызова очередного колбека. ---------------------- Вот фрагмент лог файла: ... 93>0,0,0,0,11,11,0,0,0,0,0,0,0,0,15784,95846,0 83>0,0,0,0,11,11,0,0,0,0,0,0,0,0,15784,95847,0 90>0,0,0,0,11,11,0,0,0,0,0,0,0,0,15784,95848,0 129>0,0,0,0,11,11,0,0,0,0,0,0,0,0,15785,95848,0 110>0,0,0,0,11,11,0,0,0,0,0,0,0,0,15786,95848,0 261>0,0,0,0,11,11,0,0,0,0,0,0,0,0,15786,95850,0 431>0,0,0,0,11,11,0,0,0,0,0,0,0,0,15786,95850,0 88>0,0,0,0,11,11,0,0,0,0,0,0,0,0,15786,95851,0 85>0,0,0,0,11,11,0,0,0,0,0,0,0,0,15786,95852,0 131>0,0,0,0,11,11,0,0,0,0,0,0,0,0,15787,95852,0 113>0,0,0,0,11,11,0,0,0,0,0,0,0,0,15788,95852,0 162>0,0,0,0,11,11,0,0,0,0,0,0,0,0,15788,95853,0 91>0,0,0,0,11,11,0,0,0,0,0,0,0,0,15788,95854,0 93>0,0,0,0,11,11,0,0,0,0,0,0,0,0,15789,95854,0 294>0,0,0,0,11,11,0,0,0,0,0,0,0,0,15789,95855,0 .... На первой позиции время в микросекундах, прошедшее с момента вызова терминалом колбека до момента активации потока main скрипта. далее через запятую счетчики вызова колбеков. -------------------------------------------- Как видно из лог файла это время составляет примерно 100 мкс (компьютер слабый, WIN XP). -------------------------- Получается, что использование функции sleep либо приведет к постоянной активации потока и бесполезной загрузки ядра, либо к пропуску завершения работы колбеков. Обе ситуации плохо.
Инесса написал: Здравствуйте. Сломался компьютер, поменяли жёсткий диск. Сохранилась на флэшке резервная копия QUICK давностью полтора года с ключами. Как правильно переустановить терминал чтобы в нём были мои ПОСЛЕДНИЕ (недельной/месячной давности) настройки? Можно ли это вообще каким-то образом сделать? Если я просто копирую с этой флэшки и запускаю терминал, он имеет настройки полуторагодичной давности (время создания этой резервной флэшки). Может просто потом обновить терминал до текущей версии и появятся мои последние настройки? Или скачать дистрибутив с сайта ВТБ и потом как-то прописать там старые ключи? Или есть ещё способ восстановить собственные настройки терминала? Если этот вопрос уже где-то рассматривался, киньте ссылкой, пожалуйста.
Олег написал: Небольшая корректировка: сейчас в коде прописано sleep (20000) , то есть сообщение появляется раз в 20 секунд.
в цикле читайте системное время и вычисляйте требуемый интервал при его наступлении выводите сообщение. Таким образом получите интервал от 1 секунды до 100 лет.
Владимир написал: nikolz, Лапуль, Ваша информационная ценность для меня просто РАВНА нулю. Ну, расскажите, коль неймётся, как Вы будете получать дневные, недельные и месячные свечи - посмеёмся...
Владимир, Вообще-то это Вы льете крокодильи слезы про ужас со свечами. У меня нет проблем Не хотите помощи, нет проблем. Полагаю Вам надо лишь ля-ля. Успехов в словесном поносе на форуме.
Владимир написал: Anton, Я догадываюсь - я же не первый год программирую. :: Но сути это не меняет: это по-прежнему простенькая прикладная задача и по-прежнему с поганым языком и поганым интерфейсом. Но функциональность по-прежнему ДОСТАТОЧНАЯ для организации торговли. Что до "внешних длл по дизайну" - а зачем они нужны? Дизайн на таблицах Квика и всяких там SetTableNotificationCallback более, чем удовлетворительный - хрен такой получишь от этих внешних длл! А роботу, по большому счёту, это вообще не нужно. Только вот со свечами какой-то тихий ужас творится.
Я Вам уже предлагал выше. Напишите конкретно что у вас за ужас со свечами. (проще задачи не бывает) Я Вам расскажу как решить Ваш ужас.
поясню про быстрее. Биржевая информация о сделках поступает простым клиентам с задержкой примерно 0.1 секунды. Компьютер обработает ее и отправит заявку примерно через 0.01 сек Поэтому, если хотите быстрее, то используйте выделенный сервер в дата центре брокера. Будет до 100 быстрее.
nikolz написал: В итоге каждый колбек пишет принимаемые им данные в свой массив А функция main лишь читает эти данные. Синхронизировать колбек и main нет надобности, так как если колбек изменил данные, то main на следующем цикле их увидет.
У меня меин в блокировке ждет данных периодических...в этот момент колбеки вызывают функциии другие. Но стек то получается один и надо его синхронизировать.
я решил проблему через системные события и мапинг файлы. В результате я могу данные из колбеков использовать в любых других скриптах т е потоках а не только в main данного скрипта. Чтобы стеки не пересекались определяю все данные как локальные для соответствующего потока.
В итоге каждый колбек пишет принимаемые им данные в свой массив А функция main лишь читает эти данные. Синхронизировать колбек и main нет надобности, так как если колбек изменил данные, то main на следующем цикле их увидет.
Виталий написал: Известно, что функция main и колбэки (напр. OnTransReply) выполняются в разных потоках. Далее к проекту подключена с++ либа и функции из нее вызываются как и из функции main так и из колбэков. Далее, я понимаю механику следующим образом: - Функция main и колбэки отправляют в с++ либу разные lua_state, и поэтому в данном случае обращение к ним из либы в принципе не может пересечься поэтому потокобезопасно. - А вот разные колбэки сами по себе отправляют в либу одно и тоже lua_state и поэтому работа с ними в либе уже требует синхронизации.
Правильно ли я понял механизм?
Проблема синхронизации потоков не связана с исполняемым кодом, а связана с записью данных . -------------------- Из своего опыта: Особенностью работы с биржевыми данными является то, что всегда можно организовать данные так, чтобы запись в конкретный массив (вектор) делалась лишь одним потоком, а читались данные всеми другими. Так как данные поступают асинхронно, то в такой реализации синхронизировать ничего не надо. Проблем не возникает.
Андрей написал: ошибки типа данный инструмент запрещен в шорт
Цитата
Андрей написал: Сделайте вторую версию sendTransaction, которая бы не проверяла подобные локальные условия. Чтобы можно было вызывать 2 транзакции сразу друг за другом.
Вы не подумали, что первая заявка может исполниться, пока транзакция на её снятие дойдёт до биржи? Тогда, при исполнении второй заявки, получится как раз шорт. А это нарушение. Брокер будет вынужден закрывать ваш шорт принудительно.
А кто в этом случае контролирует лимиты?Никаких нарушений не возникнет
Не парьтесь никаких нарушений не возникнет. На бирже торгуете не Вы, а брокер. Поэтому не важно будет шорт или нет. У брокера достаточно средств клиентов и бумаг клиентов для покрытия всех его ( т е его клиентов) сделок За достаточностью средств у брокера следит биржа .
Олег написал: Коллеги! Подскажите как бороться с наглым Сбером, который неправильно исполняет стоп-заявки. У меня была выставлена стоп-заявка №305 019 117 на продажу акций Акрон по цене 6600, с отступом 2 и защитным спредом 6.
27.07.21 произошел скачек стоимости акций до 7000. Но моя заявка была реализована по цене 6028, что на 240 рублей ниже покупки.
Стор-ордер был выставлен именно с защитным спредом, а не "по рынку". Если бы в момент исполнения стоп-ордера на рынке не было бы предложения по цене 6600+2-6, то должен был остаться открытым и не исполненным ордер на продажу по цене 6596 и до предложения на рынке он должен был остаться не исполненным. Так как в Сбер-онлайн отключили возможность написать жалобу, а в чате оператору ни чего нельзя объяснить, пришлось писать в группы Сбера в соцсетях, но хоть так приняли жалобу и даже присвоили ей входящий номер. К стати, это фишка только Сбера не принимать на сайте жалобы :-(
В ответ получаю вот такую отписку: -------------------------------------------------- Решение: У банка отсутствуют основания для выплаты компенсации денежных средств. Заявка от 05.07.2021 на продажу Акций исполнена банком согласно выставленных Вами условий. Банк регулярно контролирует показатель текущей очереди входящих звонков в службу поддержки. Однако в силу того, что количество поступающих телефонных обращений в некоторых ситуациях не поддаются точному прогнозу, оперативно сократить при данных обстоятельствах время ожидания клиента до показателя штатного режима не всегда представляется возможным. Банк проводит мероприятия для исключения подобных проблем в будущем, в том числе путем увеличения штатной численности службы поддержки. Задать интересующие Вас вопросы Вы можете в приложении СберБанк Онлайн в разделе «Диалоги» или в профиле «Связь с банком», а также в мобильном приложении СберБанк Инвестор / СберИнвестор. Информация о инвестиционно-брокерском обслуживании размещена на официальном сайте банка в разделе «Инвестиции». За консультацией Вы также можете обращаться в подразделения банка, осуществляющие брокерское обслуживание. Адреса, телефоны и режим работы офисов брокерского обслуживания размещены на интернет-сайте банка в разделе «Инвестиции» - «Брокерское обслуживание» - «Контакты»: Приносим извинения за неудобства. Основание принятого решения: Порядок и условия, на которых Банк предоставляет физическим лицам брокерские услуги на рынке ценных бумаг, биржевом валютном рынке и срочном рынке, предусмотренные Федеральным законом «О рынке ценных бумаг» от 22.04.1996 № 39-ФЗ, а также иные сопутствующие услуги определяются Условиями предоставления брокерских и иных услуг ПАО Сбербанк (далее - Условия). Текст Условий размещён на официальном сайте банка в сети Интернет в разделе «Инвестиции» - «Брокерское обслуживание» - «Документы»[1]. Заявка «Тэйк-профит» – это заявка с условием вида «исполнить при ухудшении цены на заданную величину от достигнутого максимума (на продажу) или минимума (на покупку)». Заявка работает следующим образом (пример для заявки на продажу): после достижения ценой последней сделки условия стоп-цены начинается определение максимума цены последней сделки. Если цена последней сделки снижается от максимума на величину, превышающую установленный «отступ», то создается лимитированная заявка с ценой, меньшей цены последней сделки на величину «защитного спрэда». ---------------------------------------------- Дальше куча воды. Может мне специалисты по Квику объяснят как в таком случае должна исполняться заявка? И зачем нужен защитный спред, если брокер как хочет, так ее и исполняет? С уважением, Олег.
Попробую пояснить про стоп-заяви. Стоп-заявка - это отложенная отправка заявки клиента При срабатывании условия заявка не будет исполнена а будет отправлена на исполнение на сервер биржи. Поэтому фактическое исполнение стоп-заявки зависит от многих условий. Так как стоп-заявка как правило исполняется у многих клиентов и в моменты резкого движения цены, то в итоге получается длинная очередь на отправку этой заявки с сервера биржи и длинная очередь на исполнение этой заявки на сервере биржи ---------------- В итоге Вы всегда получите результат хуже, чем Вы мечтаете.
nikolz написал: пора бы усвоить что халява - она и есть халява.Во-первых, весь квик - это официально бесплатный продукт.
Это вам так брокеры рассказывают, но при этом в ваших комиссиях брокеру незримо сидит некий процент отчисления за QUIK. Так что за QUIK пользователь платит и ARQA материально зависит от пользователей.
Это так в регламенте брокера указано и Вы с ним согласны и подписываете с ним договор. ------------------------- что сидит там незримо, то в суде не докажите. ----------------------- А бесплатность услуги исключает ответственность за ее качество. ------------------------ Можете сколько угодно жаловаться на ошибки на форуме. ----------------------- Для всех посетителей форума писанина на QUIK это хобби с желанием на халяву срубить бабло. --------------------------------- Для разработчиков - это ежедневная работа , а не хобби. Поэтому они делают то, за что им брокеры платят. -------------------- Вы платите деньги брокерам. Вот и жалуйтесь брокерам на ошибки в софте. Только при претензиях от них разработчики будут исправлять ошибки. --------------------- А на жалобы от халявщиков всегда будут лишь отписки и милостыня.