Файл CSV-формата это обычный текстовый файл, с которым Excel и аналогичные программы могут работать как с таблицей. Каждая строка таблицы в этом файле записывается как новая строка со знаком переноса в конце, а значения полей разделены между собой каким-то символом, чаще ";". В самой первой строке такого файла можно (не обязательно) указать названия столбцов, так же через ";".
Ниже приведен пример создания такого файла и записи в него данных о совершенных сделках средствами QLua(Lua):
Код скрипта QLua
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; |
Скрипт создает файл следующего вида:
Если у Вас появились какие-то вопросы, задайте их в комментариях под статьей !!!
ДОбрый день! Я взяла ваш скрипт и исопльзую его в своем роботе, но есть сложность: у меня все роботы пишут каждую сделку, не свою, а каждую, при этом как автора сделки ставят именно себя. Как это можно обойти?
Код могу выслать
Здравствуйте, поставьте фильтр по № сделки.
А лучше, при выставлении заявки, делать ее описание (поле brokerref), тогда достаточно 1-го робота (переделать пример выше), который будет писать сделки в разные файлы с именем файла содержащим текст из поля brokerref.
Я правильно понимаю, что название можно указывать в поле комментарии ? Для акций у меня такой фокус не сработал, а для фьючей жду первую сделку. Это, конечно, решило бы вопрос.
Здравствуйте. Поле комментарий составное 20 символов, включая разделитель. Для акций: код_клиента//комментарий. Для срочного рынка просто комментарий.
Спасибо огромное! Очень выручили:)
Рад помочь;)
Да, сделки можно писать и в один файл, просто добавить поле комментарий, а потом фильтровать в экселе.
Приветствую Вас уважаемые создатели ресурса. Прежде всего хочу поблагодарить Вас за ваше невероятное терпение и "веру в человечество" (стремление и желание обучать чайников типа меня).
Я попробовал использовать приведённый выше пример скрипта "ИЗ QLUA (LUA) В EXCEL (CSV)" на срочном рынке. Фьючерс сбер.
Идёт запись только первой половины сделки (покупка для лонга и продажа для шорта) да и та не вся. Лонг 1 лот. Шорт - 5 лотов был разбит на 2-2-1 (за одину продажу, но лоты разных покупателей). Записано было только 2 лота.
Вопрос: возможно ли, что эта ошибка связана со старой версией квика 7.29.0.40? Только не ржите надо мной )))
Немного покопавшись, я обнаружил
- при экспорте из таблицы сделок через ДДЕ-сервер, номера сделок в эксель сбрасываются с округлением до 10 000 (естественно, что они воспринимаются как один номер), т.е рубится 5 знаков справа.
- экспортный файл сохраняемый на диск скриптом вообще выдает формат типа "1.9534635126301e+018" они различаются по номеру заявки. Номер Сделок же всех - "на одно лицо".
Стало очевидно, что проблема возникает из-за невозможности правильно считать 19 значный номер старым софтом.
Приношу извинения за флуд, т.к. не хотелось отвлекать достопочтенную публику по пустякам.
Здравствуйте, подскажите почему может не работать данный скрипт с файлом формата .XLSX ? В коде везде поменял формат файла.
Здравствуйте, потому что CSV - это обычный текстовый файл, который понимает программа Excel а .XLSX это файл Excel, с ним как с обычным текстовым невозможно работать.
Привет. Вопрос. Есть csv файл с 3 строками.
1я - "Первая"
2я - "Вторая"
3я - "Третья"
Возможно ли перезаписать какую либо строку. Например вторую - "Получилось Ура". Получить результат:
1я - "Первая"
2я - "Получилось Ура"
3я - "Третья"
Привет! Формат .csv от обычного .txt практически ничем отличается, можно чуть больший данных объем записать и аля-excel сразу его преобразуют в таблицу.
Поэтому работать с этим файлом нужно как с обычным текстовым.
Считываем строки в массив, меняем нужную строку, переписываем весь файл, если такие изменения частые, то работаем с массивом, а переписываем файл по завершении скрипта и/или в OnClose() терминала.
может пригодится для работы с .csv
Дмитрий, привет! Добавь пожалуйста пример по замене точки на запятую и обратно в описание функции gsub
в примере проклятый копипаст, вот так правильно
Есть ли объяснение не зеркального синтаксиса при обратной замене знака? Почему в первом случае перед точкой стоит %, а запятая в кавычках, а при обратной замене запятая в кавычках без %, а точка в двойных квадратных скобках?
И еще, допустимо ли менять строку А, перезаписывая результат в саму себя:
A = string.gsub(A, “%.”, “,”)?
Спасибо, суть идеи понятна
Всегда пожалуйста
Спасибо за ценную информацию!
Скажите, что на Ваш взгляд считается «часто» при перезаписи в файл? Например перезапись раз в 10 секунд, это часто? И если часто, то записывая изменения в массив, какая частота записи данных из массива в файл будет оптимальной? Раз в минуту, раз в час?….