Блог им. vitales

Скрипт lua читающий таблицу обезличенных сделок.

Всем привет. Может кому пригодится. Скрипт читает ленту сделок и раз в минуту подсчитывает разницу между покупками и продажами. Часть кода нашел в интернете часть кода написал сам. Не знаю может уже есть что то подобное. Цель была не написать что то оригинальное, а наработать навыки программирования на lua.
TICER = "SBER";
CLASS_CODE = "TQBR";

stopped = false;
t_id = nil
H = -1;
M = -1;
VSELL = 0;
VBUY  = 0;

function OnInit()
        CreateTable();
end 

function main() 
  while not stopped do 
     if IsWindowClosed(t_id) then
        stopped = true;
     end        
     sleep(100);
  end
end

function CreateTable()
   t_id = AllocTable(); 
   AddColumn(t_id, 0, "Время", true, QTABLE_STRING_TYPE, 10);
   AddColumn(t_id, 1, "BUY", true, QTABLE_INT_TYPE, 15);
   AddColumn(t_id, 2, "SELL", true, QTABLE_INT_TYPE, 15);
   AddColumn(t_id, 3, "Дельта V", true, QTABLE_INT_TYPE, 15);   
   AddColumn(t_id, 4, "Цена", true, QTABLE_DOUBLE_TYPE, 15);
   tab = CreateWindow(t_id);
   SetWindowCaption(t_id, TICER.." Баланс покупок/продаж");
   SetTableNotificationCallback(t_id, EventCallBack);
end

function OnAllTrade(alltrade)
        if alltrade.sec_code == TICER then      
                  fl = tostring(alltrade.flags);
                  if H==alltrade.datetime.hour then
                        if M==alltrade.datetime.min then
                           if fl == "1025" then VSELL = VSELL+alltrade.qty; end --Продажа
                           if fl == "1026" then VBUY  = VBUY+alltrade.qty;  end                         
                        else               
                           M=alltrade.datetime.min;
                           --Rows --срока   Coll -- Колонка
                           InsertRow(t_id, -1);
                           local Rows, Col = GetTableSize(t_id);                           
                           local Delta = VBUY-VSELL;
                           --local t = tostring(alltrade.datetime.hour)..":"..tostring(alltrade.datetime.min);
                           local t = tostring(H)..":"..tostring(M);
                           SetCell(t_id, Rows-1, 0, t);
                           SetCell(t_id, Rows-1, 1, tostring(VBUY));
                           SetCell(t_id, Rows-1, 2, tostring(VSELL));                      
                           SetCell(t_id, Rows-1, 3, tostring(Delta));
                           SetCell(t_id, Rows-1, 4, tostring(alltrade.price));
                           
                           if Delta<0 then Red(Rows-1,3); end
                           if Delta>0 then Green(Rows-1,3); end
                           if Delta==0 then Yellow(Rows-1,3); end
                           if fl == "1025" then VSELL = alltrade.qty; end --Продажа
                           if fl == "1026" then VBUY  = alltrade.qty; end                               
                        end
                  else                   
                         H = alltrade.datetime.hour;
                         M = alltrade.datetime.min;
                  end
        end
end
function Red(row,col)
        SetColor(t_id, row, col, RGB(255,0,0), RGB(0,0,0), RGB(255,0,0), RGB(0,0,0));
end
function Yellow(row,col)
        SetColor(t_id, row, col, RGB(240,240,0), RGB(0,0,0), RGB(240,240,0), RGB(0,0,0));
end
function Green(row,col)
        SetColor(t_id, row, col, RGB(0,200,0), RGB(0,0,0), RGB(0,200,0), RGB(0,0,0));
end


function EventCallBack(t_id, msg, par1, par2)
   if msg==QTABLE_CLOSE then
     OnStop();
   end;
end

function OnStop(s)
  if t_id ~= nil then
    DestroyTable (t_id);
  end;
   stopped = true;
end
  • обсудить на форуме:
  • QUIK
