Анализ акций Tesla с помощью Python

Целью этого проекта был анализ возможностей Python для исследования цен на акции. Легенда этого исследования такова: некий инвестор хочет инвестировать в акции Tesla, потому что он видит хорошую тенденцию к росту на многочисленных биржевых сайтах. Я, как аналитик, должен ответить ему хорошее ли сейчас время для покупки или нет.

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

Итак, давайте посмотрим как можно проанализировать акции с помощью Python. Давайте импортируем котировки акций Tesla в Jupyter Notebook. Мы это сделаем через библиотеку yfinance от Yahoo. А для анализа данных и построения графиков будем использовать библиотеки pandas, datetime и plotly.

import pandas as pd
import yfinance as yf
import datetime
from datetime import date, timedelta
import plotly.graph_objects as go
import plotly.express as px

today = date.today()
d1 = today.strftime("%Y-%m-%d")
end_date = d1
d2 = date.today() - timedelta(days=365)
d2 = d2.strftime("%Y-%m-%d")
start_date = d2
data = yf.download('TSLA', 
                      start=start_date, 
                      end=end_date, 
                      progress=False)
data["Date"] = data.index
data = data[["Date", "Open", "High", "Low", "Close"]]
data.reset_index(drop=True, inplace=True)
print(data.tail(15))

Котировки акций в Jupyter Notebook
Рис. 1: Котировки акций в Jupyter Notebook

Беглого взгляда на эти данные достаточно, чтобы понять что акции Тесла уверенно растут последние 15 дней и этот рост составил 11%!

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

figure = go.Figure(data=[go.Candlestick(x=data["Date"],
                                        open=data["Open"], high=data["High"],
                                        low=data["Low"], close=data["Close"])])
figure.update_layout(title = "Свечной график акций Тесла", xaxis_rangeslider_visible=False)
figure.show()

Свечной график акций Tesla

Рис. 2: Свечной график акций Tesla

Как мы видим по этому графику разброс цен на акции Тесла за последние 365 дней был коллоссальным (от 140 с небольшим долларов до 270). И сейчас мы находимся выше середины этого диапазона.

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

figure = px.bar(data, title = "Бар-чарт акций Тесла", x = "Date", y= "Close")
figure.show()

Бар-чарт акций Tesla

Рис. 3: Бар-чарт акций Tesla

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

По этому бар-чарту более наглядно видно где у акций дно, а где пики. И очевидно, что краткосрочно (на несколько недель) у нас есть шансы на рост. Но не более того, так как мы близки к годовому максимуму. Чтобы убедиться в этом, давайте построим еще один график – Range Slider.

figure = px.line(data, x='Date', y='Close', 
                 title='Анализ акций Тесла с селекторами времени')
figure.update_xaxes(rangeslider_visible=True)
figure = px.line(data, x='Date', y='Close', 
                 title='Анализ акций Тесла с селекторами времени')

figure.update_xaxes(
    rangeselector=dict(
        buttons=list([
            dict(count=1, label="1m", step="month", stepmode="backward"),
            dict(count=6, label="6m", step="month", stepmode="backward"),
            dict(count=3, label="3m", step="month", stepmode="backward"),
            dict(count=1, label="1y", step="year", stepmode="backward"),
            dict(step="all")
        ])
    )
)
figure.show()

График цен акций Tesla с селекторами времени

Рис. 4: График цен акций Tesla с селекторами времени

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

Читайте также:  Прогнозирование временных рядов с помощью ARIMA, SARIMA, ARFIMA

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

Анализ с использованием скользящих средних

Одним из самых популярных инструментов для анализа трендов на финансовых рынках является скользящая средняя (SMA – Simple Moving Average). Давайте добавим 50-дневную и 100-дневную скользящие средние, чтобы лучше понять долгосрочные и краткосрочные тренды в котировках акций Tesla.

data['SMA50'] = data['Close'].rolling(window=50).mean()
data['SMA100'] = data['Close'].rolling(window=100).mean()

# График с SMA
figure = go.Figure()
figure.add_trace(go.Scatter(x=data['Date'], y=data['Close'], name='Цена закрытия', mode='lines'))
figure.add_trace(go.Scatter(x=data['Date'], y=data['SMA50'], name='50-дневная SMA', mode='lines'))
figure.add_trace(go.Scatter(x=data['Date'], y=data['SMA100'], name='100-дневная SMA', mode='lines'))
figure.update_layout(title='Акции Tesla с 50 и 100-дневными скользящими средними', xaxis_rangeslider_visible=False)
figure.show()

