Отказ от ответственности: Эта статья предназначена только для демонстрации и не должна использоваться в качестве инвестиционного совета.
Чаще всего мы хотим сравнить показатели акций в одной отрасли, например, какой банк показал наилучшие результаты за последний год или какая технологическая компания получила наибольший прирост за последние два года? Эта статья проведет вас через процесс анализа и визуализации этих данных с помощью Python, что позволит вам получить полезные выводы.
Прежде чем мы продолжим, давайте импортируем необходимые библиотеки Python для последующих разделов. По мере продвижения по шагам я буду давать пояснения по пакетам по мере их вызова.
from pandas_datareader import data as pdr import yfinance as yf import pandas as pd import numpy as np import datetime import time yf.pdr_override() import seaborn as sns import cufflinks as cf
Здесь я создам список тикеров банков, импортирую их информацию из Yahoo Finance и консолидирую их в один Panda DataFrame. У вас есть возможность указать предпочтительные даты начала и окончания анализа:
bank = ['C','JPM','BAC','WFC'] df_all = pd.DataFrame() for ticker in bank: df = pdr.DataReader(ticker, data_source='yahoo', start='2020-01-01', end='2021-08-01') df['Symbols'] = ticker df_all = pd.concat([df_all,df],axis=0) df_all
Полученный DataFrame 'df_all', содержит временной ряд цен открытия, максимума, минимума, закрытия/скорректированной цены закрытия акций и соответствующий объем сделок.
Проверка наличия недостающих значений в данных :
df_all.isnull().sum()
Следующим шагом будет создание DataFrame с минимальной и максимальной ценой закрытия каждой акции за указанный период:
df1 = df_all.groupby('Symbols')['Adj Close'].agg(('min','max')).reset_index().rename(columns = {"min": "Min Close","max":"Max Close"}) df1
Далее мы объединим df1 и df_all DataFrame, чтобы добавить минимальные/максимальные цены в основной DataFrame (будет создан "df_all2")
df_all1 = df_all.reset_index() df_all2 = pd.merge(df_all1, df1 ,on = ['Symbols']) df_all2
Ниже приведен процесс создания DataFrame со скользящими 5-дневными, 30-дневными и 90-дневными средними ценами закрытия банков.
dfcomp = pdr.DataReader(bank, data_source='yahoo', start='2022-01-01', end='2023-03-01') dfcomp1 = dfcomp['Adj Close'] df_5days = dfcomp1.rolling(window=5).mean().tail(1) df_30days = dfcomp1.rolling(window=30).mean().tail(1) df_90days = dfcomp1.rolling(window=90).mean().tail(1) df_5days_new = df_5days.T df_30days_new = df_30days.T df_90days_new = df_90days.T df_5days_new.columns = ['rolling_5days'] df_30days_new.columns = ['rolling_30days'] df_90days_new.columns = ['rolling_90days'] rolling = pd.concat([df_5days_new,df_30days_new,df_90days_new], axis = 1).reset_index().rename(columns = {"index":"Symbols"}) rolling
Мы также хотим сохранить последнюю цену закрытия акций:
dfcomp_close = dfcomp1.tail(1) dfcomp_close = dfcomp_close.T dfcomp_close = dfcomp_close.reset_index() dfcomp_close.columns = ['Symbols','Close Price'] dfcomp_close
Чтобы объединить всю информацию, мы объединим три DataFrame: 'df_all2', 'rolling' и 'dfcomp_close'. Теперь объединенный DataFrame содержит всю историческую информацию о ценах, а также дополнительные характеристики, такие как минимальная и максимальная цены, скользящая средняя цена и последняя цена закрытия.
df_all3 = pd.merge(df_all2, rolling ,on = ['Symbols']) df_all4 = df_all3.merge(dfcomp_close, on = ['Symbols']) df_all4
До этого момента было бы полезно определить акции с наибольшим приростом от минимальной цены до последней цены закрытия, а также акции с наибольшим процентным падением от максимальной цены. Для этого мы добавляем следующие два столбца, выполнив приведенный ниже код:
#calculating percentage of gain from minimum price to close price df_all4['min_to_close_pct_change'] = (df_all4['Close Price'] - df_all4['Min Close'])/df_all4['Min Close'] #calculating percentage of price drop from the maximum price df_all4['close_to_max_pct_change'] = (df_all4['Max Close'] - df_all4['Close Price'])/df_all4['Close Price']
Наконец, мы дедуцируем данные до уникального уровня запасов и сохраняем их в другой DataFrame, чтобы позже использовать их для визуализации.
df_all4_unique = df_all4.drop_duplicates(subset = ['Symbols']) df_all4_unique = df_all4_unique.reset_index() df_all4_unique = df_all4_unique.drop(columns = ['index','Date','Open','High','Low','Close','Adj Close','Volume']) df_all4_unique
Теперь у нас есть практически все необходимые данные, давайте приступим к визуализации.
c = df_all4.loc[df_all4['Symbols'] == 'C'] c = c[['Date','Adj Close', 'Max Close','rolling_5days', 'rolling_30days', 'rolling_90days']] c.set_index("Date", inplace = True) c
Мы импортировали библиотеку "cufflinks" заранее (import cufflinks as cf), Cufflinks - это библиотека, которая соединяет рамку данных Pandas с Plotly, позволяя пользователям создавать визуализации прямо из Pandas.
cf.go_offline() c.iplot() plt.show()
Выше показана историческая скорректированная цена закрытия, максимальная цена и несколько скользящих средних цен на одном графике, график динамический, вы можете увидеть значение определенной временной точки при наведении на нее курсора мыши.
2). Мы также можем визуализировать тренд цены закрытия нескольких акций на одном графике.
bank_close_price = dfcomp['Adj Close'] import cufflinks as cf cf.go_offline() bank_close_price.iplot() plt.show()
3). Похоже, что все 4 банка имели очень похожий паттерн в плане изменения цены, давайте построим гистограмму с помощью библиотеки Python Seaborn, чтобы увидеть, какой из них имел наибольший выигрыш от минимальной цены.
Библиотека Seaborn была импортирована заранее (import seaborn as sns). DataFrame, который мы будем использовать, это тот, который мы создали выше на уровне уникальной компании (df_all4_unique).
plt.figure(figsize=(20,10), tight_layout=True) ax = sns.barplot(x=df_all4_unique['Symbols'], y=df_all4_unique['min_to_close_pct_change'], palette='pastel', ci=None) ax.set(title='Barplot', xlabel='Symbols', ylabel='min_to_close_pct_change') plt.show()
Мы можем заметить, что JPM получила больший прирост от самой низкой цены, чем остальные три акции за этот период.
Мы можем сделать еще одну гистограмму, чтобы посмотреть на нее под другим углом, чтобы увидеть, у какой акции был наибольший процент падения цены от максимальной цены.
plt.figure(figsize=(20,10), tight_layout=True) ax = sns.barplot(x=df_all4_unique['Symbols'], y=df_all4_unique['close_to_max_pct_change'], palette='pastel', ci=None) ax.set(title='Barplot', xlabel='Symbols', ylabel='close_to_max_pct_change') plt.show()
У "BAC" было самое большое падение цены от максимальной цены в течение этого периода.
В этой статье я продемонстрировал процесс получения данных из Yahoo и проведения простого анализа для сравнения конкурирующих акций в одной отрасли, а также представил различные методы визуализации. Вы можете настроить анализ, выбрав различные наборы акций за разные периоды времени.
Надеюсь, вы найдете эту статью полезной!
20.08.2023 18:21
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в 2023-2024 годах? Или это полная лажа?".
20.08.2023 17:46
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
19.08.2023 18:39
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в частности, магию поплавков и гибкость flexbox.
19.08.2023 17:22
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для чтения благодаря своей простоте. Кроме того, мы всегда хотим проверить самые последние возможности в наших проектах!
18.08.2023 20:33
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий их языку и культуре.
14.08.2023 14:49
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип предназначен для представления неделимого значения.