★51
35 комментариев
скинь в блокноте, плиз
avatar
bohemian rhapsody, Не знаю как тут файл прикрепить. Зарегистрировался недавно, пока еще не разобрался до конца как ту что работает.
avatar
Виталий, пошлите на почту, плиз, адрес в личке
avatar
А теперь новое ТЗ:
Сделать тоже самое, но для всех ликвидных и в одной таблице, причем два разных скрипта: Фондовый и Срочный.


Просто для каждого тикера отдельно запускать смысла… мало.

пысы, со скриптом неполадки или я летом на лыжах. У меня такие минутные дельты получились. У вас еще с общим объемом сделок не коррелирует. Инструмент юзал для фюьча RIM0, может там собака зарыта.



avatar
Винни Пух, для всех? У вас из за OnAllTrade() Quik встанет.
avatar
3Qu, для ликвидов, и у меня же не встает =)
avatar
Винни Пух, OnAllTrade() не встает?
avatar
3Qu, неа, тьфу тьфу тьфу.
Фильтрую нужные инструменты на входе при заказе данных.
avatar
Винни Пух, Я думая над этим, но пришел к выводу, что тогда в таблице будет неупорядоченная «каша» если туда все инструменты писать. 
avatar
Виталий, сделать одну функцию для всех инструментов, и вызывать ее с соответствующими параметрами. И каши не будет. Будет один большой порядок.)
avatar
3Qu, Это понятно, что алгоритм должен быть универсальный. Просто как данные из разных инструментов запихнуть в одну таблицу. Тогда надо для каждого инструмента создавать отдельную таблицу.
avatar
Виталий, варианта два: либо горизонтально, либо вертикально. В соотв. колонках/строках наименование инструмента или тикера и потом остальные аналитические данные.
Что-то вроде этого:



avatar
Винни Пух, Можно наверно и так, но тогда, допустим если в колонках писать дельту то для каждого инструмента будет грубо говоря 1440 колонок. Если брать 24 торговых часа по 60 минут в каждом. Надо тогда увеличивать интервал и считать часовую дельту тогда колонок будет 24 для одного инструмента. 
avatar
Виталий, а зачем исторические данные в таблице? Нужны только свежие, их и добавлять, с удалением старых в логи или куда то еще по мере надобности. Так что и трех колонок хватит. В зависимости от ТФ, день, 4H, 1H, 15M, 1M и т.п. 
avatar
Винни Пух, Если так, то это думаю будет работоспособный вариант. Можно брать тикер инструмента из таблицы текущих торгов и уже после получения данных в OnAllTrade() обновлять таблицу.
avatar
Винни Пух, Возможно в скрипте ошибка, и минуты пишет не верно со смещением. Например данные были за 30-тую минуту, а в таблице пишется 31-вая минута. И еще он считает не объем в деньгах, а кол-во лотов в ленте сделок.
avatar
полезная штука. Я подобное писал, правда в виде индикатора, который по любому инструменту работает. По сути своей индикатор Дельта для квика написал, ибо не хватало прям для счастья. Для практики программирования рекомендую прописать в скрипт функцию восстановления данных по всем имеющимся обезличенным сделкам :) Без нее мне было грустно с индикатором 
avatar
Vitaliy, Я пока не знаю какую из этого скрипта можно извлечь практическую пользу. Предполагаю, что информацию из него можно использовать скальперам. В свободное время подумаю, что еще полезного можно будет туда добавить. Может быть накопленную дельту раз в час в дополнении к минутной дельты. 
avatar
Виталий, Ох поверьте, пользу можно извлечь просто потрясающую и даже, отчасти, провидческую :) Ибо только активные объемы правят миром. Я изначально собирал и обрабатывал эту информацию скриптом типа Вашего и перегонял в эксель и там обрабатывал. Потом под квик все создал и сбор информации, и восстановление и обработку и анализ. У меня есть пару старых постов на тему того, как с помощью плюс-минус такой методики можно делать красивейшие входы в сделки.