Акции Tesla с 50-дневной и 100-дневной скользящими средними (SMA)

Рис. 5: Акции Tesla с 50-дневной и 100-дневной скользящими средними (SMA)

На этом графике хорошо видны долгосрочные и краткосрочные тренды. Когда краткосрочная (50-дневная) скользящая средняя пересекает долгосрочную (100-дневную) сверху вниз, это сигнал на продажу (так называемый “мёртвый крест”). И наоборот, пересечение снизу вверх может быть сигналом на покупку (“золотой крест”).

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

Индикатор относительной силы (RSI)

Следующим шагом является использование индикатора RSI (Relative Strength Index). RSI показывает, перекуплены или перепроданы акции на текущем рынке. Значение выше 70 говорит о перекупленности акций, а ниже 30 — о перепроданности.

import numpy as np

# Функция для расчета RSI
def calculate_RSI(data, window=14):
    # Вычисляем изменения цены закрытия
    delta = data['Close'].diff(1)
    
    # Отделяем положительные и отрицательные изменения
    gain = np.where(delta > 0, delta, 0)
    loss = np.where(delta < 0, -delta, 0)
    
    # Скользящее среднее для прибыли и убытков
    avg_gain = pd.Series(gain).rolling(window=window, min_periods=1).mean()
    avg_loss = pd.Series(loss).rolling(window=window, min_periods=1).mean()
    
    # Рассчитываем RS (отношение средних прибылей к убыткам)
    rs = avg_gain / avg_loss
    
    # Рассчитываем RSI
    rsi = 100 - (100 / (1 + rs))
    return rsi

# Добавляем RSI в DataFrame
data['RSI'] = calculate_RSI(data)

# Строим график с RSI
figure = go.Figure()
figure.add_trace(go.Scatter(x=data['Date'], y=data['RSI'], name='RSI', mode='lines'))
figure.add_hline(y=70, line_dash="dash", line_color="red", annotation_text="Перекупленность", annotation_position="top right")
figure.add_hline(y=30, line_dash="dash", line_color="green", annotation_text="Перепроданность", annotation_position="bottom right")
figure.update_layout(title='Индикатор RSI для акций Tesla', xaxis_rangeslider_visible=False)
figure.show()

Анализ акций на перекупленность / перепроданность методом RSI

Рис. 6: Анализ акций на перекупленность / перепроданность методом RSI

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

Читайте также:  Методы предиктивной аналитики и машинного обучения для оптимизации конверсии веб-сайтов

Как работает этот код? Все очень просто. Мы рассчитываем следующие метрики:

  • Изменение цен (delta): Рассчитываем разницу между сегодняшней и вчерашней ценами закрытия.
  • Прибыль и убыток (gain/loss): Из этой разницы извлекаем положительные значения (прибыль) и отрицательные (убыток).
  • Скользящее среднее: Рассчитываем средние прибыли и убытки за указанное окно (обычно 14 дней).
  • RSI: Далее вычисляется относительный индекс на основе формулы индикатора RSI.

Прогнозирование котировок с помощью машинного обучения

В заключение, давайте попробуем предсказать цены акций Tesla с помощью модели машинного обучения. Я буду использовать здесь метод LSTM (Long Short-Term Memory), который отлично подходит для временных рядов. Однако для начала проведу предварительную подготовку данных и разделю их на обучающую и тестовую выборки.

from sklearn.preprocessing import MinMaxScaler
import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense

# Нормализация данных
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(data['Close'].values.reshape(-1,1))

# Подготовка данных для LSTM
prediction_days = 60
X_train, y_train = [], []

for x in range(prediction_days, len(scaled_data)):
    X_train.append(scaled_data[x-prediction_days:x, 0])
    y_train.append(scaled_data[x, 0])

X_train, y_train = np.array(X_train), np.array(y_train)
X_train = np.reshape(X_train, (X_train.shape[0], X_train.shape[1], 1))

Что делает этот код? Рассмотрим по шагам:

  1. Импортирует необходимые библиотеки: MinMaxScaler, numpy, Sequential, LSTM, Dense;
  2. Нормализует данные о ценах закрытия акций в диапазоне от 0 до 1 с помощью MinMaxScaler;
  3. Устанавливает количество дней для предсказания (60);
  4. Создает списки для входных (X_train) и выходных (y_train) данных;
  5. Заполняет X_train последовательностями из 60 дней и y_train соответствующими значениями на следующий день;
  6. Преобразует списки в массивы NumPy;
  7. Изменяет форму массива X_train для соответствия требованиям LSTM (3 измерения: образцы, временные шаги, признаки).

