Алгоритм анализа файлов SEC EDGAR с помощью Elixir.

Все публично торгуемые компании и отдельные лица используют EDGAR — электронную систему сбора, анализа и поиска данных — для подачи необходимых, срочных документов в Комиссию по ценным бумагам и биржам США.

Система Edgar предоставляет доступный веб-интерфейс, который позволяет любому искать эти документы. Для тех, кто, возможно, не знает, что именно ищет, или заинтересован в самостоятельном изучении данных; SEC предоставляет ежедневные индексы данных, доступных для скачивания.

Вот как я проанализировал текстовое содержимое индексных файлов сканера. В файле crawler.20210122.idx файлы edgar представлены в виде строк текста с такой схемой:

Я провел несколько выборочных проверок и визуально проверил данные. Поля записи кажутся разделенными пробелами. Я предполагал, что значения полей не будут содержать последовательные пробелы и что пробел между значениями полей будет содержать не менее 2 последовательных пробелов. Это показалось мне разумным предположением, поскольку это упростило бы код для анализа этих записей.

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

Функция должна как минимум пройти следующий тест:

Мой первый подход выглядел так:

«Как изящно и просто!» — подумал я, чувствуя гордость за себя. Я разделяю строку вокруг разделителя, обрезаю все начальные и конечные пробелы, а затем отфильтровываю все пустые строки.

К моему большому огорчению, мои предположения оказались неверными…

Просматривая данные регистрации, моя программа сломалась на человеке, у которого были последовательные пробелы между его фамилией и именем. ☹️

Функция также должна пройти этот тест:

Еще больше усложняет ситуацию то, что названия компаний могут вообще не содержать пробелов. Типы форм также могут содержать пробелы! Эта схема довольно дикая и грязная, мне это не нравится, но я могу с этим смириться.

См. также:  Разверните свое приложение Symfony на Heroku

Нам нужно будет написать более надежную функцию синтаксического анализа для обработки этих дополнительных случаев:

 

Я немного подумал об этом и придумал алгоритм, который проходит все тесты, но…

Мой красивый элегантный код, кажется, превратился в чудовище! ?

Общая идея алгоритма состоит в том, чтобы пройти по строке в обратном порядке (от конца к началу), идентифицировать значения и создать их список за один проход.

Давайте посмотрим глубже, чтобы понять, что здесь происходит.

Я использую функцию Enum.reduce для перебора индексов строки и отслеживания своего состояния. В моем состоянии я слежу за тремя вещами:

  1. Список значений, которые я извлек на данный момент.
  2. Индекс того, где в общей строке заканчивается текущее значение.
  3. Логическое значение, определяющее, является ли текущий индекс частью значения или нет.

Далее, в моей вызванной функции у меня есть 5 условий, которые я обрабатываю:

  1. Я уже извлек все 5 значений, ничего не делать.
  2. Текущий индекс не находится в значении, и я смотрю на что-то, что не является пробелом… должно быть, это конец значения! Я переворачиваю логическое значение и отмечаю конец значения.
  3. Текущий индекс — это значение, и если я уже нашел 4 других значения и не смотрю на пробел… это должно быть окончание названия компании! Извлеките имя и добавьте его в наш список значений.
  4. Текущий индекс — это значение, и я смотрю на пробел, и следующий символ — тоже пробел… это должно быть начало значения! Извлеките значение, добавьте его в наш список и укажите, что мы больше не находимся в значении.
  5. Ни одно из приведенных выше условий не было выполнено, ничего не делайте.

В конце концов, я просто возвращаю значения, извлеченные во время редукции.

См. также:  Найти и вернуть диапазоны всех вхождений данной строки в Swift

Есть вопросы или лучший алгоритм? Дай мне знать в комментариях!

Понравилась статья? Поделиться с друзьями:
IT Шеф
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: