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

  • Анализ настроений по финансовому рынку
  • Анализ настроений с помощью Python
  • Определение лидеров роста и падения с помощью API Polygon
  • Использование анализа настроений в качестве торгового сигнала
  • Прогнозирование настроений фондового рынка с помощью OpenAI и Python

Анализ настроений по финансовому рынку

В этой статье мы обсудим, как анализ настроений влияет на финансовый рынок, основы NLP (обработка естественного языка) и продемонстрируем, как обрабатывать финансовые заголовки по пакетам для создания индикатора настроений рынка.

Станьте участником Medium, чтобы продолжить обучение без ограничений. Я получу небольшую часть вашего членского взноса, если вы воспользуетесь следующей ссылкой, без дополнительных затрат с вашей стороны.

Что такое анализ настроений

Представьте себе,

Вы первоклассный трейдер на Уолл-стрит. Однажды утром вы читали газету, потягивая чашку американо из своей любимой кружки. Вы наслаждаетесь прекрасным солнечным светом, проливающимся на вас. Внезапно ваше внимание привлекла одна новость. В новостях, казалось, говорилось о недавно выпущенном продукте и финансовом прогнозе компании. После прочтения всей статьи пессимистический тон всей статьи начал вас беспокоить. Вы поглаживаете подбородок и начинаете размышлять: «Может быть, мне стоит сбросить акции, которые я купил вчера»…

Созерцательное фото Дариуса Башара с сайта Unsplash

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

В чем заключается применение анализа настроений на финансовом рынке

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

Введение в НЛП

НЛП — это междисциплинарная область информатики и лингвистики, и ученые в этой области посвящают себя тому, чтобы обобщить языки, которые мы используем, в лингвистические правила, а затем научить компьютеры понимать и даже говорить на языках. В настоящее время уже существуют продукты искусственного интеллекта, созданные для того, чтобы иметь возможность вести разговоры с людьми, такие как ChatGPT от OpenAI, Bard от Google и Claude от Anthropic. Все это современные продукты искусственного интеллекта, которые пользователи могут применять в своей повседневной жизни. Однако в этой статье мы не будем касаться ни одного из них. Вместо этого мы возвращаемся к основам, используя NLTK (Natural Language Tool Kit) чтобы продемонстрировать, как мы можем преобразовать предложение в числовую оценку настроений, чтобы помочь нам быть более информированными, чем другие розничные инвесторы.

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

Процессы NLP для векторизации текста

Токенизация

NLP-процессы: Токенизация

Токенизация, как следует из названия, заключается в том, чтобы разбить предложение на слова и стандартизировать эти слова в лексемы, которые можно рассматривать единогласно, выполнив следующие шаги:

Разделите документ/предложение слово за словом

Это самый первый шаг к обработке текстового ввода документа.import nltk

# This is the lexicon for processing text. We’re going to talk about it later
nltk.download(‘punkt’)

corporas = «AMD’s Q3 earnings report exceeded Wall Street’s expectations. \
Its growth indicates the PC market has finally bottomed out. ……»

print(nltk.sent_tokenize(corporas))
>>> [«AMD’s Q3 earnings report exceeded Wall Street’s expectations.»,
‘Its growth indicates the PC market has finally bottomed out.’,
‘……’]

print(nltk.word_tokenize(corporas))
>>> [‘AMD’, »’, ‘s’, ‘Q3’, ‘earnings’, ‘report’, ‘exceeded’, ‘Wall’, ‘Street’, «‘s», ‘expectations’, ‘.’, ‘Its’, ‘growth’, ‘indicates’, ‘the’, ‘PC’, ‘market’, ‘has’, ‘finally’, ‘bottomed’, ‘out’, ‘.’, ‘……’]

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

Удаление символов и знаков препинания

В приведенном выше списке токенов мы видим множество знаков препинания, таких как ', ., или ..., разбросанных тут и там по всему списку. Несмотря на то, что они что-то значат, когда объединяются в предложение, их удаление на самом деле не помешает нам или машине понять общую структуру предложения.tokens = [x for x in nltk.word_tokenize(corporas) if x.isalpha()]

print(tokens)
>>> [‘AMD’, ‘s’, ‘earnings’, ‘report’, ‘exceeded’, ‘Wall’, ‘Street’, ‘expectations’, ‘Its’, ‘growth’, ‘indicates’, ‘the’, ‘PC’, ‘market’, ‘has’, ‘finally’, ‘bottomed’, ‘out’]

Удаление стоп-слов

Стоп-слова — это набор общих слов, которые добавляют много смысла в предложение. Например, если вы хотите узнать, «как приготовить кусок стейка в духовке», вы, вероятно, погуглите ключевые слова «cook», «steak» и oven». How, к, aof и with будут считаться стоп-словамиto так как они содержат меньше информации, чем остальные слова. Стоп-слова на самом деле используются в каждом языке (но, возможно, не в языках программирования, лол).from nltk.corpus import stopwords

# Again, another lexicon that contains all the stop words
nltk.download(‘stopwords’)

stop_words = set(stopwords.words(‘english’))
tokens_wo_stop_words = [x for x in tokens if x not in stop_words]

print(tokens_wo_stop_words)
>>> [‘AMD’, ‘earnings’, ‘report’, ‘exceeded’, ‘Wall’, ‘Street’, ‘expectations’, ‘Its’, ‘growth’, ‘indicates’, ‘PC’, ‘market’, ‘finally’, ‘bottomed’]

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

Стемминг и лемматизация

Процессы НЛП: стемминг и лемматизация

В английском языке существует множество вариаций одной распространенной корневой формы. Например, слово love имеет формы loves (глагол), loved(глагол), loving(прилагательное), loves(n). Эти вариации действительно помогают людям понять контекст намерений говорящих, но неизбежно создают двусмысленность для модели машинного обучения, чтобы уловить ключевой момент в документе. Поэтому крайне важно дополнительно обработать эти варианты, а затем преобразовать их в идентичную форму, которая не запутает модель машинного обучения. Stemming или lemmatization — это методы, которые по-разному помогают найти общую корневую форму вариантов слов, но в конечном итоге оба они направлены на достижение одной и той же цели.

Словари
Прежде всего, давайте поговорим о лексиконах. Лексиконы являются основой методов стемминга и лемматизации. Это похоже на словарь, который нужно искать при поиске корневой формы варианта слова. Поэтому выбор правильных лексиконов для использования очень важен для обработки слов в данном документе. LIWCHarvard’s General InquirerSeticNet и SentiWordNet являются самыми известными лексиконами. Мастер-словарь Лограна-Макдональда является одним из самых популярных экономических лексиконов. SentiBigNomics — это подробный финансовый словарь, специализирующийся на анализе настроений. В этом лексиконе задокументировано около 7300 терминов и корневых форм. Кроме того, если вы хотите провести анализ тональности по сравнению с биомедицинской статьей, WordNet for Medical Events (WME) может быть вашим лучшим выбором.

Вытекающие
Стемминг — это процесс уменьшения морфологических аффиксов из вариантов слов, оставляя только основу слова. Грамматическая роль, время и словообразовательная морфология будут убраны, останется только основа слова, которая является общим корнем. Например, и любовь, loves и loving будут возвращаться к корню love. Тем не менее, у стемминга есть и темная сторона, которая иногда приводит к неприятным последствиям. Слова universaluniversity и universe имеют разные значения, но имеют один и тот же корень univers, если вы примете метод стемминга. Это цена, которую вам придется заплатить, потому что стемминг предлагает более быстрый и простой способ извлечения текстовых объектов.from nltk.stem import PorterStemmer
ps = PorterStemmer()

for w in tokens_wo_stop_words:
print(f'{w}: {ps.stem(w)}’)
>>> AMD: amd
>>> earnings: earn
>>> report: report
>>> exceeded: exceed
>>> Wall: wall
>>> Street: street
>>> expectations: expect
>>> Its: it
>>> growth: growth
>>> indicates: indic
>>> PC: pc
>>> market: market
>>> finally: final
>>> bottomed: bottom

Лемматизация
Напротив, лемматизация может лучше обнаружить корневую форму вариаций слов ценой принесения в жертву производительности скорости. Лемматизация использует более толстый лексикон для сравнения и сопоставления, чтобы найти корневую форму. Следовательно, он вернет более точное слово по сравнению с стеммингом. Кроме того, лемматизация учитывает и часть речи. Например, lemmatize saw даст вам see, если вы относитесь к нему как к глаголуsaw, и saw, если вы относитесь к нему как к существительному.from nltk.stem import WordNetLemmatizer
nltk.download(‘wordnet’)
nltk.download(‘omw-1.4’)
lemmatizer = WordNetLemmatizer()

print(f’AMD: {lemmatizer.lemmatize(«AMD», pos=»n»)}’)
>>> AMD: AMD

print(f’earnings: {lemmatizer.lemmatize(«earnings», pos=»n»)}’)
>>> earnings: earnings

print(f’report: {lemmatizer.lemmatize(«report», pos=»n»)}’)
>>> report: report

print(f’exceeded: {lemmatizer.lemmatize(«exceeded», pos=»v»)}’)
>>> exceeded: exceed

print(f’Wall: {lemmatizer.lemmatize(«Wall», pos=»n»)}’)
>>> Wall: Wall

print(f’Street: {lemmatizer.lemmatize(«Street», pos=»n»)}’)
>>> Street: Street

print(f’expectations: {lemmatizer.lemmatize(«expectations», pos=»n»)}’)
>>> expectations: expectation

print(f’Its: {lemmatizer.lemmatize(«Its», pos=»n»)}’)
>>> Its: Its

print(f’growth: {lemmatizer.lemmatize(«growth», pos=»n»)}’)
>>> growth: growth

print(f’indicates: {lemmatizer.lemmatize(«indicates», pos=»v»)}’)
>>> indicates: indicate

print(f’PC: {lemmatizer.lemmatize(«PC», pos=»n»)}’)
>>> PC: PC

print(f’market: {lemmatizer.lemmatize(«market», pos=»n»)}’)
>>> market: market

print(f’finally: {lemmatizer.lemmatize(«finally», pos=»r»)}’)
>>> finally: finally

print(f’bottomed: {lemmatizer.lemmatize(«bottomed», pos=»v»)}’)
>>> bottomed: bottom

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

Различия между стеммингом и лемматизацией

Тегирование частей речи

После того, как вы узнали о силе лемматизации, вы, вероятно, захотите спросить: «Эй! Если я собираюсь указать часть речи каждого отдельного слова, это уже не эффективно». Не волнуйтесь. NLTK хорошо продуман и создал эту часть речи в качестве одного из своих подпакетов. Вы просто передаете свои токены в качестве параметров в функцию nltk.pos_tag() и предопределенный тег части речи будет возвращен вместе с токенами в виде кортежей. Затем вы можете дополнительно определить функцию, чтобы заменить возвращаемый тег pos простым набором [n, v, adj, adv, conj, ...] что значительно упростит лемматизацию.nltk.download(‘averaged_perceptron_tagger’)

nltk.pos_tag(tokens_wo_stop_words)
>>> [(‘AMD’, ‘NNP’), (‘earnings’, ‘NNS’), (‘report’, ‘NN’), (‘exceeded’, ‘VBD’), (‘Wall’, ‘NNP’), (‘Street’, ‘NNP’), (‘expectations’, ‘NNS’), (‘Its’, ‘PRP$’), (‘growth’, ‘NN’), (‘indicates’, ‘VBZ’), (‘PC’, ‘NN’), (‘market’, ‘NN’), (‘finally’, ‘RB’), (‘bottomed’, ‘VBD’)]

NER (распознавание именованных сущностей) и фрагментация

Что такое NER (распознавание именованных сущностей)? Лёгкий. Возьмем, к примеру, New York Statue of Liberty. Должны ли мы токенизировать это как New, Статуя of Liberty, или вместо этого должны быть New York и Statue of LibertyYorkStatue Именованная сущность — это уникальное имя для мест, людей, вещей, локаций и т. д. Эту комбинацию слов не следует рассматривать как несколько лексем. Вместо этого его следует рассматривать как один токен. Вот почему нам нужно перегруппировать слова и найти названные сущности, чтобы уменьшить вероятность запутать наши следующие шаги.nltk.download(‘maxent_ne_chunker’)
nltk.download(‘words’)

tagged_token = nltk.pos_tag(tokens_wo_stop_words)
nltk.chunk.ne_chunk(tagged_token)

for chunk in nltk.chunk.ne_chunk(tagged_token):
if hasattr(chunk, ‘label’):
print(chunk.label(), ‘ ‘.join(c[0] for c in chunk))
>>> FACILITY Wall Street

processed_token = [(‘ ‘.join(c[0] for c in chunk), chunk.label()) if hasattr(chunk, ‘label’) else chunk for chunk in nltk.chunk.ne_chunk(tagged_token)]
>>> [(‘AMD’, ‘NNP’), (‘earnings’, ‘NNS’), (‘report’, ‘NN’), (‘exceeded’, ‘VBD’), (‘Wall Street’, ‘FACILITY’), (‘expectations’, ‘NNS’), (‘Its’, ‘PRP$’), (‘growth’, ‘NN’), (‘indicates’, ‘VBZ’), (‘PC’, ‘NN’), (‘market’, ‘NN’), (‘finally’, ‘RB’), (‘bottomed’, ‘VBD’)]

Видеть! Wall Street была объединена в одно слово как именованная сущность.

ХОРОШО!

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

VADER (Valence Aware Dictionary и sEntiment Reasoner)

VADER — это модель, встроенная в NLTK, которая предназначена для оценки эмоциональной интенсивности предложения. VADER не только определяет, является ли предложение положительным или отрицательным, но также оценивает уровень интенсивности предложения, оценивая, насколько позитивным или отрицательным является данное предложение. Вот еще несколько фактов о VADER:

  • VADER возвращает четыре значения для каждой оценки предложения: положительный уровень, отрицательный уровень, нейтральный уровень и составная оценка.
  • Он учитывает эмоциональное воздействие специальных знаков препинания, таких как !!! и !?, а также смайликов, таких как :) и ;(.
  • Он также учитывает влияние символов, написанных с заглавной буквы, которые усиливают или ослабляют эмоциональный подтекст предложения.
  • Он быстрый, так как ему не нужно обучать какую-либо модель перед использованием
  • Он лучше всего подходит для языка, используемого в социальных сетях, из-за его превосходного анализа эмодзи и нетрадиционной пунктуации.

%-) -1.5 1.43178 [-2, 0, -2, -2, -1, 2, -2, -3, -2, -3]
&-: -0.4 1.42829 [-3, -1, 0, 0, -1, -1, -1, 2, -1, 2]

advantaged 1.4 0.91652 [1, 0, 3, 0, 1, 1, 2, 2, 2, 2]
advantageous 1.5 0.67082 [2, 0, 2, 2, 2, 1, 1, 1, 2, 2]

(vader_lexicon.txt используется для нахождения соответствующего балла слова или знака препинания)

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

Пара примеров VADER polarity_scores()

Начало работы с анализом настроений на акции

Давайте перейдем к делу! Я продемонстрирую, как проводить анализ настроений с VADER против четырех акций: NVDAAVGOAMDBABA Что касается источников данных новостного заголовка, то я буду скреб из https://finviz.com/, предложенных автором этой статьи.

Шаг 1. Глобальные переменные

Во-первых, давайте импортируем нужные нам библиотеки и определим тикеры, которые мы будем изучать.import pandas as pd
from datetime import datetime

from bs4 import BeautifulSoup
import nltk
from nltk.sentiment.vader import SentimentIntensityAnalyzer
import requests

# Define the ticker list
tickers_list = [‘NVDA’, ‘AVGO’, ‘AMD’, ‘BABA’]

Шаг 2. Получение заголовков бегущих строк

На этом шаге мы используем BeautifulSoup и requests на извлечение заголовка новости из https://finviz.com/. После того, как вы соскоблите заголовки и заправите их в пд. DataFrame, вы заметите, что большинство ячеек в столбце Date на самом деле пусты. Это связано с тем, что формат даты в https://finviz.com/ вызывает эту проблему. Следовательно, нам необходимо дополнительно обработать данные в столбце Date и извлечь данные о времени для заполнения столбца Time. Как только это будет сделано правильно, мы можем объединить все очищенные заголовки, чтобы создать полную таблицу заголовков.news = pd.DataFrame()

for ticker in tickers_list:
url = f’https://finviz.com/quote.ashx?t={ticker}&p=d’
ret = requests.get(
url,
headers={‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36’},
)

html = BeautifulSoup(ret.content, «html.parser»)

try:
df = pd.read_html(
str(html),
attrs={‘class’: ‘fullview-news-outer’}
)[0]
except:
print(f»{ticker} No news found»)
continue

df.columns = [‘Date’, ‘Headline’]

# Process date and time columns to make sure this is filled in every headline each row
dateNTime = df.Date.apply(lambda x: ‘,’+x if len(x)<8 else x).str.split(r’ |,’, expand = True).replace(«», None).ffill()
df = pd.merge(df, dateNTime, right_index=True, left_index=True).drop(‘Date’, axis=1).rename(columns={0:’Date’, 1:’Time’})
df.loc[:, ‘Date’][df.loc[:,’Date’]==’Today’] = str(datetime.now().date())
df.Date = pd.to_datetime(df.Date)
df.Time = pd.to_datetime(df.Time).dt.time
df = df[df[«Headline»].str.contains(«Loading.») == False].loc[:, [‘Date’, ‘Time’, ‘Headline’]]
df[«Date»] = df[«Date»].dt.date

df[«Ticker»] = ticker
news = pd.concat([news, df], ignore_index = True)

DataFrame очищенных заголовков

Шаг 3. Создание оценки тональности новостей

Этот шаг будет довольно простым. Мы применяем функцию polarity_scores() ко всем заголовкам. Как только мы получаем все отрицательные, нейтральные, положительные и составные оценки, мы объединяем их обратно в исходный новостной фрейм данных. Обратите внимание, что здесь нам нужно сначала загрузить vader_lexicon, чтобы функция polarity_scores() могла работать правильно. Способ, которым пакет Vader подсчитывает счет, довольно интересен и несложен для понимания. Если вам интересно узнать, как подсчитываются баллы, прочтите исходный код VADER. Вероятно, это займет у вас полчаса, но это определенно окупится.nltk.download(‘vader_lexicon’)
vader = SentimentIntensityAnalyzer()

scored_news = news.join(
pd.DataFrame(news[‘Headline’].apply(vader.polarity_scores).tolist())
)

Шаг 4. Чтобы дополнительно добавить изюминку в оценку тональности

Хорошо известно, что влияние любой недавно выпущенной новости со временем ослабевает. Я использую метод EMA (экспоненциальная скользящая средняя), чтобы учесть это явление в нашей модели оценки настроений. Здесь я использую 5-дневную EMA для расчета скользящей средней.news_score = scored_news.loc[:, [‘Ticker’, ‘Date’, ‘compound’]].pivot_table(values=’compound’, index=’Date’, columns=’Ticker’, aggfunc=’mean’).ewm(5).mean()
news_score.dropna().plot()