В общем там такой себе граальчик своего рода, если правильно обработать и посмотреть на данные ) Под верным углом, так сказать :)
avatar
Vitaliy, :) Я только начинаю с этим разбираться, так что у меня все еще впереди. Надо будет почитать ваши посты.
avatar
Виталий, там ничего ценного особо, кроме показанных для примера точек входа. Когда изобрел сие чудо с доработками своими не мог поверить своему счастью и боялся торговать сигналы эти, потом чинил это все в голове и потихоньку уверовал в систему. Системность наше все :)
avatar
Vitaliy, какая доходность у граальчика?
avatar
Не помню, есть ли у самодельных таблиц экспорт по DDE. Такие данные, по идее, нужно в Excel VBA обрабатывать, и уже выводить там в таблицы в обработанной форме.
Делаю так, но не с Quik.
avatar
3Qu, Можно паралельно с выводом в таблицу еще писать в текстовый файл, а потом этот файл обрабатывать в другой программе.
avatar
Виталий, да, вариант, только это надо делать в потоке main(). В Lua для этого есть средства. См. потоки (нити) Lua.
avatar
3Qu, Понял, спасибо почитаю об этом.
avatar
Виталий, Кстати, все ваши данные лучше извлекать не из OnAllTrade, а из текущей свечи. Примерно так:

function main()
— подписка на получение данных свечи
ds_s, Err1 =CreateDataSource (EX_CODE, FUT_S, INTERVAL_M1)
if Err1 == "" or Err1 == nil then
message(«Пока ОК 1»)
while not (ds_s:Size() >0) do
sleep(10)
end
— определение функции обратного вызова
Err1 = ds_s:SetUpdateCallback (cbCandleS)
if Err1 == true then
message(«cb1 OK»)
else
message(«Err1»… tostring(Err1))
end
else
message(«Ошибка 1»… Err1)
end

Это уже не в main()

— изменение свечи S и запись в БД (получение реал-тайм данных)
function cbCandleS(i) --
local dt ={}
local evt =0
dt = GetCandle(ds_s, FUT_S, i)
--message(«Изменение свечи S»)
a, b = CCS.cvCandleS(dt)
--message( «CCS.cvCandleS(dt) »… a)
end


avatar
3Qu, а разве из свечи Вы сможете вытащить данные для дельты? Я имею ввиду не общий объем, а именно направление рыночных сделок
avatar
Vitaliy, да, эт вряд ли смогу, не учел. 
Я все получаю и свечи и сделки

function OnAllTrade(alltrade)
if alltrade.sec_code == FUT_S or alltrade.sec_code == FUT_L then
--message(«Обезлич сделка beg »… alltrade.sec_code)
at ={alltrade.datetime, alltrade.sec_code, alltrade.trade_num, alltrade.flags, alltrade.price,
alltrade.qty, alltrade.value, alltrade.period}
CCS.AllTrade2DB(at)
--message(«Обезлич сделка end »… alltrade.sec_code)
end
end



avatar
3Qu, Я понял, что мы подписываемся на получение данных заданного инструмента и когда происходит изменение свечи выполняем какие то действие. Только не понял, что за объект или структура CCS. Она пишет данные в БД? Пока не знаю как с помощью GetCandle() получить данные о том какое действие вызвало изменение свечи. Покупка или продажа и какой был объем.
avatar
CCS. func_name() — это вызовы функций DLL, которая все пишет в базу данных и обрабатывает данные.
avatar
3Qu, Получается это какая то ваша собственная разработка реализованная в виде DLL. Я пока в это не лезу, мне бы со встроенными функциями разобраться для начала.
avatar
Виталий, имхо, и напрасно.
Если почитать Р.Иерузалимски, то Lua не самостоятельный язык, а язык расширяемый и расширяющий. Т.е., он изначально разрабатывался не для самостоятельного применения, а для взаимодействия с другими программами.
В общем, я этой концепции и придерживаюсь, Луа обеспечивает только передачу данных в ПО и взаимодействие ПО с терминалом. Вся обработка на стороне, в нормальных средах программирования с большими возможностями.
avatar
3Qu, Саму книгу не читал, но видел инфу в интернет, о том что lua лучше использовать совместно со сторонними DLL, это вроде как снижает нагрузку на терминал и дает больше простора для творчества. У меня тут вопрос возник, если не сложно подскажите как мне средствами lua получить вот такую информацию о инструменте.



avatar
Все, спасибо вроде уже сам разобрался.
avatar

теги блога Виталий А

....все тэги



UPDONW
Новый дизайн