Роман написал: если у нас индекс массива с плавающей точкой, какую функцию использовать, что бы получить первое и/или последнее значение индекса, существует ли простой вариант без использования циклов?
Думаю что нет. Без явной сортировки не получится. По аналогии с ф-цией pairsByKeys, можно сделать такую же ф-цию возвращающую первый и последний элементы таблицы с сортировкой по вещественному индексу:
Код
local t = {}
t[15.5] = "aaa"
t[3.1] = "bbb"
t[7.8] = "ccc"
t[115.5] = "aaa"
t[23.1] = "bbb"
t[557.8] = "ccc"
t[14.5] = "aaa"
t[43.1] = "bbb"
t[87.8] = "ccc"
function getFirstAndLastByKeys(t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
return a[1], t[a[1]], a[#a], t[a[#a]]
end
local first_k, first_v, last_k, last_v = getFirstAndLastByKeys(t)
print(first_k.." = "..first_v)
print(last_k.." = "..last_v)
Suntor написал: Этот sleep ... там должен быть обязательно.
Ну и какой тогда толк от "колбэка"?
sleep в main и «колбэки» никак напрямую не связаны... разные вещи. sleep в main нужен для того, чтобы этот самый main не повесил весь Quik с концами...
Цитата
Ирина написал: Что без него main спал и пропускал сигнал, что с ним спит, только ещё и основной поток грузится...
main ничего не пропускает, а лишь реагирует с задержкой. И так он и должен работать, потому что ваш код изначально строится по схеме «опроса». И «колбэки» вы в эту схему засунули, чтобы лишний раз не дёргать getNumberOf, а я лишь довёл вашу эту схему до совершенства, грубо говоря, и вообще избавился от getNumberOf... Важно то, что вы строите ваш код по принципу опроса системной таблицы all_trades. Можно опрашивать её в main дёргая getNumberOf, сохраняя и сравнивая размер каждый раз, можно через булев флаг выставленный из «колбека» о том что таблица изменилась, а можно подсчётом событий «колбэков» насколько она изменилась, как в моём примере. В любом случае, этот код по схеме «опроса» будет работать с задержкой sleep в потоке main, и в любом случае эта задержка там необходима, иначе всё повиснет.
Цитата
Ирина написал: Кстати, в примере из "Использование Lua в Рабочем месте QUIK" в main нет sleep. Ошибка?
Он там есть, только спрятан в нижестоящую ф-цию ProcessingCallback... и это пример кода. Если в этом месте менять на свои реальные вычисления, то этот sleep нужно будет передвинуть выше в main. Можете все остальные примеры с первой и до последней страницы пересмотреть в этом документе, там везде в каждом main стоит sleep.
Цитата
Ирина написал: Сдается мне, что не main-ом надо "колбэки" обрабатывать, а "колбэками" main, - только так их скорость будет использована.
Ваше заблуждение лишь оттого, что вы через «колбэки» пытаетесь сделать код по схеме «опроса», где эти «колбэки» то и не нужны. Они нужны совсем для другого, кода вы строите код по схеме обратного вызова. То-есть, вместо цикла со sleep внутри main, где вы периодично опрашиваете таблицу, нужно поместить код в «колбэки», и он сам будет вызываться и именно в тот момент, когда наступит событие. А не тогда, когда цикл main после sleep наконец проснётся и обнаружит, что пока он спал, таблица all_trades приросла новыми данными. «Колбэки» срабатывают в тот момент, когда по сети информация приходит в Quik. Счёт идёт на миллисекунды... «Колбэки» это более мощное средство, и с его помощью можно имитировать схему «опроса», а вот наоборот уже не получится.
Наверно да. Лет 10 назад, помню была эта чехарда с серверами, их висело по 5..6 штук в диалоге, постоянно их там меняли. Но давно такого уже не вижу. Да и брокеры менялись.
Цитата
Sergey Gorokhov написал: это надо чтобы стоп заявка не срабатывала одновременно на всех контурах брокера.
Спасибо за объяснения. В общем-то понятно зачем. Тем не менее, прихожу к выводу, что явно не хватает важной части на серверной стороне Quik. То что вы описали, это типовое Аварийное переключение (Failover), которого у вас просто нет. Такая штука должна быть в рамках вашей сети серверов. На этом построена работа большинства интернет систем от DNS до CDN. Участие пользователя не требуется, чтобы синхронизировать данные между хостами одной сети. Он вообще не должен знать в идеале, где и что там находится, какой сервер и где упал, где произошла горячая замена такого сервера и пр. Для пользователя это должно быть прозрачно. Если он подключился к любому серверу системы, то должен видеть то состояние своих заявок в системе, которое он оставил при своём последнем подключении. Система сама должна выбирать сервер, который в данный момент обрабатывает заявку, сама следить за его состоянием, и сама перебрасывать заявки на другие сервера в случае необходимости.
Sergey Gorokhov написал: Если этот конкретный сервер сломается, чтобы стоп заявка начала работать, ее надо привязать к другому серверу. Для этого и нужен пункт «Сделать стоп заявку своей». Т.е. Вы подключаетесь к рабочему серверу и делаете стоп своим. Если не сделаете, то стоп не сыграет.
У меня просто ни разу такой ситуации не возникало, поэтому я и не представляю как это на практике выглядит.
Всё это выглядит мудрёно как-то. Если сервер со стоп-заявкой упал, то как другой сервер узнает о наличии оной? Если же сервера между собой обмениваются информацией о стоп-заявках, то почему другой сервер сразу не может подхватить эти стоп-заявки без ручного нажимания на пункт «сделать своей»? Не могу понять этого... получается, стоп-заявка вроде как есть, и сервер о ней знает, но пока не нажмёшь «сделать своей» она работать не будет. Зачем? какая-то избыточная функция лишняя.
Всё так себе и представляю, как вы описали. И стоп-заявки неоднократно ставил, и отключался от сервера, и они сами срабатывали... это всё понятно. Я не могу понять, для чего нужен пункт меню «Сделать стоп заявку своей». В какой момент может возникнуть потребность в этом пункте?
Я вот вначале вообще подумал, что вы так адресацию двухмерного массива делаете, а потом его индекс пытаетесь отсортировать... даже «Альфу» вспомнил, где такой синтаксис применялся, ну да ладно...
Решение вашей задачи есть в книжке по Lua, код оттуда: 19.3 – Sort
Код
BigTab = {}
BigTab[12.2] = {s = 11, f =22}
BigTab[11.1] = {s = 11, f =22}
BigTab[14.1] = {s = 11, f =22}
BigTab[3.32] = {s = 11, f =22}
for k, v in pairs(BigTab) do
print(tostring(k).." = "..tostring(v))
end
print()
function pairsByKeys(t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function () -- iterator function
i = i + 1
if a[i] == nil then return nil
else return a[i], t[a[i]]
end
end
return iter
end
for k, v in pairsByKeys(BigTab) do
print(tostring(k).." = "..tostring(v))
end
Роман написал: У меня по правой кнопке мыши на графике есть пункт "Заменить инструмент".
Чтобы сразу на всех индикаторах в окне поменялось нужно менять инструмент через «Редактировать... \ Диаграмма \ Свойства диаграммы», «Инструмент», кнопка «Изменить». Если через контекстное меню графика менять, то только на выбранном графике будет меняться.
Ирина написал: Смущает sleep(1000). Раз после цикла стоит, он будет прерываться при поступлении нового колбэка?
Этот sleep относится к циклу fRun и нужен для того, чтобы скрипт не завис на бесконечном цикле. В этом случае его невозможно будет остановить кнопкой «Остановить» из окна скриптов. Да и весь Quik при этом также зависнит. Его можно ставить меньше по длительности или больше в зависимости от того, что вы в main делаете. Но он там должен быть обязательно.
На «колбэки» содержание кода в main никак не влияет, так как они исполняются в другом потоке.
Цитата
Ирина написал: Не обращала внимания, что происходит с таблицами в вечерний клиринг... а вечерняя сессия ещё и вялая обычно - не страшно.
На акциях, где нет «вечерки», тоже самое... это не про то речь. Quik если запустить через несколько дней, то он со старыми данными загрузится, они все в таблицах видны. А когда залогинетесь на сервер, то увидите, что все таблицы сбрасываются, а потом загружаются новыми последними данными. Вот в этом месте будет рассинхрон в работе скриптов. Нужно либо это в коде учитывать, либо ручками следить. Вообще, после некоторой практики приспособитесь к этому. В Quik'е вообще много похожих вещей, за которыми нужно либо самому следить, либо писать нетривиальный код их автоматизации.
Цитата
Ирина написал: Вообще, уважаемый Suntor , благодарю за помощь в написании моего маленького скрипта! Вашими усилиями он почти готов. :)))
это очень специфичный термин... можно сказать, что это вообще не термин... в той литературе, где вы это смотрите, в той и надо искать объяснение... такие вещи не относятся к общей биржевой терминологии
if math.abs(b-c) <= 0.123456789 then
print(bla)
end
Только имейте ввиду, что такого рода вычисления и сравнения с числами с плавающей запятой работают с точностью представления десятичных дробей двоичными, а также с точностью по порядку и мантиссе сравнения таких дробей вообще.
Let_it_go написал: Suntor пытаюсь запусить ваш код dll в Visual Studio 2017 Community Такая ошибка возникает при нажатии на "собрать решение". Спасибо за помощь.
У вас включена опция использования предварительно скомпилированных файлов заголовков. Её надо отключить. У меня нет под рукой студии такой же версии, поэтому не могу вам сходу указать, где эта опция отключается. Ищите по названию «Precompiled headers»... в старой VS6.0 это выглядит так:
Ирина написал: В примере с колбэками из "Использование Lua в Рабочем месте QUIK" в main непрерывно проверяется размер таблицы Lua. А без колбэка мог бы также проверяться размер таблицы обезличенных сделок или иной. Чем хуже?
Тут вопрос не в том, хуже или нет. А в том, что код по другому структурирован. Можно в свою таблицу складывать события, а можно из системной их потом вылавливать. Тут есть свои плюсы и минусы. В том числе и с рассинхроном. См. мой пример в пред. сообщении.
Ирина написал: собьется поток main при поступлении нового колбэка?
Например, при таком использовании:
Код
if start = true then
end
start = false
Сразу прокомментирую две ошибки новичка классических. В условии стоит оператор присвоения «=», а не оператор сравнения «==». В Lua такой код отсекается при компиляторе, но в том же Си/Си++ нужно быть внимательным. И сброс переменной условия происходит вне инструкции проверки, а не внутри неё. То-есть, присвоение start = false должно стоять внутри блока условия. Даже, если это не повлияет численно на алгоритм, это стилистическая и логическая ошибка компоновки... это всё несущественно, просто глаз режет...
По самому коду. В принципе, будет работать и так. Если сильно не придираться. Но если уж писать в рамках этой идеи, то надо бы булеву переменную start заменить на счётчик новых сделок. Который инкрементировать в OnAllTrade, и декрементировать в main. В этом случае, это уже будет выглядеть законченным кодом. И в этом случае, можно даже избавиться от вызова getNumberOf.
Я бы вообще написал вот так, с использованием двух переменных начала и конца. Код компилируется и запускается, но проверить на идущей торговой сессии не могу, так как сегодня праздничный неторговый день.
Код
local fRun = true
local first = getNumberOf("all_trades")-1
local last = first
function OnAllTrade(alltrade)
last = last+1
end
function main()
while fRun do
while first ~= last do
first = first+1
local alltrade = getItem("all_trades", first)
if alltrade then
message("Новая сделка № "..tostring(alltrade.trade_num))
end
end
sleep(1000)
end
end
function OnStop(s)
fRun = false
end
В любом случае, у такого кода, одновременно работающего с OnAllTrade и с таблицей all_trades одна проблема. Это рассинхронизация состояния таблицы all_trades. То-есть, если запустить Quik и скрипт в середине торгового дня, то таблица all_trades будет содержать старые сделки за предыдущую торговую сессию. И параметр first будет инициализирован по размеру этих данных. Потом Quik сбросит всю таблицу all_trades в ноль, и начнёт закачку данных за текущую торговую сессию, что займёт несколько минут. Всё это время будут сыпаться OnAllTrade по получаемым сделкам, а в main цикл выборки из таблицы all_trades будет пытаться получить данные по уже несуществующим индексам. Поэтому, такой код можно запускать только дождавшись полной загрузки всей all_trades таблицы за текущую торговую сессию. Можно смотреть в таблицу всех сделок, и когда она полностью загрузится, уже тогда запускать скрипт. То-есть, это отдельная проблема. Она частично решается если работать со своей очередью куда складывать OnAllTrade, но даже в этом случае, тоже нужно отсекать загрузку старых данных за текущую торговую сессию при первом запуске Quik.
Let_it_go написал: В Code Blocks можно выбирать разные компиляторы. Разве это не то что нужно?
Это выбор внутренней конфигурации под требуемый компилятор, но саму конфигурацию нужно ещё настраивать и сам компилятор отдельно устанавливать... выше я кинул уже ссылку на PDF, где описано, как это делать.
rinat написал: в третьем классе? в 9 лет? Вы -гений? :)
«в начальных, но точно не помню», «до 10 лет, не старше», «нет»
Цитата
rinat написал: как-то мне кажется, что финансовый рынок - это не то место, где надо искать легкой жизни
это уже философия... а речь о приземлённой конкретной задаче
Цитата
rinat написал: выше писал форумные лозунги с пунктами, реализация - дело интимное :)
в том то и дело, что это лишь общие наставления были... вы конкретно объясните человеку, каким способом он должен решить свою задачу и сколько времени потребуется на это
Цитата
rinat написал: дилетантизм и верхоглядство - бичь нашей современной реальности.
опять философия... то-бишь попытка уйти от ответа на прямой вопрос: Что первое было у вас в руках по жизни: молоток или диплом? )))
P.S. Предлагаю свернуть полемику или перенести её в раздел «Обмен опытом»... а то мы тут сейчас всю ветку за... своим разговором, не имеющим дело к теме.
Suntor написал: что делают его программы на железном уровне
обучал недавно младшеклассника
спор ради спора или реально не вдумались? :)
я тоже был когда-то младшеклассником... и помню чему меня учили... стек, куча, мантисса, сортировки, деревья, Дональд Кнут был настольной книгой, свою первую программу вообще в машинных кодах писал... видимо я совсем от жизни отстал, и современных школьников учат только делать cout <<... я это могу понять, но согласиться с этим, никак...
Цитата
rinat написал: не читал, но и не говорю ничего слишком узкоспецифичного вроде
вы просто посылаете человека в увлекательное путешествие получать «больше разносторонней инфы»... и моё мнение, что это в данном случае просто усложнит человеку жизнь, и пойдя по этому пути он может в итоге не добраться до пункта назначения в приемлемые сроки
Цитата
rinat написал: именно. именно необходимость такого подхода и вызывает максимальные сомнения ...
предложите свой... и можно будет сравнить, обсудить плюсы и минусы...
Цитата
rinat написал: а вот это кстати только так и правильно ибо и молоток сломает и сам убьется :)
нет, я не согласен... вы когда в первый раз в руки молоток взяли у вас был к этому времени диплом?... )))
Sergey Gorokhov написал: Если будет работать другой сервер то стоп заявка не сработает пока Вы ее не сделаете "своей" (в таблице стоп заявок выполнить пункт "Сделать стоп заявку своей")
Не совсем понятно. У брокера одновременно работают два сервера. Если поставить стоп-заявку на первом сервере, отключиться от него и подключиться ко второму серверу. Стоп-заявка сработает на первом сервере при наступлении её условий?
rinat написал: обучал недавно младшеклассника и оказалось, что таки нет - лучше начинать именно с С++:
Это потому, что вы его учили языку программирования, а не самому программированию как таковому... А это суть две большие разницы. Использование высокоуровневых языков и их абстракций действительно сокращает код и ускоряет процесс написания программ, но к сожалению, за этими конструкциями «леса не видно»... Уж не вспомню сейчас название, но в одной из серьёзных западных компаний даже тест при приёме на работу был такой, человеку давали простые задачи, которые он успешно решал на том же Си++, а потом во второй части собеседования просили объяснить, что делают его программы на железном уровне. Как оказывается большинство вполне неплохих программистов неспособны объяснить и не понимают, во что превращаются их программы после компиляции.
Цитата
rinat написал: возможно ему dll в таком виде и не нужно ... :)
Именно такая и нужна, собственно это и есть тема данной ветки.
Цитата
rinat написал: в итоге: писать надо не под систему или КВИК, а ставить задачи и подбирать системным образом оптимальные инструменты
Если вы не заметили, то находитесь на форуме Quik... ))) Да и предыдущие темы не читали скорее всего. Человеку эта DLL нужна чтобы вынести тяжёлые вычисления из его Lua скрипта. Вполне чёткая задача, ради которой он вообще начал это «обучение». И та задача, которую ему нужно сделать, требует минимум использования базовой математики из обычного Си, плюс добавить шаблон DLL к этому, который я кинул вначале. Никакие Си++, классы, исключения и т.п. ему не нужны... Это тоже самое, что человека пришедшего попросить молоток, чтобы забить гвоздь, послали в техникум учиться на 5 лет, со словами «сначала диплом принеси, а потом молоток получишь».
rinat написал: 1. у С++ - кодера не может быть спокойной жизни по определению.
Это да... поэтому в другой ветке писал, что начинать надо с чистого Си.
Цитата
rinat написал: 2. чем больше разносторонней инфы, тем пушистей извилины.
Но не для новичка... человек только осваивает язык, а щас зароется MinGW и прочую лабудень настраивать... он возненавидит этот Си/Си++ ещё даже не начав... оно надо?
Цитата
rinat написал: 3. на вантузе мир клином не сошелся, особенно в РФ.
Есть хорошее правило, пиши на родных для системы инструментах... человек будет под Quik писать DLL, зачем ему MinGW и GCC? не хочется ругаться, поэтому не буду, но вы поняли...
Let_it_go написал: Я качал эти файлы с сайта lua.org и кидал в папку где лежит моя программа для Си++. CodeBlocks называется.
Судя по вашим словам их можно было не кидать в эту папку, а подключить как то иначе?
Так у вас ничего не получится. У разных компиляторов различный формат библиотечных LIB файлов. Насколько я вижу вы поставили себе «Lua for Windows», которая собрана на MSVC и в комплекте у неё .lib файлы для MSVC. А в качестве среды вы установили себе CodeBlocks с MinGW и компилятором GCC, у которого свой формат LIB файлов с расширением .a. Вы не сможете откомпилировать и слинковать свой проект с такой связкой.
У вас три возможности по CodeBlocks: • Либо настройте CodeBlocks на использование MSVC компилятора, приблизительно как это описано здесь: CodeBlocks_MSVC_setup.pdf • Либо скачайте библиотеки Lua под MinGW отсюда: lua-5.1.5_Win32_dllw4_lib.zip (или отсюда lua-5.1.4-4-mingw32-dev.tar.xz) и дальше пытайтесь слинковаться с ними, если там версии совпадут или не будет ещё какой засады. • Либо скачайте исходники Lua 5.1.5 и соберите из них свой проект и библиотеки под свою версию компилятора в CodeBlocks.
Но мой вам совет, не усложняйте себе жизнь, бросьте вы этот CodeBlocks, поставьте себе MSVC и работайте спокойно.
Andrey.R написал: Поэтому думаю вы не правы. Я не могу верить вам, а не своим глазам когда вижу явные объекты .
)))
Цитата
Andrey.R написал: и это явно видно на графиках (и это факт, а не теория)
)))
Цитата
Andrey.R написал: То что вы дали такой ответ, я вполне вас понимаю. Никто не должен сдавать просто так на форуме свою прибыльную стратегию
)))
Цитата
Andrey.R написал: Я просто хочу элементарное смотреть на график и видеть что еа нем в это время происходит и все.
Как и миллионы других людей... они тоже хотят смотреть на график и видеть то, что в нём происходит... но почему-то получается у очень немногих. Интересно почему?... Могу только сказать, что ваше упорство похвально и идеи которые вы генерируете, но пока они не сработают и не принесут вам реальную прибыль утверждать что вы что-то там видите в графике не стоит. Попробуйте сначала превратить свои идеи в реальные деньги. Могу поспорить, что спустя лет 10 перечитывая свои сегодняшние утверждения про «факты» и «явные объекты» вы будете неистово хохотать... приговаривая: «Боже! Неужели я такое когда-то мог написать...».
Сброс глобальных переменных объявляемых внутри блока:
Код
function save_globals()
old_G = {} for k, v in pairs(_G) do old_G[k]=v end
end
function clear_globals()
for k, v in pairs(_G) do if not old_G[k] then _G[k]=nil end end
end
save_globals()
a, b, c = 5, 10, 15
print(a, b, c)
clear_globals()
print(a, b, c)
Вывод:
Код
5 10 15
nil nil nil
Можно также решить задачу со сбросом глобальных переменных объявленных до блока, но код будет сложнее, с подменой _G через setfenv и метометодами.
Archie_ написал: А если не локальные,то можно как нибудь сбросить?
Если это глобальные переменные и они не были объявлены заранее до указанного блока кода, то можно. Сохранив содержимое глобальной таблицы _G в отдельную переменную перед блоком, а после блока сравнив _G с сохранённой таблицей и обнулив все переменные появившиеся в _G.
Andrey.R написал: Из теории мне кажется, продавать должны
Нет никакой теории, есть рынок со своими причудами... сегодня все продают, и никому не нужно, завтра ажиотажно скупают по бешеным ценам... вы пытаетесь найти ответы на вопросы, на которые написано тысячи книг... люди которые нашли ответы хотя бы на часть этих вопросов, становятся профессионалами и начинают зарабатывать...
Suntor написал: Если цена на базовый актив идёт вверх, то стакан фьюча так же идёт вслед за ним вообще без сделок.
вот это мне совсем непонятно напрочь, какая между ними связь? Есть какая то расчетная величина во время клиринга или прямо в динамике?
прямой связи нет и во время клиринга нет... связь только в конце срока обращения, при погашении/экспирации, но этого достаточно, чтобы фьюч на базовый актив ходил вслед за ценой самого актива с высокой точностью... так устроен рынок... потому что как только фьюч начнёт сильно отклоняться (бэквордация/контанго) от цены базового актива, то можно построить беспроигрышную стратегию на срок обращения такого фьючерса купив корзину из фьюча и базового актива... чем больше отклонение, тем сильнее начинается скупка обоих инструментов с противоположными знаками и отклонение начинает выравниваться... есть формулы разные взаимоувязывающие процентные ставки и спреды между ценами фьючерсов и базовых активов и т.п...
Ирина написал: Прошу развеять сомнения и поправить, если неправильно понимаю принцип работы.
Для начала, посмотрите пример из документации по QLua (https://arqatech.com/upload/iblock/194/quik_lua.zip) В файле Использование Lua в Рабочем месте QUIK.pdf в главе 2. Взаимодействие потоков Lua скрипта пример с разбором, как сделать очередь событий от ф-ций обратного вызова и обработать её в main().
Если долго разглядывать ваш код, то можно познать дзен... шутка... ))) В принципе, если скрипт неторопливый и перерасчитывается раз в секунду, то наверно можно и так сделать как вы. Только обработчик OnStop добавьте и переменную для прерывания цикла в main().
Цитата
Ирина написал: Ну и какой смысл в этом колбэке, если нет реакции на каждый тик? А main итак проверяет все новые тики.
«Колбэки» нужны, когда вам нужна максимальная скорость реакции на события. Если такой задачи не стоит, то можно и без них обойтись в целом.
Смотря какие переменные и из какой области видимости... Для примера, локальные переменные можно сбросить такой вот глобальной функцией:
Код
function clear_locals()
local l = 1 while debug.getlocal(2, l) do debug.setlocal(2, l, nil) l = l+1 end
end
local a = 5
local b = 10
local c = 15
print(a, b, c)
clear_locals()
print(a, b, c)
Andrey.R написал: то что вы написали по идее работать не должно.
ваши идеи и повседневная действительность сильно расходятся... )))
Цитата
Andrey.R написал: а встречных заявок на продажу НЕТ (или значительно меньше на продажу чем на покупку), так как нет желающих продавать - когда график идет вверх и что тогда будет?
То и будет, вы сами ответили, график пойдёт вверх... и будет идти вверх до тех пор, пока не наступит новое равновесие, и количество продающих и покупающих сравняется. Я вам уже писал про алгоритм «двойного аукциона». Если вы программист, то можете на досуге его смоделировать сами и сразу поймёте как работает стакан и как движется график.
Цитата
Andrey.R написал: Объемы пропадут, торговля остановится, инструмент станет неликвидным или что будет?
Бывают ситуации, когда объёмы пропадают совсем. Это вполне заурядное событие, которое вы можете постоянно наблюдать в стаканах малоликвидных инструментов. Можете открыть какой-нибудь и понаблюдать как он торгуется. Заявки на покупку и продажу там ставятся и снимаются время от времени, между ними сохраняется спред и сделки отсутствуют. Если цена на базовый актив идёт вверх, то стакан фьюча так же идёт вслед за ним вообще без сделок. Объёмы равны нулю. Далеко ходить не надо, можно взять тот же рублёвый евро на следующий календарный период (EuU8), или ещё какой-нить похожий фьюч. Просто посидите и понаблюдайте за стаканом, за объёмами на графике и вообще за таблицей всех сделок по этому фьючу, и сразу большинство вопросов отпадёт.
Egor Zaytsev написал: Наименование параметра assured. Значения могут быть "Разрешены" "Запрещены"
В Руководстве пользователя Quik, в разделе QPILE, в таблице идентификаторов параметров GET_PARAM нет такого. И по-видимому ещё каких-то не хватает. А в документации по QLua такая таблица для getParamEx вообще отсутствует. Может стоит обновить эту таблицу до полного списка и добавить её в документацию по QLua... Зарегистрируйте пожелание, пожалуйста.
Andrey.R написал: Если я покупаю в течении минуты 100 лотов по рыночной цене, а больше никто не покупает кроме меня (это такой простой пример), то я собираю все лоты которые выставлены на продажу по текущей цене и выше пока не наберу 100 лотов. Так какой при этом будет объем 100 или 200.
100
Цитата
Andrey.R написал: Я делаю 100 покупок, а кто то при этом делает 100 продаж. Какой объем будет в этом случае?
На бирже в этом случае пройдут сделки на покупку объёмом 100. Поэтому объём по этим сделкам будет равен 100. При этом одни люди продадут 100, а вы купите 100.
Цитата
Andrey.R написал: 1. Объем это количество купленных и проданных лотов по текущему контракту выбранного инструмента за единицу времени (в зависимости от таймфрейма), так?
Объём — это «количество в сделках», по определению!... Купили 5 штук, продали 10, потом ещё купили 15... Объём равен 30 в итоге. Берутся все сделки, которые прошли на бирже, неважно в каком направлении, и складывается количество по всем сделкам.
Цитата
Andrey.R написал: 2. Количество лотов (по объему) на покупку и продажу в единицу времени одно и тоже или разное? И вашего ответа вроде как разное
Количество проданных и купленных инструментов в единицу времени одинаково, но к направлению сделки это не имеет никакого отношения! Потому что направление сделки определяется тем, кто в стакане кого кроет! Один поставил на продажу заявку, и у него висит эта заявка в стакане. А другой долбанул по этой заявке своей заявкой, и купил её. В итоге, сделка будет иметь направление «покупка». Но в результате этой сделки, будет куплено и продано одинаковое количество.
Направление контракта, направление заявки и направление сделки — это три разных сущности! Они между собой никак не связаны.
У вас может быть контракт на покупку, и вы можете поставить по нему заявку на продажу, а в стакане она будет висеть пока по ней кто-то не совершит сделку на покупку, либо сразу исполнится и будет сделка на продажу. И т.д. и т.п. в различных комбинациях.
Ирина написал: У меня в коде нет фильтра по инструменту, но есть в "Заказ данных/ Поток котировок", и код выдает индекс аккурат на 1 меньше номера последней строки в QUIK. Т.е. если ничего не делать с полученной через "Создать окно" таблицей, связь всё-таки есть...
Просто при ваших условиях, у вас эти индексы совпали с точностью до единицы. Но это разные таблицы с разными индексами. Связь там есть в том смысле, что сами ГПИ таблицы как бы берут информацию из главной таблицы «all_trades». Вы попробуйте настроить несколько разных таблиц всех сделок для разных инструментов, у сразу увидите, что там ничего не совпадает. У вас в одной таблице будет 100'000 элементов, в другой 200'000, в третьей 350'000, а в таблице «all_trades» будет при этом сразу 650'000 элементов. И соответственно номера строк в ГПИ таблицах и индекс в «all_trades» совершенно никак не совпадут между собой.
Ирина написал: Порядковый номер строки, который мы видим в таблице Рабочего месте QUIK, не совпадает с индексом этой строки, да?
Это вообще разные таблицы... Таблица с именем «all_trades» это внутренняя таблица Quik, которую вы не видите в ГПИ, а обращаетесь к ней через скрипт. А таблицы которые вы создаёте через «Создать окно / Таблица обезличенных сделок...» это ГПИ таблицы, в которые вы добавляете фильтры, какие инструменты показывать в них. Поэтому, если создадите две таблицы обезличенных сделок по двум инструментам, то будете видеть в них только каждый инструмент по отдельности. А внутренняя таблица «all_trades» будет содержать сделки для обоих этих инструментов вперемешку.
Andrey.R написал: Нашел вот такую фразу, объем на фьючерсах - сколько денег влито в данный момент времени по текущему инструменту, так правильно?
Нет, неправильно. Возможно фраза выдрана из контекста какого-то, где она правильная. Но сама по себе, в прямой интерпретации нет. Объём — это количество в сделках. Это сумма абсолютных величин по продажам и покупкам. Поэтому даже если сначала все купили много всего, а потом всё это продали, то объём будет большой, а вложения в итоге равны нулю. А «сколько денег влито» показывает другой параметр — «Открытый интерес».
Не знаю... я просто расшифровал лог для вас... ))) Но поисковик на вашу ошибку выдаёт массу ссылок, где в основном рекомендуют через Winetricks ставить пакет vcrun6 (или vcrun6sp6).
Andrey.R написал: Цифра 1 объем коричневого цвета значит возможно было 800 контрактов на продажу и 700 на покупку (на продажу больше, чем на покупку). Цифра 2 зеленая значит больше было контактов на покупку и меньше на продажу (к примеру 2000 на покупку и 1000 на продажу)?
Нет, это совсем не то значит. Раскраска графика объёма делается по свечам графика цены. То-есть, цвет столбика на гистограмме объёма совпадает с цветом свечи на графике цены. Ну если цвета на обоих графиках одинаковые выбрали, разумеется...
Цитата
Andrey.R написал: Или не так, и количество контрактов на продажу должно быть равно количеству контрактов на покупку иначе сделка не осуществится? (что то я запутался с объемами)
Нет, не так. Вы путаете тип контракта — «на покупку/на продажу», и операцию с этим контрактом «купля/продажа». Соответственно, количество контрактов разного типа — на продажу и на покупку — одинаково. А весь объём открытых позиций по инструменту — «открытый интерес» — соответственно всегда чётный. Но это совсем другой параметр, не имеющий отношение к графику объёма. Он строится как отдельный график количества открытых позиций.
А вот то, что вы хотели, это разноцветный график объёма отражающий количество в сделках на продажу и в сделках на покупку. Раскраска такого графика должна быть привязана к параметру — «направление сделки» — купля/продажа. Насколько я знаю, хотя возможно я отстал от жизни, в Quik'е можно построить график только по объёму всех сделок, а вот отдельно по объёму сделок на продажу и сделок на покупку нельзя. По объёму заявок отдельно на покупку и отдельно на продажу можно, а вот для сделок нет... И если требуется подобный график, то нужно самому писать скрипт или брать готовый, чтобы строить такие графики по информации из таблицы всех сделок.
Archie_ написал: Вот тут не совсем понятно,("хоть это и не требуется сейчас, но интересно для изучения , на будущее"),а как определить где папка ,где файл и как зайти в подпапку?
Сама команда dir определит. Как я и написал, дважды вставить код вызова dir отдельно с ключами для папок и отдельно для файлов. То-есть: dir /a:d (для папок) dir /a:-d (для файлов) А найденные папки точно также обходить, рекурсивно вызвав саму функцию из себя ещё раз для каждой папки.
Андрей написал: Не могу найти где она у меня зафиксировалась?
Зафиксируется как продадите их... а пока фьючи лежат на счёте, вар. маржа по ним будет плавать в течение сессии и списываться туда/сюда при каждом клиринге.
Цитата
Андрей написал: И ГО тоже нигде не проявилось? (пока все смотрю на демо счете)
Откройте две таблицы: «Ограничения по клиентским счетам (Фьючерсы и опционы)» и «Позиции по клиентским счетам (Фьючерсы и опционы)». Там в них смотрите разные значения. Например, в таблице позиций в столбце «Тек. чист. поз.» будет количество ваших фьючерсов, а в столбце «Вариац. маржа» будет вариационная маржа, которую вам эти фьючерсы насобирали в данный момент. Она постоянно меняется вслед за ценой самих фьючерсов. В другой таблице ограничений в столбце «Тек. чист. поз. (под открытые позиции)» будет размер вашего ГО.
А вообще в разных местах можно смотреть. В таблице «Клиентский портфель» тоже есть эта информация, в столбцах «Вариац. маржа» и «ГО поз.».
Archie_ написал: Suntor ,Спасибо большое !!! Еще вопросик такой ,эта сканирует одну указанную папку и отдает имена,а как сделать "не могу сообразить " что бы подпапки тоже сканировались
Если нужно чтобы всё в итоге линейно в одну таблицу путями попало, то просто добавить ключ /s к команде dir.
А если нужно чтобы создалась структура папок, их подпапок и файлов с именами вложенными таблица в таблицу повторяющими вложение подпапок и файлов в папки, то надо будет писать рекурсивную ф-цию, в которой вставить дважды код из примера с ключами dir отдельно для папок и отдельно для файлов, сохраняя в разные таблицы, и по таблице папок потом рекурсивно вызывать саму ф-цию...
min_stop_order = min_stop_order or stop_order
min_stop_order = (min_stop_order.condition_price <= stop_order.condition_price) and min_stop_order or stop_order
зациклился мой мозг минут на 15 на первой итерации, а на второй ушел на больничный... Если знак не перепутан (ищем мы минимум), поясните, пожалуйста.
Первая строчка — это типовой шаблон-паттерн первичной инициализации переменной с nil значением:x = x or V Если x == nil вначале, то ей будет присвоено значение V, а если x ~= nil, то она будет присвоена сама себе и сохранит значение.
В моём примере первая строчка нужна, чтобы не было ошибки во второй. Так как во второй строчке идёт обращение к элементу .condition_price переменной min_stop_order, и если эта переменная равна nil при первом проходе, то просто произойдёт ошибка обращение к элементу nil таблицы, то-есть (nil).condition_price
Сама вторая строчка, такой же стандартный шаблон-паттерн присвоения по условию: x = (exp) and A or B Если exp == true, то x = A, иначе x = B.
Цитата
Ирина написал: Из спортивного интереса, SearchItems тут сэкономит миллисекунду? Вроде того:
Код
function fn (par)
if par = = 4 then
return true
else
return false
end
end
local i = SearchItems ( "stop_orders" , 0 , getNumberOf ( "stop_orders" ) - 1 , fn, "condition" )
local min_stop_order = nil
for i = 0 , # i - 1 do
local stop_order = getItem ( "stop_orders" , i)
min_stop_order = min_stop_order or stop_order
min_stop_order = (min_stop_order.condition_price < = stop_order.condition_price) and min_stop_order or stop_order
end
Наоборот, перебор такой же по времени, но при этом написали лишний код, усложнили, добавили выделением памяти под таблицу индексов и пр... К тому же, у вас там ряд ошибок. Переменной i обозначили как саму таблицу индексов, так и сам индекс. А также убрали одну из проверок на возврат getItem значения nil, что лучше не делать, даже если вы уверены, что по индексам вам не должно вернуться nil. Это просто неправильный стиль программирования. Проверки на ошибки должны присутствовать всегда.
P.S. Смотрю, с утра были бурные обсуждения пары строчек кода... )))
local min_stop_order = nil
for i=0,getNumberOf("stop_orders")-1 do
local stop_order = getItem("stop_orders", i)
if stop_order and stop_order.condition == 4 then
min_stop_order = min_stop_order or stop_order
min_stop_order = (min_stop_order.condition_price <= stop_order.condition_price) and min_stop_order or stop_order
end
end
Ирина написал: Suntor , с фильтрацией согласна. Но тянуть каждый getItem-ом... Сколько времени уйдет на сотню заявок? table.sort сама б не нашла, спасибо.
А без getItem сами элементы не получите, SearchItems возвращает таблицу только с индексами этих элементов... таков порядок работы этих ф-ций... 100 заявок это мало. Уйдут миллисекунды на современных ПК разумеется... ))) Ну вы можете конечно в саму ф-цию fn для SearchItems сразу в тело встроить сохранение найденных элементов куда вам надо.
Да и вообще, то что вы описали можно сделать без всяких сортировок в одном цикле прохода по таблице стоп-заявок. Ну типа такого: Поиск стоп-заявки на продажу с минимальной стоп-ценой:
Код
local condition_price = nil
local min_stop_order = nil
for i=0,getNumberOf("stop_orders")-1 do
local stop_order = getItem("stop_orders", i)
if stop_order and stop_order.condition == 4 then
condition_price = condition_price or stop_order.condition_price
min_stop_order = min_stop_order or stop_order
if condition_price > stop_order.condition_price then
condition_price = stop_order.condition_price
min_stop_order = stop_order
end
end
end
— код написал от руки, прямо сюда, не проверяя... доработайте его напильником, перепроверьте... но суть думаю понятна.