5-дневная EMA оценок настроений

Взглянув на диаграмму выше, легко заметить, что оценка тональности этих четырех тикеров в конечном итоге имела разные траектории движения. Тем не менее, цены на акции определяются не точным результатом, а относительными изменениями в оценках. Поэтому давайте сделаем еще один шаг, чтобы выяснить изменения в эмоциональном подтексте этих заголовков.news_score.pct_change().dropna().plot()

Процентное изменение ежедневной оценки настроений каждого тикера

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

Заключение и другие мысли

На этом мой анализ настроений заканчивается, но он не должен быть вашим. На самом деле есть более интересные вещи и идеи, которые вы можете начать строить на основе этой системы настроений, например:

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

Добро пожаловать, оставьте мне сообщение о том, нравится вам эта статья или нет. Или, может быть, просто подскажите, что можно добавить к анализу здесь.
Аплодисменты.

Ссылки

Анализ настроений с помощью Python

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

В этой статье мы углубимся в захватывающий мир анализа настроений. Мы покажем вам, как построить собственную модель анализа настроений с помощью Python. И знаете что? Мы привносим большие пушки — механизм внимания. С помощью удивительной библиотеки Keras мы обучим модель глубокого обучения, которая может считывать эмоции как профессионал.

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

Начало работы

Прежде чем мы продолжим, нам нужно будет установить несколько библиотек. Мы будем использовать следующие библиотеки:

NLTK, который мы будем использовать для предварительной обработки текста путем удаления стоп-слов.

TensorFlow, платформа с открытым исходным кодом для машинного обучения.

Keras, библиотека для построения моделей глубокого обучения.

Чтобы установить их, просто откройте терминал и введите:

$ pip install nltk tensorflow keras pandas matplotlib seaborn sklearn

Подготовка данных

Мы будем использовать набор обзорных данных IMDB, который содержит обзоры фильмов с положительными, отрицательными и неконтролируемыми настроениями соответственно. Набор данных доступен на Kaggle.

Мы скачаем набор данных и загрузим его в программу.

from importlib import reload
import nltk
nltk.download('stopwords')
nltk.download('wordnet')

import re
from nltk.stem import WordNetLemmatizer
from nltk.corpus import stopwords

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import (
classification_report,
confusion_matrix,
roc_auc_score
)
import tensorflow as tf
from tensorflow import keras
from keras.preprocessing.text import Tokenizer
from keras.utils import pad_sequences
from keras.layers import Concatenate, Dense, Input, LSTM, Embedding, Dropout, Activation, GRU, Flatten
from keras.layers import Bidirectional, GlobalMaxPool1D
from keras.models import Model, Sequential
from keras.layers import Convolution1D
from keras import initializers, regularizers, constraints, optimizers, layers

import pandas as pd
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns

# Import IMDB dataset and drop unnecessary columns and rows
df2 = pd.read_csv('imdb_master.csv', encoding="latin-1")
df2 = df2.drop(['Unnamed: 0','type','file'],axis=1)
df2.columns = ["review","sentiment"]
df2 = df2[df2.sentiment != 'unsup']
df = df2

# Set NLTK StopWords and WordLemmatizer
stop_words = set(stopwords.words("english"))
lemmatizer = WordNetLemmatizer()

Результирующий df имеет два столбца: обзор, который содержит рецензию на фильм, и тональность, которая является тональностью рецензии (положительной или отрицательной).

Чистые данные

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

# Defining function to clean text data
def clean_text(text):
text = re.sub(r'[^\w\s]','',text, re.UNICODE)
text = text.lower()
text = [lemmatizer.lemmatize(token) for token in text.split(" ")]
text = [lemmatizer.lemmatize(token, "v") for token in text]
text = [word for word in text if not word in stop_words]
text = " ".join(text)
return text

# Applying the clean_text function to every row of the 'review' column
df['Processed_Reviews'] = df.review.apply(lambda x: clean_text(x))

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

Разделение данных

Затем мы кодируем целевые метки, которые представляют тональность каждого текста, в числовые значения от 0 до 1. LabelEncoder сопоставляет каждую уникальную метку тональности с уникальным целочисленным значением, позволяя модели работать с числовыми представлениями меток.

Чтобы оценить производительность нашей модели классификации тональности, нам нужно разделить набор данных на обучающий и тестовый наборы. Это достигается с помощью функции train_test_split. Переменные x_train и x_test хранят обработанные отзывы (текстовые данные) из кадра данных df, в то время как y_train и y_test хранят соответствующие метки тональности.

# Encode target labels between 0 and 1
le = LabelEncoder()
df['sentiment'] = le.fit_transform(df['sentiment'])

# Split Train y Test
x_train, x_test, y_train, y_test = train_test_split(df['Processed_Reviews'],
df['sentiment'])

Настройка параметров модели

Чтобы подготовить текстовые данные к моделированию, они должны быть токенизированы, то есть предложения разбиты на отдельные слова или лексемы. Библиотека Keras предоставляет класс Tokenizer, который выполняет эту задачу. Указывая параметр num_words как MAX_FEATURES, мы ограничиваем размер словаря наиболее часто встречающимися словами в обучающих данных.

Метод tokenizer.fit_on_texts подходит для токенизатора на x_train текстовых данных. После установки токенизатора мы можем преобразовать текстовые данные в последовательности целых чисел с помощью texts_to_sequences.

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

# Model Parameters
MAX_FEATURES = 6000
EMBED_SIZE = 128
RNN_CELL_SIZE = 32
MAX_LEN = 130 # Since our mean length is 128.5

# Tokenization
tokenizer = Tokenizer(num_words=MAX_FEATURES)
tokenizer.fit_on_texts(x_train)
# Converting into sequences
list_tokenized_train = tokenizer.texts_to_sequences(x_train)


# Padding Sequences
X_train = pad_sequences(list_tokenized_train, maxlen=MAX_LEN)

Архитектура модели

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

  1. Механизм внимания: Этот слой повышает способность модели концентрироваться на важных словах, игнорируя нерелевантные. Присваивая веса внимания различным словам во входной последовательности, модель может сосредоточиться на наиболее информативных элементах для анализа настроений.
  2. Слой встраивания: Этот слой преобразует каждое слово во входной последовательности в векторное представление фиксированного размера. Он фиксирует семантическое значение и контекстную информацию, связанную с каждым словом, позволяя модели понять нюансы текста.
  3. Двунаправленный RNN: Этот слой кодирует предложение в векторное представление фиксированной длины, используя как прямой, так и обратный поток информации. Двунаправленная природа этой рекуррентной нейронной сети (RNN) позволяет модели фиксировать зависимости и последовательные закономерности в тексте, способствуя более всестороннему анализу.

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

Создание слоя внимания

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

Мы используем взвешенную сумму этих закодированных состояний (наш механизм внимания), чтобы сделать наш прогноз. Поскольку все эти закодированные состояния одинаково ценны, мы используем взвешенную сумму этих закодированных состояний. Следующий код Python создает слой внимания с помощью Keras:

# Attention Layer
class Attention(tf.keras.Model):
def __init__(self, units):
super(Attention, self).__init__()
self.W1 = tf.keras.layers.Dense(units)
self.W2 = tf.keras.layers.Dense(units)
self.V = tf.keras.layers.Dense(1)

def call(self, features, hidden):
hidden_with_time_axis = tf.expand_dims(hidden, 1)

score = tf.nn.tanh(
self.W1(features) + self.W2(hidden_with_time_axis))

attention_weights = tf.nn.softmax(self.V(score), axis=1)

context_vector = attention_weights * features
context_vector = tf.reduce_sum(context_vector, axis=1)

return context_vector, attention_weights

Этот код определяет класс Attention, который расширяет tf.keras.Model Мы устанавливаем три плотных слоя в конструкторе, self.W1self.W2, и self.V и реализуйте метод call для вычисления внимания.

Сначала мы расширяем тензор скрытого состояния, чтобы получить временное измерение, а затем вычисляем оценку, добавляя развернутое состояние к self.W1(features). Веса внимания рассчитываются с использованием tf.nn.softmax(self.V(score), axis=1) а контекстный вектор представляет собой взвешенную сумму признаков тензора features attention_weights, нормализованную суммированием по временному измерению.

Слой встраивания

Следующий шаг включает в себя создание слоя встраивания для представления слов в наших текстовых данных. Для этой цели используется слой EmbeddingMAX_FEATURES представляет максимальное количество объектов, а EMBED_SIZE определяет размерность слова embeddings.

# Add Embedding Layer
sequence_input = Input(shape=(MAX_LEN,), dtype="int32")
embedded_sequences = Embedding(MAX_FEATURES, EMBED_SIZE)(sequence_input)

Двунаправленный RNN

Для захвата контекстной информации как из прямых, так и из обратных последовательностей используется двунаправленная рекуррентная нейронная сеть (RNN). Bidirectional оболочка используется для инкапсуляции слоя LSTM. Затем собираются выходы двунаправленного LSTM.


# Add Bidirectional layer
bilstm = Bidirectional(LSTM(64, return_sequences=True), name="bi_lstm_0")(embedded_sequences)
(lstm, forward_h, forward_c, backward_h, backward_c) = Bidirectional(LSTM(RNN_CELL_SIZE, return_sequences=True, return_state=True), name="bi_lstm_1")(bilstm)

Внимание и плотные слои

