Блог им. 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



★46 | ₽ 22
26 комментариев
Пиши исчо 
avatar
данные лучше пишите в csv — удобнее потом анализировать excel`ем. Можно на поток настроить, только надо, чтобы csv закрыт был файл. Ну это лирика. А еще рекомендую сделать цикл по таблице обезличенных сделок, чтобы не копить данные, а просчитать все имеющиеся :)
avatar
Vitaliy, В комментариях к первому варианту мне предлагали что то подобное сделать, пока руки не доходять, мало свободного времени. Я этот вариант почти неделю делал и отлаживал. Не удобно в квик нет отладчика, да и опыта программирования на lua мало. Встроенная справка не очень помогает. А в текстовом файле в качестве символа разделителя используется точка запятая как и в csv файлах. Если поменять расширение файла, то он без проблем откроется в эксель.
avatar
Виталий, Возможно, я и предлагал. Мои пути развития данного скрипта были следующие: сначала я сделал бота, который собирал информацию и складывал в csv, позже я научил его разделять по заданному интервалу, чтобы удобнее было анализировать (суммировал по минутам, по 5 минут — как задам), потом анализируя эксель и балуя с этим всем мракобесием, я нашел своего рода грааль и его превратил в индикатор для Квика. Потом шлифовка для быстродействия и тд. В общем поле деятельности тут есть — массивы освоите потихоньку в процессе :)
avatar
Vitaliy, Понятно, спасибо за подсказки. 
avatar
Vitaliy, 
А еще рекомендую сделать цикл по таблице обезличенных сделок, чтобы не копить данные, а просчитать все имеющиеся :)
каждый расчет скрипта пробегать циклом таблицу обезличенных сделок?
avatar
Андрей К, Зачем же каждый?! Достаточно при запуске. 
avatar
код сохранять как *.luac? сохранил как *.lua — не работает
avatar
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, Странно, я не знаю почему у вас с расширением Lua не работает.  У меня версия квик такая же. Тоже 64 бит, только ось Win 7.  Ни каких дополнительных программ не устанавливал. Скачал дистрибутив от брокера, установил, и кроме настроек рабочего места больше ни чего не трогал.
avatar
Виталий, получается разница только в ОСях. Про финт с луак видел на форуме квика примерно год назад. Подробностей по той теме сейчас уже не помню, поскольку плохо ориентируюсь в программировании)
avatar
Glago, Я точно не уверен, но возможно это как то связано именно с ОС. Вероятно, что в вашей ОС расширение luac ассоциировано с языком LUA. А расширение lua ОС не воспринимает. У меня работает как с расширением lua так и с расширением luac. Специально проверил у себя поменяв расширение файла на luac.
avatar
ещё в прошлом скрипте обнаружился баг, когда не двузначные минуты некорректно отображаются)



avatar
Glago, Это не совсем баг. Преобразуя числовое значение в строковое, впереди просто не добавляются незначащие нули. То есть запись 23:3 это есть 23 часа 03 минуты. Но «03» это строка числа 03 не бывает. Попробуйте в экселе в числовую ячейку напишите 03 эксель преобразует его в 3. 
avatar
Я чего-то не вкурил: TICER это переменная? вместо неё мы можем написать абракадабра = «инструмент? если это переменная почему она явно не объявляется или в луа это необязательно?
avatar
Glago, Глобальная переменная. В ней пишешь код нужного инструмента. В lua нет необходимости предварительно объявлять переменную и указывать ее тип.
avatar
ВАЖНО! Недопустим вызов функций Clear и DestroyTable для t_id внутри функции обратного вызова f_cb, назначенной на таблицу с данным t_id.
avatar
protorus, Почему?
avatar
Виталий, А кто его знает? Просто запомнил, что так написано в источниках которые встречал. Но я это все равно проверил и ничего подозрительного не обнаружил.
Например, здесь https://arqatech.com/upload/iblock/194/quik_lua.zip. Интерпретатор языка Lua.pdf. Раздел 3.15.16.
Хотя может сам не так понял.
avatar
protorus, Да, действительно написано, что не допускается. О причинах ни чего не сказано. Но у меня вроде работает, ошибок времени выполнения нет. 
avatar
спасибо
avatar
скажите, как и где изменить накопление на другой интервал? 15 минут к примеру
avatar
Infomax, В этом скрипте такого нет. Накопленная дельта считается за все время пока сприпт работает. Если будет свободное время попробую сделать такую возможность.
avatar
Виталий, спасибо

avatar

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

....все тэги



UPDONW