Веб-приложение: https://github.com/malcolmrite-dsi/JSE_Researcher

Репозиторий: https://share.streamlit.io/malcolmrite-dsi/jse_researcher/main/main.py

Введение

В качестве финального проекта интенсивной программы по науке о данных в Африке я решил отправиться в путешествие, чтобы сократить время, необходимое для исследования компании, котирующейся на фондовой бирже Йоханнесбурга (JSE), путем предоставления всех данных и анализа. в одном месте, с некоторой помощью машинного обучения кое-где.

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

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

Что касается качества, я сосредоточился на двух основных направлениях. Что, если Сценарии или красные флажки, а также предыстория компании. Что касается количественной стороны, двумя основными направлениями были финансовый анализ и прогноз цен на акции. На схеме ниже показана структура проекта. Сначала я опишу свои усилия по инструментам качественного исследования.

Используемые инструменты

Основным языком программирования, используемым в этом проекте, был Python. В основном это было связано с простотой использования, особенно с библиотеками обработки данных.

Для веб-развертывания я выбрал Streamlit в качестве оружия. Это простая в использовании библиотека веб-приложений на основе Python с собственной бесплатной платформой для развертывания. Сделать выбор легким.

Я использовал модуль FPDF для создания отчетов в формате PDF для функции генератора. Он записывает функции, отображаемые в приложении, в формате PDF.

Код и репозиторий со всем обучением, которое я использовал, находятся в моем репозитории GitHub здесь.

Качественное исследование

Что, если сценарии (анализатор новостей)

Первой особенностью, на которой я сосредоточился, была функция красного флага. Этот аспект исследования компании не следует путать с количественными инструментами, относящимися к этому. Здесь мы хотели бы определить, насколько негативным или позитивным может показаться компания в СМИ.

Анализ настроений NLTK Vader

Для этой функции анализ настроений оказался правильным инструментом для определения того, как компания воспринимается в новостях. Имея это в виду, я выбрал готовый Анализ настроений Вейдера из Инструментария естественного языка. Я выбрал эту модель по трем основным причинам:

  1. Это было относительно быстро по сравнению с более сложной нейронной сетью, такой как Flair. Около 20+ заголовков анализируются за 10 секунд, по сравнению с одним заголовком, анализируемым за 4+ секунды.
  2. Другие пользовательские модели, основанные на биржевых новостях, выдавали те же ошибки, что и Вейдер, но требовали большей сложности.
  3. Это давало легко интерпретируемую партитуру.

Как это работает? Итак, модель анализирует каждое слово заголовка и дает каждому слову оценку воспринимаемой положительности или отрицательности этого слова. Затем эти оценки суммируются и нормализуются от -1 (наиболее отрицательный) до +1 (наиболее положительный). Пакет также предоставляет вероятности того, является ли текст нейтральным, положительным или отрицательным.

Все, что требуется для включения анализатора, - это установить пакет из NLTK и загрузить лексику для пакета, чтобы определить положительные и отрицательные оценки для каждого слова.

from nltk.sentiment.vader import SentimentIntensityAnalyzer
import nltk
#Installing the lexicon for the VADER package
@st.cache
 def download_lexicon():
 nltk.download(‘vader_lexicon’)

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

def add_label(score):
 if score < -0.5:
 label =”Negative”
 elif score < -0.05:
 label =”Slightly Negative”
 elif score < 0.05:
 label =”Neutral”
 elif score <= 0.5:
 label =”Slightly Positive”
 else:
 label =”Positive”
 return label

Реализация веб-приложений

Для реализации веб-приложения у пользователя была возможность анализировать новости для отдельной компании или сектора на JSE. Затем отобразится соответствующий раскрывающийся список. Пользователь может пролистать список или ввести конкретный код доступа или сектор, который они ищут. На рисунке 2 показаны реализованные варианты.

Ползунок под раскрывающимся списком позволяет пользователю ввести заданное количество страниц, которые следует проанализировать. Эти страницы для компании копируются прямо со страницы компании на MoneyWeb. Код для этой операции ниже. Каждая страница может содержать до 12 статей.

def get_news_headlines(html):
#Initialise two lists to store the headlines and the links retrieved for the sector
 all_company_headlines = []
 all_company_links = []
 soup = BeautifulSoup(html, ‘lxml’)
#This finds the artcles on the page
 newspage = soup.find_all(‘h3’, class_= “title list-title m0005”)
#Iterate over each article
 for headline in newspage:
 #Extracting the headline text
 headline = headline.find(“a”)
#Extracting the headline link
 newslink = headline.get(“href”)
headline = headline.text.strip()
#Append the news link and headline to the list
 all_company_links.append(newslink)
 all_company_headlines.append(headline)
return all_company_links, all_company_headlines

Последний вариант - хотел ли пользователь сводный или подробный анализ. В резюме был получен средний балл всех проанализированных заголовков и найдены наиболее положительные и отрицательные заголовки. На рисунке 3 показан пример итогового результата.

Что не сработало