Поскольку в нашей модели используется двунаправленная RNN, мы объединяем скрытые состояния каждого RNN, прежде чем вычислять веса внимания и применять взвешенное суммирование. Сцепленные скрытые состояния передаются на слой внимания.

# Concatenate RNN hidden states and apply attention
state_h = Concatenate()([forward_h, backward_h])
state_c = Concatenate()([forward_c, backward_c])
context_vector, attention_weights = Attention(10)(lstm, state_h)

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

# Add Dense Layers
dense1 = Dense(20, activation="relu")(context_vector)
dropout = Dropout(0.05)(dense1)
output = Dense(1, activation="sigmoid")(dropout)

Визуализация архитектуры модели

Чтобы лучше понять архитектуру модели и связи между слоями, мы можем создать визуальное представление модели с помощью plot_model из библиотеки Keras.

# Plot Model
keras.utils.plot_model(model, show_shapes=True, dpi=90)

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

Компиляция модели

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

# Set Train Metrics
METRICS = [
keras.metrics.TruePositives(name='tp'),
keras.metrics.FalsePositives(name='fp'),
keras.metrics.TrueNegatives(name='tn'),
keras.metrics.FalseNegatives(name='fn'),
keras.metrics.BinaryAccuracy(name='accuracy'),
keras.metrics.Precision(name='precision'),
keras.metrics.Recall(name='recall'),
keras.metrics.AUC(name='auc'),
]

# Compile the Model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=METRICS)

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

Модель обучения

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

# Train Model
BATCH_SIZE = 100
EPOCHS = 5
history = model.fit(X_train, y_train,
batch_size=BATCH_SIZE,
epochs=EPOCHS,
validation_split=0.2)

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

Оценка модели

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

# Tokenize and padding
list_sentences_test = x_test
list_tokenized_test = tokenizer.texts_to_sequences(list_sentences_test)
X_test = pad_sequences(list_tokenized_test, maxlen=MAX_LEN)

Затем мы используем обученную модель для прогнозирования тестовых данных.

# Make Predictions
prediction = model.predict(X_test)

Матрица путаницы

Чтобы оценить производительность модели, мы можем вычислить различные показатели, такие как точность, прецизионность, отзыв и AUC-ROC. Мы также можем создать отчет о классификации и построить матрицу путаницы, чтобы получить более глубокое представление о прогнозах модели.

# Classificacion Report
report = classification_report(y_test, y_pred)
print(report)

def plot_cm(labels, predictions, p=0.5):
cm = confusion_matrix(labels, predictions)
plt.figure(figsize=(5, 5))
sns.heatmap(cm, annot=True, fmt="d")
plt.title("Confusion matrix (non-normalized)")
plt.ylabel("Actual label")
plt.xlabel("Predicted label")

plot_cm(y_test, y_pred)

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

              precision    recall  f1-score   support

0 0.88 0.85 0.87 6299
1 0.85 0.88 0.87 6201

accuracy 0.87 12500
macro avg 0.87 0.87 0.87 12500
weighted avg 0.87 0.87 0.87 12500

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

Метрики проверки

Затем мы можем построить график метрик обучения и проверки по эпохам, чтобы оценить ход обучения модели.

# Figure Params
colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]
mpl.rcParams["figure.figsize"] = (12, 18)

# Plot Model Metrics
def plot_metrics(history):
metrics = [
"loss",
"tp", "fp", "tn", "fn",
"accuracy",
"precision", "recall",
"auc",
]

# Create subplot for each metric
for n, metric in enumerate(metrics):
name = metric.replace("_", " ").capitalize()
plt.subplot(5, 2, n + 1)
plt.plot(
history.epoch,
history.history[metric],
color=colors[0],
label="Train",
)
plt.plot(
history.epoch,
history.history["val_" + metric],
color=colors[1],
linestyle="--",
label="Val",
)
plt.xlabel("Epoch")
plt.ylabel(name)
if metric == "loss":
plt.ylim([0, plt.ylim()[1] * 1.2])
elif metric == "accuracy":
plt.ylim([0.4, 1])
elif metric == "fn":
plt.ylim([0, plt.ylim()[1]])
elif metric == "fp":
plt.ylim([0, plt.ylim()[1]])
elif metric == "tn":
plt.ylim([0, plt.ylim()[1]])
elif metric == "tp":
plt.ylim([0, plt.ylim()[1]])
elif metric == "precision":
plt.ylim([0, 1])
elif metric == "recall":
plt.ylim([0.4, 1])
else:
plt.ylim([0, 1])
plt.legend()
plot_metrics(history)

Функция plot_metrics генерирует набор подграфиков, каждый из которых представляет разные показатели, включая потери, истинные положительные результаты (tp), ложные срабатывания (fp), истинные отрицательные значения (tn), ложноотрицательные результаты (fn), точность, точность, отзыв и AUC. Наблюдая за этими графиками, мы можем получить представление о производительности модели и определить, происходит ли какое-либо переобучение или недообучение.

Кривая ROC

Наконец, мы можем построить кривую рабочих характеристик приемника (ROC), чтобы оценить способность модели различать положительные и отрицательные настроения.

from sklearn.metrics import roc_curve, auc

# Binarize labels
y_bin = label_binarize(y_test, classes=[0, 1])
n_classes = 1
fpr = dict()
tpr = dict()
roc_auc = dict()

# Create ROC Curve for each class
for i in range(n_classes):
fpr[i], tpr[i], _ = roc_curve(y_test.ravel(), y_pred.ravel())
roc_auc[i] = auc(fpr[i], tpr[i])
fpr["micro"], tpr["micro"], _ = roc_curve(y_test.ravel(), y_pred.ravel())
roc_auc["micro"] = auc(fpr["micro"], tpr["micro"])

# Plot ROC Curve
plt.figure()
lw = 2
plt.plot(fpr[0], tpr[0], color='darkorange',
lw=lw, label='ROC curve (area = %0.2f)' % roc_auc[0])