Окей. Давайте приступим к обучению модели.

# Создание модели LSTM
model = Sequential()

model.add(LSTM(units=50, return_sequences=True, input_shape=(X_train.shape[1], 1)))
model.add(LSTM(units=50, return_sequences=False))
model.add(Dense(units=1))

model.compile(optimizer='adam', loss='mean_squared_error')
model.fit(X_train, y_train, epochs=25, batch_size=32)

Процесс обучения модели LSTM (эпохи, затраченное время и лоссы)

Рис. 7: Процесс обучения модели LSTM (эпохи, затраченное время и лоссы)

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

Далее, чтобы оценить качество построенной модели, нам нужно будет сделать следующее:

  1. Провести тестирование модели на новых данных: Мы разделим данные на обучающую и тестовую выборки, чтобы проверить качество предсказаний;
  2. Создать визуализацию прогнозов по сравнению с реальными данными: Построим график сравнения фактических данных и прогнозов;
  3. Провести оценку точности модели: Рассчитаем метрики качества, такие как RMSE (корень среднеквадратичной ошибки) или MAE (средняя абсолютная ошибка);
  4. Сохранить веса модели для дальнейшего использования (продакшен).
from sklearn.metrics import mean_squared_error, mean_absolute_error
import math
import matplotlib.pyplot as plt

# Разделение данных на обучающую и тестовую выборки
train_data_len = int(len(scaled_data) * 0.8)
test_data = scaled_data[train_data_len - prediction_days:]

X_test, y_test = [], []
for x in range(prediction_days, len(test_data)):
    X_test.append(test_data[x-prediction_days:x, 0])
    y_test.append(test_data[x, 0])

X_test, y_test = np.array(X_test), np.array(y_test)
X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))

# Прогнозирование на тестовых данных
predicted_prices = model.predict(X_test)
predicted_prices = scaler.inverse_transform(predicted_prices)  # Денормализация

# Денормализуем тестовые данные для сравнения
real_prices = scaler.inverse_transform(y_test.reshape(-1, 1))

# Оценка модели с помощью метрик
rmse = math.sqrt(mean_squared_error(real_prices, predicted_prices))
mae = mean_absolute_error(real_prices, predicted_prices)

print(f"RMSE: {rmse}")
print(f"MAE: {mae}")

Значения метрик RMSE и MAE для тестовой выборки

Рис. 8: Значения метрик RMSE и MAE для тестовой выборки

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

# Визуализация прогноза и реальных данных
plt.figure(figsize=(10,6))
plt.plot(real_prices, color='blue', label='Реальные цены')
plt.plot(predicted_prices, color='red', label='Прогнозируемые цены')
plt.title('Прогноз цен акций Tesla с помощью LSTM')
plt.xlabel('Время')
plt.ylabel('Цена акции')
plt.legend()
plt.show()

Прогноз цен акций Tesla с помощью модели LSTM

Рис. 9: Прогноз цен акций Tesla с помощью модели LSTM

Увы, но график не впечатлил. Да, в целом модель угадывает направление верно, но запаздывание просто кошмарное!

Читайте также:  Анализ поездок в такси с помощью статистических методов

Очевидно, что наша модель – сырая. Такую нельзя пускать в прод. Но для полноты исследования давайте все-же сохраним веса.

# Сохранение модели
model.save('lstm_tesla_model.h5')

Итак, давайте подытожим каков был алгоритм нашей модели и что тут можно улучшить:

  1. Тестовые данные: Мы взяли 20% последних данных для тестирования, сохраняя 80% для обучения. Никакой кросс-валидации здесь сделано не было;
  2. Прогнозы: После обучения модели, она предсказывает цены на основе тестовой выборки. Можно добавить еще валидационную выборку;
  3. Оценка точности: Использовали метрики RMSE, измеряющую среднее отклонение предсказанных цен от фактических и MAE, которая показывает среднюю разницу между фактическими и прогнозируемыми значениями. Можно добавить еще R2, MAPE, попробовать обучать модель по ним;
  4. Визуализация: Построили график для сравнения фактических и предсказанных цен акций. Можно добавить график остатков;
  5. Сохранение модели: Сохранили модель в файл, чтобы ее можно было использовать для предсказаний в будущем.

Выводы

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