Изначально я надеялся реализовать функцию резюмирования текста для годовых отчетов выбранной компании. Однако реализация стала слишком непрактичной, поскольку форматирование, используемое в документах PDF, не могло хорошо переводиться в текстовый формат Python. Это испортило простую текстовую модель и не произвело ничего значимого из лучшего практического примера SMMRY.

Последние SENS

Эта функция была реализована в первую очередь для того, чтобы связать общую функцию для любого веб-сайта финансовых новостей. Для пользователя использовались аналогичные опции из новостного анализатора. Вывод - это просто полный текст указанного количества элементов SENS, запрошенных пользователем. На рис. 4 показаны затраты на это. Информация берется из Профильных данных через BusinessLive.

Что не сработало

Резюмирование текста также было предпринято с помощью функции SENS, как и в случае с ежегодными отчетами, в данных SENS было много проблем с форматированием, которые делали результаты непригодными или информативными. Проблемы с форматированием также мешали подходу с адаптированной моделью LSTM. Никаких дополнительных усилий по этому конкретному обобщению не предпринималось, поскольку влияние успешного результата могло не иметь такого же воздействия, как у анализатора новостей.

История компании

Реализация этой функции аналогична последней SENS, однако она просто дает возможность выбрать компанию для отображения фона. Вывод делится на две части: основная информация о компании, которая была извлечена из Money Web, и детали команды управления, которые были извлечены из Yahoo Finance. На рисунке 5 показан результат.

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

def get_management(html):
 all_persons = []
 soup = BeautifulSoup(html, ‘lxml’)
 managepage = soup.find(‘table’, class_= “W(100%)”)
 managepage = managepage.find_all(‘tr’)
 for person in managepage:
#Initialise list for each person
 details = []
 person = person.find_all(‘span’)
 for field in person:
 #Populate the details for a person in the management team with this list
 details.append(field.text.strip())
 #Add the details to the larger list of of the management staff
 all_persons.append(details)
return all_persons

Количественные исследования

Финансовый анализ

Из-за важности количественных данных при оценке инвестиций обеспечение успеха этой функции было главным приоритетом. Основная цель этой функции заключалась в том, чтобы предоставить релевантную финансовую информацию об акции и отобразить ее таким образом, чтобы ее можно было относительно легко интерпретировать за минимально возможное время. Как для секторов, так и для отдельных компаний я добился этого с помощью двух основных методов: графиков и показателей оценки. Для веб-приложения разрешалось отображать только один тип финансовой информации для каждого запроса, это было сделано для минимизации количества информации, отображаемой в приложении. Отчет в формате PDF действительно включал все анализы за один раз как по отдельной компании, так и по сектору.

Графики

Что касается графиков, самый простой способ автоматически построить их, не беспокоясь о данных, которые в них бросают, - это использовать библиотеку Matplotlib.pyplot. Для всех графиков в основном использовался график точечной диаграммы. На рисунке 6 показан пример этого ниже, для отображения были выбраны только самые важные значения.

В части анализа сектора каждой акции в секторе была предоставлена ​​отдельная ячейка, чтобы дать общее представление о тенденциях для каждой акции. Из-за ограничений функции подзаголовков в Matplotlib последняя доля сектора будет повторяться до тех пор, пока строка не будет завершена, что приведет к некоторым необработанным результатам, на Рисунке 7 это показано в действии. Код приведен ниже для справки.

tot_count = 0
#If there are more than five shares in the sector
 if rowLen > 1:
 fig, ax = plt.subplots(nrows = rowLen, ncols = colLen, figsize=(16, 16))
for row in ax:
 for col in row:
 #Get the share code of the company to be graphed next on the sector list
 code = sharecodes[tot_count]
 try:
 #Display the share code on the graph, to identify the info
 col.title.set_text(code)
 currency, dates, name = FinancialAnalyser.plot_chart(col, col, code, analysis)
 col.set_xticklabels(dates, rotation=45)
#If there’s an error in the graphing process, the message below is displayed
 except Exception as inst:
 st.write(f”{code} {analysis} Data is Not Available” )
 
 tot_count += 1
 if len(sharecodes) == tot_count:
 tot_count -= 1

Метрики оценки

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

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

Прогноз цен на акции

В качестве дополнительной функции я рассмотрел возможность использования прогнозиста цен на акции с использованием машинного обучения. Из-за нехватки времени я мог использовать только модели ARIMA для 40 крупнейших компаний на JSE. Это связано с доступностью данных и богатым набором данных, которые они содержат. Реализованный код основан на этой статье. Пользователю разрешается запрашивать прогнозы только на одну неделю вперед. Распечатанное значение прогноза рассчитывается на основе сегодняшней цены и прогнозируемого значения в будущем. Значение достоверности рассчитывается на основе ошибки между сегодняшней ценой и ценой на момент завершения обучающих данных.

Что не сработало

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

Генератор PDF

В качестве последней функции для одного из результатов проекта был разработан PDF-генератор, позволяющий пользователю сохранять анализ, который они хотят провести, для дальнейшего чтения. Использовался модуль FPDF, так как это наиболее удобный модуль для создания PDF-файлов на Python.

Большинство основных функций, доступных в приложении, можно было создать в отчете. Обзор веб-страницы представлен ниже на Рисунке 9.

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

Вывод

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