plt.plot([0, 1], [0, 1], color='navy', lw=lw, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic')
plt.legend(loc="lower right")
plt.show()

Кривая ROC отображает истинную положительную частоту по сравнению с ложноположительной частотой при различных классификационных порогах. Площадь под кривой ROC (AUC-ROC) является широко используемой метрикой для оценки общей производительности модели двоичной классификации. Более высокое значение AUC указывает на лучшую различительную способность.

Оценивая производительность модели с помощью этих методов оценки, мы можем получить ценную информацию о ее точности, точности, запоминаемости и оценке AUC-ROC. Эти метрики дают всестороннюю оценку эффективности модели при классификации тональности.

Заключение

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

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

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

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

Определение лидеров роста и падения с помощью API Polygon с моделями машинного обучения.

На сегодняшнем волатильном фондовом рынке инвесторы постоянно ищут возможности максимизировать свою прибыль. Анализ настроений на фондовом рынке может дать ценную информацию о рыночных тенденциях и помочь определить потенциальных победителей и проигравших. В этой записи блога мы рассмотрим, как использовать API Polygon, модели машинного обучения (ML) и анализ настроений для определения акций с наибольшим и наибольшим падением.

Лидеры роста и лидеры падения

Шаг 1: Получение исторических данных о запасах: Первым шагом является получение исторических данных по акциям для нашего анализа. Мы будем использовать Polygon API, который предоставляет огромное количество рыночных данных в режиме реального времени и исторических данных. С помощью API мы можем получить необходимые данные для наших моделей машинного обучения.

Шаг 2: Анализ тональности и обработка данных: Чтобы определить настроения, связанные с акциями, нам нужны данные, связанные с настроениями. Несмотря на то, что API Polygon не предоставляет прямых данных о тональности, мы можем получать их из внешних источников, таких как новостные API или платформы социальных сетей. Выполняя анализ настроений на этих текстовых источниках данных, мы можем оценить настроения (положительные, негативные, нейтральные), связанные с конкретными акциями.

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

Шаг 4: Моделирование машинного обучения: Теперь, когда объединенный набор данных готов, мы можем приступить к моделированию машинного обучения. Мы будем использовать модели машинного обучения, такие как алгоритмы классификации или модели глубокого обучения, для обучения и прогнозирования настроений акций на основе доступных функций и данных о настроениях. Этот шаг позволяет нам использовать возможности машинного обучения для классификации акций по различным категориям настроений.

Шаг 5: Визуализация: Чтобы лучше понять результаты анализа тональности, мы визуализируем результаты с помощью графиков. Мы можем использовать различные методы визуализации, такие как гистограммы или круговые диаграммы, чтобы представить распределение настроений между акциями, которые больше всего растут, и акциями, которые больше всего падают. Эти визуализации дадут четкое представление о настроениях, связанных с этими акциями.

Заключение: Анализ настроений на фондовом рынке является ценным инструментом для инвесторов, стремящихся принимать обоснованные решения на фондовом рынке. Используя API Polygon, объединяя данные об акциях с данными о настроениях и используя модели машинного обучения, мы можем определить акции лидеров роста и падения с помощью соответствующего анализа настроений. Благодаря этой информации инвесторы могут принимать более обоснованные решения и потенциально извлекать выгоду из рыночных возможностей.

Давайте рассмотрим пример кода на Python:import requests
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt

api_key = «YOUR_API_KEY»
base_url = «https://api.polygon.io/v2/aggs/ticker»

tickers = [«AAPL», «TSLA», «GOOGL», «AMZN»]
from_date = «2023-01-01»
to_date = «2023-06-01»

stock_data = {}

for ticker in tickers:
url = f»{base_url}/{ticker}/range/1/day/{from_date}/{to_date}?apiKey={api_key}»
response = requests.get(url)
data = response.json()
stock_data[ticker] = data[‘results’]

gainers = {}
losers = {}

for ticker, data in stock_data.items():
df = pd.DataFrame(data)
df[‘timestamp’] = pd.to_datetime(df[‘t’], unit=’ms’)
df.set_index(‘timestamp’, inplace=True)
df.sort_index(ascending=True, inplace=True)

df[‘change’] = df[‘c’].pct_change()

gainers[ticker] = df[‘change’].idxmax()
losers[ticker] = df[‘change’].idxmin()

top_gainer = max(gainers, key=gainers.get)
top_loser = min(losers, key=losers.get)

gainer_data = stock_data[top_gainer]
loser_data = stock_data[top_loser]

gainer_df = pd.DataFrame(gainer_data)
gainer_df[‘timestamp’] = pd.to_datetime(gainer_df[‘t’], unit=’ms’)
gainer_df.set_index(‘timestamp’, inplace=True)
gainer_df.sort_index(ascending=True, inplace=True)

loser_df = pd.DataFrame(loser_data)
loser_df[‘timestamp’] = pd.to_datetime(loser_df[‘t’], unit=’ms’)
loser_df.set_index(‘timestamp’, inplace=True)
loser_df.sort_index(ascending=True, inplace=True)

gainer_features = gainer_df[[‘o’, ‘h’, ‘l’, ‘v’]]
gainer_target = gainer_df[‘c’]

loser_features = loser_df[[‘o’, ‘h’, ‘l’, ‘v’]]
loser_target = loser_df[‘c’]

gainer_features_train, gainer_features_test, gainer_target_train, gainer_target_test = train_test_split(
gainer_features, gainer_target, test_size=0.2, random_state=42
)

loser_features_train, loser_features_test, loser_target_train, loser_target_test = train_test_split(
loser_features, loser_target, test_size=0.2, random_state=42
)

gainer_model = LinearRegression()
gainer_model.fit(gainer_features_train, gainer_target_train)
gainer_score = gainer_model.score(gainer_features_test, gainer_target_test)

loser_model = LinearRegression()
loser_model.fit(loser_features_train, loser_target_train)
loser_score = loser_model.score(loser_features_test, loser_target_test)

print(«Model performance:»)
print(f»Gainer Model R-squared: {gainer_score}»)
print(f»Loser Model R-squared: {loser_score}»)

Модель машинного обучения с графиком результатов анализа настроений для акций лидеров роста и падения. Для отображения распределения тональности можно использовать линейчатые диаграммы или круговые диаграммы или любой другой метод визуализации, который наилучшим образом представляет результаты анализа тональности.gainer_predictions = gainer_model.predict(gainer_features_test)
print(«GAINER:», gainer_predictions)

plt.figure(figsize=(12, 6))
plt.plot(gainer_target_test.index, gainer_target_test, label=»Actual»)
plt.plot(gainer_target_test.index, gainer_predictions, label=»Predicted»)
plt.xlabel(«Date»)
plt.ylabel(«Stock Price»)
plt.title(«Top Gainer Stock — Actual vs. Predicted»)
plt.legend()
plt.show()

Акции лидеров роста

loser_predictions = loser_model.predict(loser_features_test)
print(«LOSER:», loser_predictions)
plt.figure(figsize=(12, 6))
plt.plot(loser_target_test.index, loser_target_test, label=»Actual»)
plt.plot(loser_target_test.index, loser_predictions, label=»Predicted»)
plt.xlabel(«Date»)
plt.ylabel(«Stock Price»)
plt.title(«Top Loser Stock — Actual vs. Predicted»)
plt.legend()
plt.show()

Акции топ-неудачников

Это всего лишь простой пример того, как вы можете использовать API Polygon.io для получения данных о настроениях акций и использовать модель машинного обучения для прогнозирования того, какие акции, скорее всего, будут лидерами роста и падения. Вы можете использовать этот подход для построения более сложной торговой стратегии, которая поможет вам принимать более обоснованные инвестиционные решения.

Определение лидеров роста и падения с помощью API Polygon

На сегодняшнем волатильном фондовом рынке инвесторы постоянно ищут возможности максимизировать свою прибыль. Анализ настроений на фондовом рынке может дать ценную информацию о рыночных тенденциях и помочь определить потенциальных победителей и проигравших. В этой записи блога мы рассмотрим, как использовать API Polygon, модели машинного обучения (ML) и анализ настроений для определения акций с наибольшим и наибольшим падением.

Лидеры роста и лидеры падения

Шаг 1: Получение исторических данных о запасах: Первым шагом является получение исторических данных по акциям для нашего анализа. Мы будем использовать Polygon API, который предоставляет огромное количество рыночных данных в режиме реального времени и исторических данных. С помощью API мы можем получить необходимые данные для наших моделей машинного обучения.

Шаг 2: Анализ тональности и обработка данных: Чтобы определить настроения, связанные с акциями, нам нужны данные, связанные с настроениями. Несмотря на то, что API Polygon не предоставляет прямых данных о тональности, мы можем получать их из внешних источников, таких как новостные API или платформы социальных сетей. Выполняя анализ настроений на этих текстовых источниках данных, мы можем оценить настроения (положительные, негативные, нейтральные), связанные с конкретными акциями.

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

Шаг 4: Моделирование машинного обучения: Теперь, когда объединенный набор данных готов, мы можем приступить к моделированию машинного обучения. Мы будем использовать модели машинного обучения, такие как алгоритмы классификации или модели глубокого обучения, для обучения и прогнозирования настроений акций на основе доступных функций и данных о настроениях. Этот шаг позволяет нам использовать возможности машинного обучения для классификации акций по различным категориям настроений.

Шаг 5: Визуализация: Чтобы лучше понять результаты анализа тональности, мы визуализируем результаты с помощью графиков. Мы можем использовать различные методы визуализации, такие как гистограммы или круговые диаграммы, чтобы представить распределение настроений между акциями, которые больше всего растут, и акциями, которые больше всего падают. Эти визуализации дадут четкое представление о настроениях, связанных с этими акциями.

Заключение: Анализ настроений на фондовом рынке является ценным инструментом для инвесторов, стремящихся принимать обоснованные решения на фондовом рынке. Используя API Polygon, объединяя данные об акциях с данными о настроениях и используя модели машинного обучения, мы можем определить акции лидеров роста и падения с помощью соответствующего анализа настроений. Благодаря этой информации инвесторы могут принимать более обоснованные решения и потенциально извлекать выгоду из рыночных возможностей.

Давайте рассмотрим пример кода на Python:import requests
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt

api_key = «YOUR_API_KEY»
base_url = «https://api.polygon.io/v2/aggs/ticker»

tickers = [«AAPL», «TSLA», «GOOGL», «AMZN»]
from_date = «2023-01-01»
to_date = «2023-06-01»

stock_data = {}

for ticker in tickers:
url = f»{base_url}/{ticker}/range/1/day/{from_date}/{to_date}?apiKey={api_key}»
response = requests.get(url)
data = response.json()
stock_data[ticker] = data[‘results’]

gainers = {}
losers = {}

for ticker, data in stock_data.items():
df = pd.DataFrame(data)
df[‘timestamp’] = pd.to_datetime(df[‘t’], unit=’ms’)
df.set_index(‘timestamp’, inplace=True)
df.sort_index(ascending=True, inplace=True)

df[‘change’] = df[‘c’].pct_change()

gainers[ticker] = df[‘change’].idxmax()
losers[ticker] = df[‘change’].idxmin()

top_gainer = max(gainers, key=gainers.get)
top_loser = min(losers, key=losers.get)

gainer_data = stock_data[top_gainer]
loser_data = stock_data[top_loser]

gainer_df = pd.DataFrame(gainer_data)
gainer_df[‘timestamp’] = pd.to_datetime(gainer_df[‘t’], unit=’ms’)
gainer_df.set_index(‘timestamp’, inplace=True)
gainer_df.sort_index(ascending=True, inplace=True)

loser_df = pd.DataFrame(loser_data)
loser_df[‘timestamp’] = pd.to_datetime(loser_df[‘t’], unit=’ms’)
loser_df.set_index(‘timestamp’, inplace=True)
loser_df.sort_index(ascending=True, inplace=True)

gainer_features = gainer_df[[‘o’, ‘h’, ‘l’, ‘v’]]
gainer_target = gainer_df[‘c’]

loser_features = loser_df[[‘o’, ‘h’, ‘l’, ‘v’]]
loser_target = loser_df[‘c’]

gainer_features_train, gainer_features_test, gainer_target_train, gainer_target_test = train_test_split(
gainer_features, gainer_target, test_size=0.2, random_state=42
)

loser_features_train, loser_features_test, loser_target_train, loser_target_test = train_test_split(
loser_features, loser_target, test_size=0.2, random_state=42
)

gainer_model = LinearRegression()
gainer_model.fit(gainer_features_train, gainer_target_train)
gainer_score = gainer_model.score(gainer_features_test, gainer_target_test)

loser_model = LinearRegression()
loser_model.fit(loser_features_train, loser_target_train)
loser_score = loser_model.score(loser_features_test, loser_target_test)

print(«Model performance:»)
print(f»Gainer Model R-squared: {gainer_score}»)
print(f»Loser Model R-squared: {loser_score}»)

Модель машинного обучения с графиком результатов анализа настроений для акций лидеров роста и падения. Для отображения распределения тональности можно использовать линейчатые диаграммы или круговые диаграммы или любой другой метод визуализации, который наилучшим образом представляет результаты анализа тональности.gainer_predictions = gainer_model.predict(gainer_features_test)
print(«GAINER:», gainer_predictions)

plt.figure(figsize=(12, 6))
plt.plot(gainer_target_test.index, gainer_target_test, label=»Actual»)
plt.plot(gainer_target_test.index, gainer_predictions, label=»Predicted»)
plt.xlabel(«Date»)
plt.ylabel(«Stock Price»)
plt.title(«Top Gainer Stock — Actual vs. Predicted»)
plt.legend()
plt.show()

Акции лидеров роста

loser_predictions = loser_model.predict(loser_features_test)
print(«LOSER:», loser_predictions)
plt.figure(figsize=(12, 6))
plt.plot(loser_target_test.index, loser_target_test, label=»Actual»)
plt.plot(loser_target_test.index, loser_predictions, label=»Predicted»)
plt.xlabel(«Date»)
plt.ylabel(«Stock Price»)
plt.title(«Top Loser Stock — Actual vs. Predicted»)
plt.legend()
plt.show()

Акции топ-неудачников

Это всего лишь простой пример того, как вы можете использовать API Polygon.io для получения данных о настроениях акций и использовать модель машинного обучения для прогнозирования того, какие акции, скорее всего, будут лидерами роста и падения. Вы можете использовать этот подход для построения более сложной торговой стратегии, которая поможет вам принимать более обоснованные инвестиционные решения.

Использование анализа настроений в качестве торгового сигнала

Эмоции инвесторов управляют финансовым рынком. На них влияют новости, публикуемые компаниями или прессой; В золотые дни Уолл-стрит трейдер, как правило, начинал свой день с чтения последнего выпуска Financial Times и использовал его, чтобы решить, следует ли ему сохранить (или сбросить) свои недавно приобретенные акции. В настоящее время машины могут за считанные секунды обрабатывать пресс-релизы сотен компаний, годовые финансовые отчеты и даже комментарии в социальных сетях, чтобы составить четкое представление об общественном мнении.

Что, если бы мы использовали тональность сегодняшних финансовых новостных статей (с оценкой от -1 до 1) при принятии решения о входе в рынок? В этой статье я рассмотрю, как обработку естественного языка можно использовать в качестве сигнала на покупку. Я сделаю это с помощью тестирования на Python, простой стратегии, основанной на анализе тональности.

Некоторые результаты, полученные в конце этого эксперимента.

Что такое тестирование на истории?

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

План…

  1. Начало работы: Я расскажу о том, какие библиотеки Python установить и импортировать для кода этой статьи.
  2. Получение данных: Затем я вкратце объясню, как были получены данные и какой тип данных я буду использовать.
  3. Стратегия: Далее я покажу вам, как написать класс стратегии Backtrader, и объясню свою простую стратегию, основанную на анализе настроений.
  4. Запуск бэктеста: Я покажу вам, как использовать Cerebro Engine от Backtrader для оценки стратегии на исторических данных.
  5. Оценка стратегии: Наконец, я оценю стратегию, сравнив ее с классической покупкой и держи, и предложу возможные улучшения.

Начало работы…

Чтобы протестировать свою стратегию, основанную на анализе настроений, я буду использовать Backtrader.py. Эта библиотека Python отлично подходит для написания многоразовых торговых стратегий, индикаторов и анализаторов без необходимости тратить время на создание инфраструктуры.import backtrader as bt

Я также устанавливаю и импортирую Pandas, пакет Python, который предоставляет быстрые, гибкие и выразительные структуры данных. Наконец, библиотека datetime также необходима, так как я буду манипулировать временными рядами данных.import pandas as pd
from datetime import datetime

Наконец, импортируйте quantstats. Это библиотека Python, которая выполняет профилирование портфеля, позволяя квантам и портфельным менеджерам лучше понимать свою производительность, предоставляя им углубленную аналитику и метрики риска.import quantstats

Получение данных…

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

Скриншот файла GOOG.csv, содержащего исторические данные по акциям Google

Дневное открытие, максимум, минимум, закрытие, скорректированное закрытие и объем были получены с помощью библиотеки yfinance.

  • Open: цена, по которой акция начала торговаться на момент открытия рынка
  • Максимум: максимальная цена акции в данный торговый день
  • Низкая: самая низкая цена акции в данный торговый день
  • Закрытие: цена, по которой акция закончила торговлю на момент закрытия рынка
  • Объем: общее количество акций, проторгованное до закрытия рынка в данный торговый день.

Ежедневная оценка настроений была получена путем выполнения анализа тональности с использованием финансового BERT в заголовках ежедневных финансовых новостей, посвященных Google. В своей последней статье я представил способ анализа финансовых настроений: Как я кодирую Python Stock Screener & A.I. Sentiment Analysis для выбора акций. | Чеди Смауи | Дек, 2023 | Терпимая.

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

Я закодировал класс Python, чтобы помочь получить исторические данные с ежедневными оценками настроений по более чем 6 000 различных тикеров. Я использовал его для получения CSV-файла, содержащего исторические данные об акциях Google:#data_raw = DataGenerator.get_data(‘GOOG’)
#data_raw.to_csv(‘GOOG.csv’)

data = pd.read_csv(‘GOOG.csv’)

# Dataframe editing
data[‘Date’] = pd.to_datetime(data[‘Date’])
data = data.rename(columns={‘finbert_sentiment_score’: ‘sentiment’})
data.set_index(‘Date’, inplace=True)

# Edit the PandasData feeder to accept the last column as holding the sentiment scores
class PandasSent(bt.feeds.PandasData):
lines = ((‘sentiment’),)
params = ((‘sentiment’,-1),)

# Pass the data into the Backtrader data feeder
data = PandasSent(dataname=data)

Из-за того, что эта статья посвящена основной теме, я не буду более подробно останавливаться на классе DataGenerator.

Стратегия…

Во-первых, определим класс стратегии, начиная с функции log. Думайте о функции log как о функции print() вашего класса стратегии. Он позволяет передавать текстовые данные через переменную txt и выводить их на экран при вызове.class SentimentStrat(bt.Strategy):
params = (
(‘exitbars’, 3),
)

def log(self, txt, dt=None):
«»»
Logging function for this strategy.

Args:
txt (_type_): text variable to output to the screen.
dt (_type_, optional): Attempt to grab datetime values from the most recent data point if available and log it to the screen. Defaults to None.
«»»
dt = dt or self.datas[0].datetime.date(0)
print(f'{dt.isoformat()} {txt}’) # Print date and close

Теперь, когда функция печати определена, я переопределяю функцию инициализации. Внутри определите данные, которые будет использовать объект стратегии. Здесь меня интересуют только дневные цены закрытия и оценки настроений: def __init__(self):
# Keep a reference to the «close» line in the data[0] dataseries
self.dataclose = self.datas[0].close
self.datasentiment = self.datas[0].sentiment

# To keep track of pending orders and buy price/commision
self.order = None
self.buyprice = None
self.buycomm = None

Следующая функция, которую нужно переопределить, — это функция notify_order. Именно здесь обрабатывается все, что связано с торговыми ордерами. Используя функцию журнала, определенную ранее, он будет уведомлять вас всякий раз, когда исполняется торговый приказ (на покупку или продажу акций): def notify_order(self, order):
if order.status in [order.Submitted, order.Accepted]:
# Buy/Sell order submitted/accepted to/by broker — Nothing to do
return

# Check if an order has been completed
# Attention: broker could reject order if not enough cash
if order.status in [order.Completed]:
if order.isbuy():
self.log(
‘BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f’ %
(order.executed.price,
order.executed.value,
order.executed.comm)
)
self.buyprice = order.executed.price
self.buycomm = order.executed.comm
else: # Sell
self.log(
‘SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f’ %
(order.executed.price,
order.executed.value,
order.executed.comm)
)

self.bar_executed = len(self)

elif order.status in [order.Canceled, order.Margin, order.Rejected]:
self.log(‘Order Canceled/Margin/Rejected’)

self.order = None

Точно так же переопределите функцию notify_trade, чтобы распечатать информацию, относящуюся к каждой закрытой сделке: def notify_trade(self, trade):
if not trade.isclosed:
return

self.log(‘OPERATION PROFIT, GROSS %.2f, NET %.2f’ %
(trade.pnl, trade.pnlcomm))

Наконец, я реализую всю логику стратегии внутри следующей функции. Идея проста: если сегодняшняя оценка настроений будет очень высокой (выше 0,6), то я куплю 1000 акций Google и продам их все через три дня. Хотя эту стратегию можно было бы улучшить, цель этой статьи — получить представление о том, чего можно достичь при использовании простой стратегии, основанной на анализе тональности. def next(self):
# Simply log the closing price of the series from the reference
self.log(‘Close, %.2f’ % self.dataclose[0])

# Check if an order is pending … if yes we cannot send a 2nd one
if self.order:
return

# Check if we are in the market
if not self.position:

# If the sentiment score is over 0.6, we buy
if self.datasentiment[0] > 0.6:

self.log(‘BUY CREATE, %.2f’ % self.dataclose[0])

# Keep track of the created order to avoid a 2nd order
self.order = self.buy(size=1000)

else:
# Already in the market, we sell three days (bars) after buying:
if len(self) >= (self.bar_executed + self.params.exitbars):

self.log(‘SELL CREATE, %.2f’ % self.dataclose[0])

# Keep track of the created order to avoid a 2nd order
self.order = self.sell(size=1000)

Запуск бэктеста…

Теперь, когда класс стратегии установлен, его можно использовать внутри основного скрипта для сравнения с историческими данными. Во-первых, создайте экземпляр класса Cerebro. Это краеугольный камень Backtrader, так как класс Cerebro служит центральной точкой для сбора всех входных данных (Data Feeds), акторов (Strategies) и критиков (Analyzers). Он также позволяет тестировать на истории или передавать данные в реальном времени и торговать, и может использоваться для возврата и построения графика результатов.# Instantiate the Cerebro engine
cerebro = bt.Cerebro()

# Add the strategy to Cerebro
cerebro.addstrategy(SentimentStrat)

# Add the data feed to cerebro
cerebro.adddata(data)

# Add an analyzer to get the return data
cerebro.addanalyzer(bt.analyzers.PyFolio, _name=’PyFolio’)

# set initial porfolio value at 100,000$
cerebro.broker.setcash(100000.0)
start_value = cerebro.broker.getvalue() # should be 100,000$

# Run the Backtest
results = cerebro.run()

# Print out the final result
print(‘Starting Portfolio Value: ‘, start_value)
print(‘Final Portfolio Value: %.2f’ % cerebro.broker.getvalue())

Теперь запустите программу и посмотрите, сколько денег можно было бы заработать, используя эту стратегию на акциях Google с декабря 2018 года по июль 2020 года. В терминале можно увидеть начальную и конечную стоимость портфеля:

Начальная и конечная стоимость портфеля

Получилось 10 108$ — неплохо! Теперь воспользуемся функцией построения графиков движка Cerebro, чтобы получить более подробную обратную связь по результатам тестирования:# Plot the results using cerebro’s plotting facilities
cerebro.plot()

Результаты cerebro.plot()

Большинство сделок были положительными, потому что алгоритм покупал акции GOOG, когда отзывы о компании и ее акциях были очень положительными. Как и ожидалось, многие инвесторы также начали скупать акции Google. А растущий спрос привел к росту цены акций. Затем алгоритм продал все свои акции через 3 дня, получая прибыль в большинстве случаев.

Хотя, на интересную заметку, вы можете увидеть, что использование альтернативных данных, таких как оценки настроений, заставило алгоритм «уклониться» от огромного падения цен, вызванного кризисом Covid примерно в начале 2020 года. Вероятно, это связано с тем, что отзывы о GOOG были отрицательными (или, по крайней мере, ниже 0,6) во время кризиса Covid. Тем не менее, он в конечном итоге вышел на рынок после падения цены, как только критики GOOG снова были положительными. Это очень важно, поскольку, в то время как для многих пандемия была «непредвиденной», с помощью анализа настроений алгоритм смог избежать крупных финансовых потерь.

Возвращаясь к текущей работе, используйте quantstats для получения более подробной обратной связи:strat = results[0]

# Uses PyFolio to obtain the returns from the Backtest
portfolio_stats = strat.analyzers.getbyname(‘PyFolio’)
returns, positions, transactions, gross_lev = portfolio_stats.get_pf_items()
returns.index = returns.index.tz_convert(None)

import webbrowser
# Feeds the returns to Quantstats to obtain a more complete report over the Backtest
quantstats.reports.html(returns, output=’stats.html’, title=f'{ticker} Sentiment’)
webbrowser.open(‘stats.html’)

Совокупная доходность и ключевые показатели эффективности
Ежемесячная доходность и квантили доходности

Стратегия применялась только с декабря 2018 года по июль 2020 года, что объясняет доходность в 0,0% в 2018 году.

Оценка стратегии…

Превзошла бы эта стратегия покупку 1000 акций Google в 2018 году и их продажу в июле 2020 года? Нет, простая покупка и удержание принесла бы как минимум вдвое больше денег, чем при использовании этой стратегии. Но помните, что это очень простая стратегия, которая может быть улучшена. Он рассматривает только ежедневные настроения нескольких новостных статей; Чтобы расширить его, вы можете использовать другие индикаторы, как фундаментальные, так и технические, такие как скользящие средние, RSI или другие альтернативные данные, такие как твиты (для криптовалют). Кроме того, время, проведенное на рынке с этой стратегией, довольно мало, что также является хорошей вещью, на которую стоит обратить внимание.

Тем не менее, акции Google были более прибыльными только со стратегией «купи и держи», потому что они следовали восходящему тренду. В сочетании с индикатором волатильности объема в качестве сигнала к покупке, стратегия, основанная на анализе настроений, может на самом деле превзойти «покупку и удержание» на «устойчивых снижающихся» или компаниях, которые не полностью оправились от кризиса Covid, таких как Citigroup:

Результаты тестирования стратегии на акциях Citigroup с декабря 2018 года по июнь 2020 года
Стратегия принесла прибыль в размере 15 690$ и превзошла покупки и удержания за тот же период времени

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

Прогнозирование настроений фондового рынка с помощью OpenAI и Python

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

Несмотря на то, что данные доступны в Интернете и легко доступны, одним из наиболее удобных методов для наших нужд является использование конечной точки API для интеграции рыночных данных и новостей непосредственно в наш код. Существует множество поставщиков финансовых данных, которые предлагают подключения API; Они различаются по пакетам данных, подходу к поддержке и качеству данных, которые они предоставляют.

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

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

Без лишних слов, давайте углубимся в статью.

Импорт пакетов

Начнем с импорта необходимых пакетов в нашу среду Python. В этой статье мы будем использовать три пакета: pandas для работы с датафреймами, eodhd для извлечения данных и langchain для построения модели LLM. Помимо этого, мы также будем использовать другие вторичные пакеты, такие как config и re. Импортируйте все необходимые пакеты, используя следующий код:!pip install openai
!pip install langchain
!pip install eodhd
!pip install config

import re
import requests
import pandas as pd
import config as cfg
from eodhd import APIClient
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI

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

Активация ключа API

Для того, чтобы использовать его функции, необходимо зарегистрировать ключ API EODHD в пакете. Если у вас нет ключа API EODHD, сначала перейдите на их веб-сайт, затем завершите процесс регистрации, чтобы создать учетную запись EODHD, и, наконец, перейдите на страницу «Настройки», где вы можете найти свой секретный ключ EODHD API. Важно следить за тем, чтобы этот секретный ключ API никому не раскрывался. Вы можете активировать ключ API, выполнив следующий код:api_key = ‘<YOUR API KEY>’
api = APIClient(api_key)

Код довольно простой. В первой строке мы сохраняем секретный ключ API EODHD в api_key, а затем во второй строке мы используем класс APIClient, предоставляемый пакетом eodhd, для активации ключа API и сохранения ответа в клиентской переменной.

Обратите внимание, что вам необходимо заменить <YOUR API KEY>> на секретный ключ API EODHD. Помимо непосредственного хранения ключа API с текстом, существуют и другие способы повышения безопасности, такие как использование переменных окружения и так далее.

Извлечение данных

Мы собираемся использовать API фондового рынка и финансовых новостей, обратившись к библиотеке Python, предоставляемой EODHD, следующим образом:resp = api.financial_news(s = «AAPL.US», from_date = ‘2024-01-01’, to_date = ‘2024-01-30’, limit = 100)
df = pd.DataFrame(resp) # converting the json output into datframe
df.tail()

Поясню параметры в API:

  1. s: Строка. REQUIRED, если параметр ‘t’ не установлен. Код тикера для получения новостей.
  2. t: Строка. REQUIRED, если параметр ‘s’ не установлен. Тег для получения новостей по заданной теме. Вы можете найти предоставленный список тем на этой странице: https://eodhd.com/financial-apis/stock-market-financial-news-api/
  3. api_token: Строка. ОБЯЗАТЕЛЬНО. Ваш api_token доступа к API. Вы получите его после регистрации.
  4. from и to: формат «ГГГГ-ММ-ДД». Если вам нужны данные с 1 марта 2021 г. по 10 марта 2021 г., используйте from=2021–03–01 и to=2021–03–10.
  5. limit: Число. НЕОБЯЗАТЕЛЬНЫЙ. Количество результатов, которое должно быть возвращено вместе с запросом. Значение по умолчанию: 50, минимальное значение: 1, максимальное значение: 1000.
  6. offset: Число. НЕОБЯЗАТЕЛЬНЫЙ. Смещение данных. Значение по умолчанию: 0, минимальное значение: 0. Например, чтобы получить 100 символов, начиная с 200, вы должны использовать limit=100 и offset=200.

Данные будут выглядеть следующим образом:

Новостные данные AAPL (Изображение автора)

Выходные данные имеют следующие поля:

  • дата: Дата и время статьи представлены в формате ISO 8601.
  • титул: Название статьи.
  • содержание: Основная часть статьи.
  • связь: Ссылка на источник.
  • Символы: В статье упоминается массив тикерных символов.

Очистка данных

Теперь эти данные нечисты и содержат множество переносов строк и различных команд. Итак, мы собираемся их очистить:#funtion to clean the textual data
def clean_text(text):
cleaned_text = re.sub(r’\s+’, ‘ ‘, text)
return cleaned_text.strip()

# Apply the replacement function to the entire column
df[‘content’] = df[‘content’].apply(clean_text)

Теперь мы применили его ко всем данным и можем двигаться дальше с нашим чат-ботом.

Магистр права

Теперь мы будем использовать Langchain для формирования цепочки LLM с моделью OpenAI.llm = ChatOpenAI(model = «gpt-3.5-turbo»,
openai_api_key = ‘YOUR OPENAI API KEY’,
temperature = 0)

ПРИМЕЧАНИЕ: Вы должны заменить YOUR OPENAI API KEYна свой собственный OpenAI API ключ для бесперебойного функционирования кода без каких-либо ошибок.

Этот фрагмент кода инициализирует языковую модель (LM) путем создания экземпляра GPT-2.5-turbo с температурой 0. Выбор температуры 0 обеспечивает детерминированность нашей модели, предотвращая ее отклонение и поддерживая целенаправленную и согласованную генерацию.

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

1) Оперативный инжиниринг:

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

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

  1. Подсказка с нулевым выстрелом: Этот метод позволяет большим языковым моделям (LLM) обрабатывать новые задачи даже без предварительных примеров или понимания задачи. Он работает с помощью метода, называемого «подсказкой», когда вы просто даете магистру права описание желаемой задачи на естественном языке.
  2. Несколько выстрелов: Несмотря на то, что модели с большим языком демонстрируют замечательные возможности нулевого выстрела, они по-прежнему не справляются с более сложными задачами при использовании параметра нулевого выстрела. Подсказка с несколькими выстрелами может быть использована в качестве метода для обеспечения контекстного обучения, когда мы предоставляем демонстрации в подсказке, чтобы направить модель к более высокой производительности. Демонстрации служат обусловливанием для последующих примеров, в которых мы хотели бы, чтобы модель генерировала ответ.
  3. Цепочка побуждений: Цепочка подсказок — это полезный метод для систем ИИ, позволяющий упростить сложные задачи, разбивая их на управляемые шаги. Вместо того, чтобы решать сложную проблему за один раз, этот метод способствует объяснению процесса рассуждения, разбивая решение на ряд более мелких, постепенных шагов. Он начинается с четкого определения конечной цели, а затем рассматриваются логические предпосылки и подзадачи, необходимые для достижения этой цели.

2) Тонкая настройка

Тонкая настройка — это полезный процесс, который позволяет пользователям адаптировать предварительно обученные языковые модели (LLM) для конкретных задач. Выполнив точную настройку модели на небольшом наборе данных, содержащем данные, относящиеся к конкретной задаче, можно повысить ее производительность для этой конкретной задачи, сохранив при этом общее понимание языка.

Ниже приведены два основных метода тонкой настройки:

  1. Полная тонкая настройка инструкций: Полная тонкая настройка инструкций — это метод, используемый для адаптации больших языковых моделей (LLM) к конкретным задачам. Процесс включает в себя корректировку всех параметров LLM с использованием данных, специфичных для конкретной задачи. Такая адаптация позволяет модели более эффективно выполнять определенные задачи, что потенциально приводит к повышению производительности. Потребность в полной тонкой настройке инструкций возникает из-за того, что даже самый опытный предварительно обученный магистр права не всегда может удовлетворить конкретные потребности прямо из коробки. Например, для приложения может потребоваться уникальная структура или стиль, или предварительно обученному магистру права может не хватать знаний о конкретных документах, имеющих решающее значение для приложения. Кроме того, некоторые области, отрасли и даже отдельные предприятия часто имеют уникальную терминологию, понятия и структуры, не представленные в общих данных о предварительном обучении. Таким образом, полная тонкая настройка инструкций является ценным методом адаптации LLM к более конкретным случаям использования.
  2. Тонкая настройка параметров с эффективным управлением: Параметрическая эффективная тонкая настройка (PEFT) — это метод, используемый для адаптации больших предварительно обученных моделей к различным последующим приложениям без точной настройки всех параметров модели. Это связано с тем, что тонкая настройка всех параметров может быть непомерно дорогостоящей. Вместо этого методы PEFT выполняют тонкую настройку лишь небольшого числа (дополнительных) параметров модели. Это значительно снижает затраты на вычисления и хранение данных, обеспечивая при этом производительность, сравнимую с полностью настроенной моделью. PEFT решает такие проблемы, как невозможность полной тонкой настройки на потребительском оборудовании и высокая стоимость хранения и развертывания точно настроенных моделей независимо для каждой последующей задачи. Он также решает проблему катастрофического забывания, поведение, наблюдаемое во время полной тонкой настройки больших языковых моделей (LLM).

В данном случае мы будем использовать методы быстрой инженерии, используя функциональность шаблона Langchain, для создания оптимизированной подсказки для проведения анализа настроений на фондовом рынке. Цель состоит в том, чтобы создать приглашение, которое не только обеспечивает анализ тональности, но и предлагает объяснения выводов модели.template = «»»
Identify the sentiment towards the Apple(AAPL) stocks from the news article , where the sentiment score should be from -10 to +10 where -10 being the most negative and +10 being the most positve , and 0 being neutral

Also give the proper explanation for your answers and how would it effect the prices of different stocks

Article : {statement}
«»»

#forming prompt using Langchain PromptTemplate functionality
prompt = PromptTemplate(template = template, input_variables = [«statement»])
llm_chain = LLMChain(prompt = prompt, llm = llm)

Теперь, когда мы установили цепочку LLM, позвольте мне привести вам пример ее вывода.

Запуск цепочки LLM:print(llm_chain.run(df[‘content’][13]))

Результат будет выглядеть следующим образом:

Прогнозирование тональности AAPL с помощью модели (Изображение автора)

Анализ

Теперь, чтобы проанализировать состояние рынка акций AAPL (Apple), давайте проанализируем 100 статей и сделаем некоторые выводы.

Итак, во-первых, мы должны убедиться, что мы не пересекли лимит токенов нашей модели, который для меня равен 4097. Поэтому отфильтруем статьи с количеством токов < 3500:#A function to count the number of tokens
def count_tokens(text):
tokens = text.split()
return len(tokens)

Подсчет токов для всех строк в датафрейме:# Applying the tokenization function to the DataFrame column
df[‘TokenCount’] = df[‘content’].apply(count_tokens)

Фильтрация фрейма данных по TokenCount:# Define a token count threshold (for example, keep rows with more than 2 tokens)
token_count_threshold = 3500

# Create a new DataFrame by filtering based on the token count
new_df = df[df[‘TokenCount’] < token_count_threshold]

# Drop the ‘TokenCount’ column from the new DataFrame if you don’t need it
new_df = new_df.drop(‘TokenCount’, axis = 1)

# Resetting the index
new_df = new_df.reset_index(drop = True)

Теперь на этот раз я бы изменил свой шаблон приглашения, чтобы получить краткий вывод:template_2 = «»»
Identify the sentiment towards the Apple(AAPL) stocks of the news article from -10 to +10 where -10 being the most negative and +10 being the most positve , and 0 being neutral

GIVE ANSWER IN ONLY ONE WORD AND THAT SHOULD BE THE SCORE

Article : {statement}
«»»

#forming prompt using Langchain PromptTemplate functionality
prompt_2 = PromptTemplate(template = template_2, input_variables = [«statement»])

Сформируем новую цепочку LLM:llm_chain_2 = LLMChain(prompt = prompt_2, llm = llm)

Позвольте мне продемонстрировать один вывод:print(new_df[‘content’][2])
print(»)
print(‘News sentiment: ‘, llm_chain_2.run(new_df[‘content’][2]))

Обновленный прогноз тональности модели (Изображение автора)

Отлично, теперь мы можем получить лаконичный результат. Теперь мы создадим цикл for, чтобы перебирать данные и получать тональность каждой новости:x = []
for i in range(0,new_df.shape[0]):
x.append(llm_chain_2.run(new_df[‘content’][i]))

Визуализация

Теперь давайте сформируем несколько круговых диаграмм, чтобы увидеть рыночные настроения акций AAPL:import matplotlib.pyplot as plt

dt = pd.DataFrame(x) #Converting into Dataframe
column_name = 0 # this is my column name you should change it according to your data
value_counts = dt[column_name].value_counts()

# Plotting the pie chart
plt.pie(value_counts, labels = value_counts.index, autopct = ‘%1.1f%%’, startangle = 140)
plt.title(f’Pie Chart’)
plt.axis(‘equal’) # Equal aspect ratio ensures that the pie is drawn as a circle.

# Show the pie chart
plt.show()

Настроения на рынке AAPL (Изображение автора)

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

Удаление нейтральных значений:value_to_remove = ‘0’
# Remove all rows where the specified value occurs in the column
dt_new = dt[dt[0] != value_to_remove]

Визуализация новых данных:value_counts = dt_new[column_name].value_counts()

# Plotting the pie chart
plt.pie(value_counts, labels = value_counts.index, autopct = ‘%1.1f%%’, startangle = 140)
plt.title(f’Pie Chart’)
plt.axis(‘equal’) # Equal aspect ratio ensures that the pie is drawn as a circle.

# Show the pie chart
plt.show()

Рыночные настроения AAPL, исключая нейтральные значения (Изображение автора)

Если наблюдать за тенденциями, то комбинация +5 и +7 составляет почти 40% данных. С учетом дополнительных значений, таких как +10, +8 и +3, совокупный процент положительных статей возрастает до 52,5%. Эта закономерность указывает на преобладающие оптимистичные настроения, подразумевающие благоприятное восприятие Apple Inc. в недавних статьях. Указанный позитивный прогноз может иметь потенциальные последствия для формирования общих настроений относительно рыночных показателей Apple.

Заключение

В нашем исследовании мы использовали API финансовых новостей фондового рынка, предоставляемый EODHD, для сбора новостных статей фондового рынка и использовали модель анализа настроений OpenAI для оценки настроений, передаваемых в этих статьях.

Чтобы обеспечить бесшовную совместимость между нашими данными и моделью OpenAI, был использован инструмент обработки языка LangChain. Чтобы уточнить входные данные для модели OpenAI и повысить точность анализа тональности, мы внедрили методы оперативного проектирования. Мы провели анализ настроений по 100 статьям, чтобы оценить текущие рыночные настроения вокруг акций APPL.

Источник

Источник

Источник

Источник

Источник

Источник