Блог им. vitales

Скрипт lua Баланс покупок/продаж

Всем привет. Переделал первоначальную версию скрипта. Исправил некоторые ошибки и немного расширил функционал. Теперь скрипт может сохранять данные в текстовый файл, который потом можно анализировать в другой программе (например exсel). Также, в отличии от первого варианта, скрипт показывает в таблице усредненную цену, по которой прошли сделки. В первом варианте отображалась цена последней сделки. И в скрипте добавлен показ накопленной дельты за все время пока скрипт работает.

TICER = "SBER";
CLASS_CODE = "TQBR";
FilePath = getScriptPath() .. "\\export.txt";--путь к файлу
save = false;--сохранять данные в файл если false нет, true да

f = nil;
stopped = false;
t_id = nil
H = -1;
M = -1;
VSELL = 0;
VBUY  = 0;
CDelta = 0;
CountTrans = 0;
PriceTrans = 0.0; 
t = "";
function OnInit()
    CountTrans = 0;
        if save then f = io.open(FilePath,"w"); end
        CreateTable();
end 

function main() 
        while not stopped do 
          if IsWindowClosed(t_id) then
         stopped = true;
      end       
          sleep(10);
        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, 10);
   AddColumn(t_id, 2, "SELL", true, QTABLE_INT_TYPE, 10);
   AddColumn(t_id, 3, "Дельта V", true, QTABLE_INT_TYPE, 10);   
   AddColumn(t_id, 4, "AVG Цена", true, QTABLE_DOUBLE_TYPE, 15);
   AddColumn(t_id, 5, "Накопленная Дельта", true, QTABLE_INT_TYPE, 15);
   AddColumn(t_id, 6, "Кол-во сделок", true, QTABLE_DOUBLE_TYPE, 12);   
   tab = CreateWindow(t_id);
   local NAME = tostring(getParamEx(CLASS_CODE,TICER,"LONGNAME").param_image);
   SetWindowCaption(t_id, TICER.." ("..NAME..") Баланс покупок/продаж");
   SetTableNotificationCallback(t_id, EventCallBack);
end

function Calc(alltrade)
        if bit.test(alltrade.flags, 0) then VSELL = VSELL+alltrade.qty;  --Продажа
        else VBUY  = VBUY+alltrade.qty;  end                            
        CountTrans = CountTrans+1;
        PriceTrans = PriceTrans+alltrade.price;                 
end

function OnAllTrade(alltrade)    
        if alltrade.sec_code == TICER then      
                local Rows, Col = GetTableSize(t_id);
                
                if H==-1 or H~= alltrade.datetime.hour then 
                        H = alltrade.datetime.hour;
                        M = alltrade.datetime.min;
                        t = tostring(alltrade.datetime.hour)..":"..tostring(alltrade.datetime.min);
                end
                if M==alltrade.datetime.min then
                        Calc(alltrade);
                else                                    
                M=alltrade.datetime.min;        
                        InsertRow(t_id, -1);                                               
                        local Delta = VBUY-VSELL;
                        Price = PriceTrans/CountTrans;
                        SetCell(t_id, Rows, 6, tostring(CountTrans));                   
                        SetCell(t_id, Rows, 0, t);
                        SetCell(t_id, Rows, 1, tostring(VBUY));
                        SetCell(t_id, Rows, 2, tostring(VSELL));                           
                        SetCell(t_id, Rows, 3, tostring(Delta));
                        local SEC_SCALE = tostring(getParamEx(CLASS_CODE,TICER,"SEC_SCALE").param_value);
                        SEC_SCALE = string.format("%.0f",SEC_SCALE);                    
                        SetCell(t_id, Rows, 4, string.format("%."..SEC_SCALE.."f", tostring(Price)));
                   if Rows>=2 then
                           local OldPrice = tonumber(GetCell(t_id,Rows-1,4).image);
                           if OldPrice>Price then 
                                        Red(Rows,4); 
                           else 
                                        Green(Rows,4);
                           end
                           CDelta = tonumber(GetCell(t_id,Rows-1,5).image);
                           CDelta = CDelta + Delta;                        
                        else 
                          CDelta = Delta;
                        end
                        SetCell(t_id, Rows, 5, tostring(CDelta));
                    if Delta<0 then Red(Rows,3); end
                    if Delta>0 then Green(Rows,3); end
                    if CDelta<0 then Red(Rows,5); end
                    if CDelta>0 then Green(Rows,5); end                                                   
                   if save then
                                local Str = tostring(H)..";"..tostring(M)..";"..tostring(VBUY)..";"..tostring(VSELL)..";"
                                                ..tostring(Delta)..";"..tostring(Price)..";"..tostring(CDelta);
                           Str=Str.."\n";
                           SaveFile(Str);
                        end
                t = tostring(alltrade.datetime.hour)..":"..tostring(alltrade.datetime.min);                        
                    VBUY = 0;VSELL = 0;
                        PriceTrans = 0;
                        CountTrans = 0;
                        Calc(alltrade);
                end
        end --if alltrade.sec_code == TICER then        
end

function SaveFile(Str)
        if f ~= nil then 
                f:write(Str);           
                f:flush();                               
        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 f ~= nil then f:close(); end
  if t_id ~= nil then
    DestroyTable (t_id);
  end;
  stopped = true;
end



★39
Пиши исчо 
avatar

Винни Пух

