Файл CSV-формата это обычный текстовый файл, с которым Excel и аналогичные программы могут работать как с таблицей. Каждая строка таблицы в этом файле записывается как новая строка со знаком переноса в конце, а значения полей разделены между собой каким-то символом, чаще ";". В самой первой строке такого файла можно (не обязательно) указать названия столбцов, так же через ";".
Ниже приведен пример создания такого файла и записи в него данных о совершенных сделках средствами QLua(Lua):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | Run = true; -- Флаг поддержания работы скрипта TradeNums = {}; -- Массив для хранения номеров записанных в файл сделок (для предотвращения дублирования) -- Вызывается терминалом QUIK в момент запуска скрипта function OnInit() -- Создает, или открывает для чтения/добавления файл CSV в той же папке, где находится данный скрипт CSV = io.open(getScriptPath().."/MyTrades.csv", "a+"); -- Встает в конец файла, получает номер позиции local Position = CSV:seek("end",0); -- Если файл еще пустой if Position == 0 then -- Создает строку с заголовками столбцов local Header = "Дата и время;Код класса;Код бумаги;Номер сделки;Номер заявки;Операция;Цена;Количество\n" -- Добавляет строку заголовков в файл CSV:write(Header); -- Сохраняет изменения в файле CSV:flush(); end; end; -- Основная функция скрипта (пока работает она, работает скрипт) function main() -- Цикл, поддерживающий работу скрипта while Run do sleep(100); end; end; -- Вызывается терминалом QUIK в момент остановки скрипта function OnStop() -- Выключает флаг, чтобы остановить цикл while внутри main Run = false; -- Закрывает открытый CSV-файл CSV:close(); end; -- Функция вызывается терминалом QUIK при совершении Вами новой сделки -- (обычно вызывается по 2 раза для каждой сделки) function OnTrade(trade) -- Перебирает массив с номерами записанных сделок (в обратном порядке) for i=#TradeNums,1,-1 do -- Если данная сделка уже была записана, выходит из функции if TradeNums[i] == trade.trade_num then return; end; end; -- Если мы здесь, значит сделка не была найдена в числе уже записанных -- Добавляет в массив номер новой сделки TradeNums[#TradeNums + 1] = trade.trade_num; -- Вычисляет операцию сделки local Operation = ""; if CheckBit(trade.flags, 2) == 1 then Operation = "Продажа"; else Operation = "Покупка"; end; -- Создает строку сделки для записи в файл ("Дата и время;Код класса;Код бумаги;Номер сделки;Номер заявки;Операция;Цена;Количество\n") local TradeLine = os.date("%c", os.time(trade.datetime))..";".. trade.class_code..";".. trade.sec_code..";".. trade.trade_num..";".. trade.order_num..";".. Operation..";".. trade.price..";".. trade.qty.."\n"; -- Записывает строку в файл CSV:write(TradeLine); -- Сохраняет изменения в файле CSV:flush(); end; -- Функция возвращает значение бита (число 0, или 1) под номером bit (начинаются с 0) в числе flags, если такого бита нет, возвращает nil function CheckBit(flags, bit) -- Проверяет, что переданные аргументы являются числами if type(flags) ~= "number" then error("Ошибка!!! Checkbit: 1-й аргумент не число!"); end; if type(bit) ~= "number" then error("Ошибка!!! Checkbit: 2-й аргумент не число!"); end; local RevBitsStr = ""; -- Перевернутое (задом наперед) строковое представление двоичного представления переданного десятичного числа (flags) local Fmod = 0; -- Остаток от деления local Go = true; -- Флаг работы цикла while Go do Fmod = math.fmod(flags, 2); -- Остаток от деления flags = math.floor(flags/2); -- Оставляет для следующей итерации цикла только целую часть от деления RevBitsStr = RevBitsStr ..tostring(Fmod); -- Добавляет справа остаток от деления if flags == 0 then Go = false; end; -- Если был последний бит, завершает цикл end; -- Возвращает значение бита local Result = RevBitsStr :sub(bit+1,bit+1); if Result == "0" then return 0; elseif Result == "1" then return 1; else return nil; end; end; |
Run = true; -- Флаг поддержания работы скрипта TradeNums = {}; -- Массив для хранения номеров записанных в файл сделок (для предотвращения дублирования) -- Вызывается терминалом QUIK в момент запуска скрипта function OnInit() -- Создает, или открывает для чтения/добавления файл CSV в той же папке, где находится данный скрипт CSV = io.open(getScriptPath().."/MyTrades.csv", "a+"); -- Встает в конец файла, получает номер позиции local Position = CSV:seek("end",0); -- Если файл еще пустой if Position == 0 then -- Создает строку с заголовками столбцов local Header = "Дата и время;Код класса;Код бумаги;Номер сделки;Номер заявки;Операция;Цена;Количество\n" -- Добавляет строку заголовков в файл CSV:write(Header); -- Сохраняет изменения в файле CSV:flush(); end; end; -- Основная функция скрипта (пока работает она, работает скрипт) function main() -- Цикл, поддерживающий работу скрипта while Run do sleep(100); end; end; -- Вызывается терминалом QUIK в момент остановки скрипта function OnStop() -- Выключает флаг, чтобы остановить цикл while внутри main Run = false; -- Закрывает открытый CSV-файл CSV:close(); end; -- Функция вызывается терминалом QUIK при совершении Вами новой сделки -- (обычно вызывается по 2 раза для каждой сделки) function OnTrade(trade) -- Перебирает массив с номерами записанных сделок (в обратном порядке) for i=#TradeNums,1,-1 do -- Если данная сделка уже была записана, выходит из функции if TradeNums[i] == trade.trade_num then return; end; end; -- Если мы здесь, значит сделка не была найдена в числе уже записанных -- Добавляет в массив номер новой сделки TradeNums[#TradeNums + 1] = trade.trade_num; -- Вычисляет операцию сделки local Operation = ""; if CheckBit(trade.flags, 2) == 1 then Operation = "Продажа"; else Operation = "Покупка"; end; -- Создает строку сделки для записи в файл ("Дата и время;Код класса;Код бумаги;Номер сделки;Номер заявки;Операция;Цена;Количество\n") local TradeLine = os.date("%c", os.time(trade.datetime))..";".. trade.class_code..";".. trade.sec_code..";".. trade.trade_num..";".. trade.order_num..";".. Operation..";".. trade.price..";".. trade.qty.."\n"; -- Записывает строку в файл CSV:write(TradeLine); -- Сохраняет изменения в файле CSV:flush(); end; -- Функция возвращает значение бита (число 0, или 1) под номером bit (начинаются с 0) в числе flags, если такого бита нет, возвращает nil function CheckBit(flags, bit) -- Проверяет, что переданные аргументы являются числами if type(flags) ~= "number" then error("Ошибка!!! Checkbit: 1-й аргумент не число!"); end; if type(bit) ~= "number" then error("Ошибка!!! Checkbit: 2-й аргумент не число!"); end; local RevBitsStr = ""; -- Перевернутое (задом наперед) строковое представление двоичного представления переданного десятичного числа (flags) local Fmod = 0; -- Остаток от деления local Go = true; -- Флаг работы цикла while Go do Fmod = math.fmod(flags, 2); -- Остаток от деления flags = math.floor(flags/2); -- Оставляет для следующей итерации цикла только целую часть от деления RevBitsStr = RevBitsStr ..tostring(Fmod); -- Добавляет справа остаток от деления if flags == 0 then Go = false; end; -- Если был последний бит, завершает цикл end; -- Возвращает значение бита local Result = RevBitsStr :sub(bit+1,bit+1); if Result == "0" then return 0; elseif Result == "1" then return 1; else return nil; end; end;
Скрипт создает файл следующего вида:
Если у Вас появились какие-то вопросы, задайте их в комментариях под статьей !!!