данные лучше пишите в csv — удобнее потом анализировать excel`ем. Можно на поток настроить, только надо, чтобы csv закрыт был файл. Ну это лирика. А еще рекомендую сделать цикл по таблице обезличенных сделок, чтобы не копить данные, а просчитать все имеющиеся :)
avatar

Vitaliy

Vitaliy, В комментариях к первому варианту мне предлагали что то подобное сделать, пока руки не доходять, мало свободного времени. Я этот вариант почти неделю делал и отлаживал. Не удобно в квик нет отладчика, да и опыта программирования на lua мало. Встроенная справка не очень помогает. А в текстовом файле в качестве символа разделителя используется точка запятая как и в csv файлах. Если поменять расширение файла, то он без проблем откроется в эксель.
avatar

Виталий

Виталий, Возможно, я и предлагал. Мои пути развития данного скрипта были следующие: сначала я сделал бота, который собирал информацию и складывал в csv, позже я научил его разделять по заданному интервалу, чтобы удобнее было анализировать (суммировал по минутам, по 5 минут — как задам), потом анализируя эксель и балуя с этим всем мракобесием, я нашел своего рода грааль и его превратил в индикатор для Квика. Потом шлифовка для быстродействия и тд. В общем поле деятельности тут есть — массивы освоите потихоньку в процессе :)
avatar

Vitaliy

Vitaliy, Понятно, спасибо за подсказки. 
avatar

Виталий

Vitaliy, 
А еще рекомендую сделать цикл по таблице обезличенных сделок, чтобы не копить данные, а просчитать все имеющиеся :)
каждый расчет скрипта пробегать циклом таблицу обезличенных сделок?
avatar

Андрей К

Андрей К, Зачем же каждый?! Достаточно при запуске. 
avatar

Vitaliy

код сохранять как *.luac? сохранил как *.lua — не работает
avatar

Glago

Glago, Файл скрипта, должен иметь расширение lua. Почему не работает, ошибку выдает? После запуска скрипта сначала появляется пустая таблица. Скрипту необходимо некоторое время что бы собрать данные за 1 минуту. После этого таблица будет пополнятся данными раз в 1 минуту.
avatar

Виталий

Виталий, никакой ошибки не выдает, просто висит пустое окно и на 2 и 3… минуты. хз квик 8.4.1.6 Win 10 Pro x64. Скрипты из этого и прошлого поста запускал из *.luac файла, работает! Среда Lua на компе не установлена, и lua не прописан в PATH. Я копировал отсюда код в NotePad++ (кодировка по умолчанию ANSI), потом в нём сохранял как *.lua и *.luac. Из первого не запускалось, поменял на *.luac и заработало. Но всё равно поставил за пост +) 
avatar

Glago

Glago, Странно, я не знаю почему у вас с расширением Lua не работает.  У меня версия квик такая же. Тоже 64 бит, только ось Win 7.  Ни каких дополнительных программ не устанавливал. Скачал дистрибутив от брокера, установил, и кроме настроек рабочего места больше ни чего не трогал.
avatar

Виталий

Виталий, получается разница только в ОСях. Про финт с луак видел на форуме квика примерно год назад. Подробностей по той теме сейчас уже не помню, поскольку плохо ориентируюсь в программировании)
avatar

Glago

Glago, Я точно не уверен, но возможно это как то связано именно с ОС. Вероятно, что в вашей ОС расширение luac ассоциировано с языком LUA. А расширение lua ОС не воспринимает. У меня работает как с расширением lua так и с расширением luac. Специально проверил у себя поменяв расширение файла на luac.
avatar

Виталий

ещё в прошлом скрипте обнаружился баг, когда не двузначные минуты некорректно отображаются)



avatar

Glago

Glago, Это не совсем баг. Преобразуя числовое значение в строковое, впереди просто не добавляются незначащие нули. То есть запись 23:3 это есть 23 часа 03 минуты. Но «03» это строка числа 03 не бывает. Попробуйте в экселе в числовую ячейку напишите 03 эксель преобразует его в 3. 
avatar

Виталий

Я чего-то не вкурил: TICER это переменная? вместо неё мы можем написать абракадабра = «инструмент? если это переменная почему она явно не объявляется или в луа это необязательно?
avatar

Glago

Glago, Глобальная переменная. В ней пишешь код нужного инструмента. В lua нет необходимости предварительно объявлять переменную и указывать ее тип.
avatar

Виталий

ВАЖНО! Недопустим вызов функций Clear и DestroyTable для t_id внутри функции обратного вызова f_cb, назначенной на таблицу с данным t_id.
avatar

protorus

protorus, Почему?
avatar

Виталий

Виталий, А кто его знает? Просто запомнил, что так написано в источниках которые встречал. Но я это все равно проверил и ничего подозрительного не обнаружил.
Например, здесь https://arqatech.com/upload/iblock/194/quik_lua.zip. Интерпретатор языка Lua.pdf. Раздел 3.15.16.
Хотя может сам не так понял.
avatar

protorus

protorus, Да, действительно написано, что не допускается. О причинах ни чего не сказано. Но у меня вроде работает, ошибок времени выполнения нет. 
avatar

Виталий

спасибо
avatar

Infomax

скажите, как и где изменить накопление на другой интервал? 15 минут к примеру
avatar

Infomax

Infomax, В этом скрипте такого нет. Накопленная дельта считается за все время пока сприпт работает. Если будет свободное время попробую сделать такую возможность.
avatar

Виталий

Виталий, спасибо

avatar

Infomax


....все тэги
2010-2020
UPDONW