# Публикация иследовани по анализу и прогнозу стоимости угля.
# 2024-05-20 09:20 пнд Нвг вар 01.
# 11:10 вар. 02
# Смоленышев Олег
# smolenishev@mail.ru
# +7 916 014 37 70
# https://otter-finance.ru
# 2024-08-20 11:00 втр Нвг вар 3. Актуализирую расчтеты по состоянию на 20 августа 2024 года.
Цель работы: провести анализ стоимости угля, проанализировать коррелирующие показатели, возможные предикторы и построить прогноз стоимости угля.
В первой части данной работы представлен анализ временых рядов стоимости основных биржевых товаров, в том числе с преминением показателей из технического анализа. Произведен переход к единицам измерения такие как: унции золота, и тонны нефти. В этим же единицах приведен анализ представленных временных рядов.
Во второй части произведено прогнозирование стоимости угля с использованием статистического анализа, глубокого обучения в нескольких единицах измерения. В последующем будет произведено прогнозирование с прменением нейроных сетей.
Disclaimer. Принимая во внимание, происходящие события, стирающие понятие рыынка, свободного ценообразования, котировок и т.д. все нежеизложенные рассуждения стали носить умозрительный характер, которые могли бы иметь основания в парадигмах, действовавших до 2022 года.
Динамика биржевых котировок товаров группы commodities подвержены значительной волатильности. Само изменения графиков, а также совокупность влияющих факторов (предикторов) на такие изменения стоимостей изучаются и анализируются как биржевыми спекулянтами так и учёными. Есть обоснованные предположения, что «Случайное блуждание — хорошая стартовая модель для описания финансовых временных рядов». Модель случайного блуждания предполагает, что движение элемента (или группы элементов) не предсказуемо. Поэтому попробуем для оценки тенденций применить методы технического анализа, которые используют биржевые спекулянты.
Следующий возникающий вопрос заключается, а в чем мы производим измерения и почему именно в долл. или фунтах. Однако, согласитесь, что трудно что-либо «измерять» если твоя «линейка» постоянно увеличивается и причем в некоторых случаях в геометрической прогрессии путём денежной эмиссии в долларах США (см. показатель M2 с сайта Федеральной резервной системы США (https://fred.stlouisfed.org/categories/29). В как же получить "абсолютный" эквивалент истинной стоимости. Ответить на данный вопрос достаточно затруднительно. Отсылаю к экономической теории и теории эффективного фондового рынка.
В таких условиях предлагаю рассмотреть возможность и "вернуться" к так называемому «золотому стандарту», добавить к нему ещё и «нефтяной стандарт», далее оценивать биржевые товары в унциях золота и баррелях нефти. Исходя из этого в данных расчётах использование «измеритель» в долл.США буду условно - только для пересчёта одних биржевых товаров в тройские унции и баррели.
Многофакторность влияющих предпосылок на волатильность и динамику цен приводит к признанию случайного блуждания, как основной гипотезы. Однако наличие причинно-следственных связей заметны даже не всегда осведомленным обывателям.
Во второй части:
Производится прогнозирование по временным рядам (с акцентом на прогноз стоимости тонны угля) с помощью пакета sktime. (Также ссылка на GitHub sktime)
Пакет Sktime является гибкой модульной платформой с открытым исходным кодом для задач, связанных с иследованиями временных рядов.
как многомерные воспользуемся моделью VAR - векторная авторегрессия. (https://ru.wikipedia.org/wiki/Векторная_авторегрессия) и построим прогноз стоимости активов на ближайшее будущее в разных единицах измерения. Ключом к прогнозированию многомерных макроэкономических временных рядов является отображение как временных вариаций для каждого признака, так и возможных корреляций между ними в каждом периоде. Модель VAR служит таким целям, используя матрицы в качестве коэффициентов для отображения линейных зависимостей между периодами и между объектами. Он предполагает случайный процесс, который генерирует данные, и пытается оценить параметры модели, которые можно рассматривать как плавное приближение к структуре, которая сгенерировала данные.
# Загрузка необходимых библиотек Python
import numpy as np
import pandas as pd
import pandas_datareader as pdr
import yfinance as yf
import matplotlib.pyplot as plt
from matplotlib import pyplot
import mplcyberpunk
from pandas.plotting import scatter_matrix
import seaborn as sns
from sklearn import preprocessing
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import Normalizer
from sklearn.preprocessing import normalize
#for ARIMA
from statsmodels.tsa.arima_model import ARIMA
from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.graphics.tsaplots import plot_pacf
import statsmodels.api as sm
# Для разлож временного ряда на компаненты
import pandas_datareader.data as web
import statsmodels.tsa.api as tsa
from pylab import rcParams
import itertools
import warnings
from scipy.stats import pearsonr, spearmanr
# sktime
from sktime.registry import all_estimators
from sktime.forecasting.base import ForecastingHorizon
from sktime.forecasting.arima import ARIMA
from sktime.forecasting.arima import AutoARIMA
from sktime.forecasting.var import VAR
from sktime.forecasting.varmax import VARMAX
from sktime.forecasting.ets import AutoETS
from sktime.forecasting.fbprophet import Prophet
from sktime.forecasting.naive import NaiveForecaster
from sktime.forecasting.bats import BATS
from sktime.forecasting.tbats import TBATS
from sktime.forecasting.theta import ThetaForecaster
from sktime.forecasting.model_evaluation import evaluate
from sktime.forecasting.model_selection import ExpandingWindowSplitter
from sktime.forecasting.model_selection import temporal_train_test_split
from sktime.forecasting.model_selection import (
ForecastingGridSearchCV,
ExpandingWindowSplitter)
from sktime.forecasting.compose import MultiplexForecaster
from sktime.forecasting.naive import NaiveForecaster
from sktime.forecasting.theta import ThetaForecaster
from sktime.forecasting.model_evaluation import evaluate
from sktime.utils import plotting
from sktime.utils.plotting import plot_series
from sktime.performance_metrics.forecasting import mean_absolute_percentage_error
from sktime.performance_metrics.forecasting import MeanAbsolutePercentageError
import pandas_ta as ta
import datetime as dt
import prophet
/home/sm360/.local/lib/python3.12/site-packages/matplotlib/projections/__init__.py:63: UserWarning: Unable to import Axes3D. This may be due to multiple versions of Matplotlib being installed (e.g. as a system package and as a pip package). As a result, the 3D projection is not available. warnings.warn("Unable to import Axes3D. This may be due to multiple versions of " /home/sm360/.local/lib/python3.12/site-packages/dask/dataframe/__init__.py:42: FutureWarning: Dask dataframe query planning is disabled because dask-expr is not installed. You can install it with `pip install dask[dataframe]` or `conda install dask`. This will raise in a future version. warnings.warn(msg, FutureWarning)
# Задание параметров вывода
# Формат чисел
# pd.option_context('display.float_format', '{:0.20f}'.format)
pd.set_option("display.precision", 5)
pd.set_option('display.max_columns', 25)
# pd.set_option('display.max_rows', 15)
# настройка графиков
plt.style.use("cyberpunk")
# Сегодня
today = pd.Timestamp.now().normalize()
# today = pd.Timestamp.now().to_period('D')
today
Timestamp('2024-08-20 00:00:00')
Загружаем данные с https://finance.yahoo.com/, сразу получаем представление в графике и строим datagrame по цене закрытия.
Дату начала анализа временных рядов принял за 1 января 2015 года.
# yfinance
start_date = dt.datetime(2015,1,1)
end_date = dt.datetime(2024,8,20)
test = yf.download(tickers = "GOOGL", start = start_date, end = end_date)
test
[*********************100%%**********************] 1 of 1 completed
Open | High | Low | Close | Adj Close | Volume | |
---|---|---|---|---|---|---|
Date | ||||||
2015-01-02 | 26.63000 | 26.7900 | 26.39400 | 26.47750 | 26.44715 | 26480000 |
2015-01-05 | 26.35750 | 26.3995 | 25.88750 | 25.97300 | 25.94322 | 41182000 |
2015-01-06 | 26.02500 | 26.0605 | 25.27750 | 25.33200 | 25.30296 | 54456000 |
2015-01-07 | 25.54750 | 25.5745 | 25.18250 | 25.25750 | 25.22854 | 46918000 |
2015-01-08 | 25.07550 | 25.3750 | 24.75100 | 25.34550 | 25.31645 | 73054000 |
... | ... | ... | ... | ... | ... | ... |
2024-08-13 | 163.41000 | 164.7300 | 162.97000 | 164.16000 | 164.16000 | 18551700 |
2024-08-14 | 162.39999 | 163.2200 | 157.71001 | 160.37000 | 160.37000 | 40591100 |
2024-08-15 | 160.50000 | 161.6400 | 159.61000 | 161.30000 | 161.30000 | 31524300 |
2024-08-16 | 161.47000 | 165.0600 | 161.13000 | 162.96001 | 162.96001 | 24208600 |
2024-08-19 | 165.28000 | 166.6900 | 164.25999 | 166.67000 | 166.67000 | 22390100 |
2423 rows × 6 columns
### array(['^IXIC', '^GSPC', 'ZC=F', 'HG=F', 'ALI=F', 'NG=F', 'PL=F', 'SI=F','GC=F', 'BZ=F', 'MTF=F'], dtype=object)
tickers = ['^IXIC', '^GSPC', 'ZC=F', 'HG=F', 'ALI=F', 'NG=F', 'PL=F', 'SI=F','GC=F', 'BZ=F', 'MTF=F']
df0 = pd.DataFrame()
for tic in tickers:
df_temp = yf.download(tic, start=start_date)
df_temp['Ticker'] = tic
df0 = pd.concat([df_temp, df0])
[*********************100%%**********************] 1 of 1 completed [*********************100%%**********************] 1 of 1 completed [*********************100%%**********************] 1 of 1 completed [*********************100%%**********************] 1 of 1 completed [*********************100%%**********************] 1 of 1 completed [*********************100%%**********************] 1 of 1 completed [*********************100%%**********************] 1 of 1 completed [*********************100%%**********************] 1 of 1 completed [*********************100%%**********************] 1 of 1 completed [*********************100%%**********************] 1 of 1 completed [*********************100%%**********************] 1 of 1 completed
# Посмотреть:
df0
Open | High | Low | Close | Adj Close | Volume | Ticker | |
---|---|---|---|---|---|---|---|
Date | |||||||
2015-01-05 | 63.65000 | 63.65000 | 63.65000 | 63.65000 | 63.65000 | 600 | MTF=F |
2015-01-06 | 62.70000 | 62.70000 | 62.70000 | 62.70000 | 62.70000 | 410 | MTF=F |
2015-01-07 | 60.90000 | 60.90000 | 60.90000 | 60.90000 | 60.90000 | 475 | MTF=F |
2015-01-08 | 60.60000 | 60.60000 | 60.60000 | 60.60000 | 60.60000 | 695 | MTF=F |
2015-01-09 | 60.15000 | 60.15000 | 60.15000 | 60.15000 | 60.15000 | 220 | MTF=F |
... | ... | ... | ... | ... | ... | ... | ... |
2024-08-13 | 16944.74023 | 17192.78906 | 16943.94922 | 17187.60938 | 17187.60938 | 5469160000 | ^IXIC |
2024-08-14 | 17227.64062 | 17260.73047 | 17032.16992 | 17192.59961 | 17192.59961 | 4985480000 | ^IXIC |
2024-08-15 | 17394.53906 | 17602.72070 | 17375.41016 | 17594.50000 | 17594.50000 | 5478170000 | ^IXIC |
2024-08-16 | 17516.40039 | 17674.65039 | 17502.83008 | 17631.72070 | 17631.72070 | 5138150000 | ^IXIC |
2024-08-19 | 17649.74023 | 17877.43945 | 17585.58008 | 17876.76953 | 17876.76953 | 5564300000 | ^IXIC |
26535 rows × 7 columns
# Все тикеры:
df0['Ticker'].unique()
array(['MTF=F', 'BZ=F', 'GC=F', 'SI=F', 'PL=F', 'NG=F', 'ALI=F', 'HG=F', 'ZC=F', '^GSPC', '^IXIC'], dtype=object)
# переименование тикеров в норм значения по заданному словарю
dic = {'MTF=F': 'coal', 'BZ=F': 'brent', 'GC=F': 'gold', 'SI=F': 'silver', 'PL=F': 'platinum', 'NG=F': 'gaz',
'ALI=F': 'aluminum', 'HG=F': 'cupper', 'ZC=F': 'corn', '^GSPC': 'SP', '^IXIC': 'NASDAQ'}
df0['Ticker'] = df0['Ticker'].replace(dic)
df0
Open | High | Low | Close | Adj Close | Volume | Ticker | |
---|---|---|---|---|---|---|---|
Date | |||||||
2015-01-05 | 63.65000 | 63.65000 | 63.65000 | 63.65000 | 63.65000 | 600 | coal |
2015-01-06 | 62.70000 | 62.70000 | 62.70000 | 62.70000 | 62.70000 | 410 | coal |
2015-01-07 | 60.90000 | 60.90000 | 60.90000 | 60.90000 | 60.90000 | 475 | coal |
2015-01-08 | 60.60000 | 60.60000 | 60.60000 | 60.60000 | 60.60000 | 695 | coal |
2015-01-09 | 60.15000 | 60.15000 | 60.15000 | 60.15000 | 60.15000 | 220 | coal |
... | ... | ... | ... | ... | ... | ... | ... |
2024-08-13 | 16944.74023 | 17192.78906 | 16943.94922 | 17187.60938 | 17187.60938 | 5469160000 | NASDAQ |
2024-08-14 | 17227.64062 | 17260.73047 | 17032.16992 | 17192.59961 | 17192.59961 | 4985480000 | NASDAQ |
2024-08-15 | 17394.53906 | 17602.72070 | 17375.41016 | 17594.50000 | 17594.50000 | 5478170000 | NASDAQ |
2024-08-16 | 17516.40039 | 17674.65039 | 17502.83008 | 17631.72070 | 17631.72070 | 5138150000 | NASDAQ |
2024-08-19 | 17649.74023 | 17877.43945 | 17585.58008 | 17876.76953 | 17876.76953 | 5564300000 | NASDAQ |
26535 rows × 7 columns
# беру только столбец с ценой закрытия и сам тикер
df01 = df0[['Close', 'Ticker']]
df01
Close | Ticker | |
---|---|---|
Date | ||
2015-01-05 | 63.65000 | coal |
2015-01-06 | 62.70000 | coal |
2015-01-07 | 60.90000 | coal |
2015-01-08 | 60.60000 | coal |
2015-01-09 | 60.15000 | coal |
... | ... | ... |
2024-08-13 | 17187.60938 | NASDAQ |
2024-08-14 | 17192.59961 | NASDAQ |
2024-08-15 | 17594.50000 | NASDAQ |
2024-08-16 | 17631.72070 | NASDAQ |
2024-08-19 | 17876.76953 | NASDAQ |
26535 rows × 2 columns
# Посмотреть. Сводная табл
df02 = pd.pivot_table(df01, index=df01.index, values=['Close'] , columns=['Ticker'])
df02
Close | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Ticker | NASDAQ | SP | aluminum | brent | coal | corn | cupper | gaz | gold | platinum | silver |
Date | |||||||||||
2015-01-02 | 4726.81006 | 2058.19995 | 2168.50 | 56.42 | NaN | 395.75 | 2.8385 | 3.003 | 1186.00000 | 1203.00000 | 15.734 |
2015-01-05 | 4652.56982 | 2020.57996 | 2148.25 | 53.11 | 63.65 | 406.00 | 2.7930 | 2.882 | 1203.90002 | 1210.09998 | 16.179 |
2015-01-06 | 4592.74023 | 2002.60999 | 2144.50 | 51.10 | 62.70 | 405.00 | 2.8040 | 2.938 | 1219.30005 | 1220.80005 | 16.603 |
2015-01-07 | 4650.47021 | 2025.90002 | 2165.00 | 51.15 | 60.90 | 396.25 | 2.7960 | 2.871 | 1210.59998 | 1220.69995 | 16.510 |
2015-01-08 | 4736.18994 | 2062.13989 | 2202.75 | 50.96 | 60.60 | 394.25 | 2.8070 | 2.927 | 1208.40002 | 1221.69995 | 16.351 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
2024-08-14 | 17192.59961 | 5455.20996 | 2211.00 | 79.76 | 121.90 | 381.00 | 4.0250 | 2.219 | 2439.39990 | 927.59998 | 27.254 |
2024-08-15 | 17594.50000 | 5543.22021 | 2237.00 | 81.04 | 122.50 | 375.00 | 4.1390 | 2.197 | 2453.10010 | 960.00000 | 28.342 |
2024-08-16 | 17631.72070 | 5554.25000 | 2235.50 | 79.68 | 122.40 | 370.50 | 4.1275 | 2.123 | 2498.60010 | 957.29999 | 28.778 |
2024-08-19 | 17876.76953 | 5608.25000 | 2308.75 | 77.66 | 122.40 | 378.00 | 4.1665 | 2.235 | 2501.80005 | 958.90002 | 29.240 |
2024-08-20 | NaN | NaN | 2336.50 | 76.85 | NaN | 398.75 | 4.1835 | 2.234 | 2550.30005 | 966.40002 | 29.630 |
2425 rows × 11 columns
# убираю мильтиндекс из сводн табл
df02 = df02['Close']
df02
Ticker | NASDAQ | SP | aluminum | brent | coal | corn | cupper | gaz | gold | platinum | silver |
---|---|---|---|---|---|---|---|---|---|---|---|
Date | |||||||||||
2015-01-02 | 4726.81006 | 2058.19995 | 2168.50 | 56.42 | NaN | 395.75 | 2.8385 | 3.003 | 1186.00000 | 1203.00000 | 15.734 |
2015-01-05 | 4652.56982 | 2020.57996 | 2148.25 | 53.11 | 63.65 | 406.00 | 2.7930 | 2.882 | 1203.90002 | 1210.09998 | 16.179 |
2015-01-06 | 4592.74023 | 2002.60999 | 2144.50 | 51.10 | 62.70 | 405.00 | 2.8040 | 2.938 | 1219.30005 | 1220.80005 | 16.603 |
2015-01-07 | 4650.47021 | 2025.90002 | 2165.00 | 51.15 | 60.90 | 396.25 | 2.7960 | 2.871 | 1210.59998 | 1220.69995 | 16.510 |
2015-01-08 | 4736.18994 | 2062.13989 | 2202.75 | 50.96 | 60.60 | 394.25 | 2.8070 | 2.927 | 1208.40002 | 1221.69995 | 16.351 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
2024-08-14 | 17192.59961 | 5455.20996 | 2211.00 | 79.76 | 121.90 | 381.00 | 4.0250 | 2.219 | 2439.39990 | 927.59998 | 27.254 |
2024-08-15 | 17594.50000 | 5543.22021 | 2237.00 | 81.04 | 122.50 | 375.00 | 4.1390 | 2.197 | 2453.10010 | 960.00000 | 28.342 |
2024-08-16 | 17631.72070 | 5554.25000 | 2235.50 | 79.68 | 122.40 | 370.50 | 4.1275 | 2.123 | 2498.60010 | 957.29999 | 28.778 |
2024-08-19 | 17876.76953 | 5608.25000 | 2308.75 | 77.66 | 122.40 | 378.00 | 4.1665 | 2.235 | 2501.80005 | 958.90002 | 29.240 |
2024-08-20 | NaN | NaN | 2336.50 | 76.85 | NaN | 398.75 | 4.1835 | 2.234 | 2550.30005 | 966.40002 | 29.630 |
2425 rows × 11 columns
# Посмотреть
df02.info()
<class 'pandas.core.frame.DataFrame'> DatetimeIndex: 2425 entries, 2015-01-02 to 2024-08-20 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 NASDAQ 2423 non-null float64 1 SP 2423 non-null float64 2 aluminum 2386 non-null float64 3 brent 2418 non-null float64 4 coal 2372 non-null float64 5 corn 2420 non-null float64 6 cupper 2422 non-null float64 7 gaz 2423 non-null float64 8 gold 2422 non-null float64 9 platinum 2405 non-null float64 10 silver 2421 non-null float64 dtypes: float64(11) memory usage: 227.3 KB
# создаю переменную с названием столбцов
col = df02.columns
col
Index(['NASDAQ', 'SP', 'aluminum', 'brent', 'coal', 'corn', 'cupper', 'gaz', 'gold', 'platinum', 'silver'], dtype='object', name='Ticker')
# df только по углю
coal = df02[['coal']].copy()
coal
Ticker | coal |
---|---|
Date | |
2015-01-02 | NaN |
2015-01-05 | 63.65 |
2015-01-06 | 62.70 |
2015-01-07 | 60.90 |
2015-01-08 | 60.60 |
... | ... |
2024-08-14 | 121.90 |
2024-08-15 | 122.50 |
2024-08-16 | 122.40 |
2024-08-19 | 122.40 |
2024-08-20 | NaN |
2425 rows × 1 columns
# coal.info()
coal.index
DatetimeIndex(['2015-01-02', '2015-01-05', '2015-01-06', '2015-01-07', '2015-01-08', '2015-01-09', '2015-01-12', '2015-01-13', '2015-01-14', '2015-01-15', ... '2024-08-07', '2024-08-08', '2024-08-09', '2024-08-12', '2024-08-13', '2024-08-14', '2024-08-15', '2024-08-16', '2024-08-19', '2024-08-20'], dtype='datetime64[ns]', name='Date', length=2425, freq=None)
# удаляю Nan
coal.dropna(how='any', inplace=True)
coal
Ticker | coal |
---|---|
Date | |
2015-01-05 | 63.65 |
2015-01-06 | 62.70 |
2015-01-07 | 60.90 |
2015-01-08 | 60.60 |
2015-01-09 | 60.15 |
... | ... |
2024-08-13 | 120.75 |
2024-08-14 | 121.90 |
2024-08-15 | 122.50 |
2024-08-16 | 122.40 |
2024-08-19 | 122.40 |
2372 rows × 1 columns
# график за ближайшие дни
fig = plt.figure(figsize=(12, 4))
plt.grid(2)
plt.title('Стоимость тонны угля в $ за предыдущие дни')
plt.plot(coal['coal']['2023-05-01':])
# plt.plot(coal)
plt.xlabel("Период", fontsize = 10)
plt.ylabel("$", fontsize = 10)
plt.show()
# скользящие средние разных периодов
coal_rol180 = coal.rolling(180).mean()
coal_rol90 = coal.rolling(90).mean()
coal_rol30 = coal.rolling(30).mean()
# график скользящих средних
fig, ax = plt.subplots(figsize = (12,4), dpi = 100)
# plt.figure(figsize=(12, 4))
plt.grid(1)
plt.plot(coal, label='Стоимость угля')
plt.plot(coal_rol180, label='Скользящая средняя 180 дней')
plt.plot(coal_rol90, label='Скользащая средняя 90 дней')
plt.plot(coal_rol30, label='Скользящая средняя 30 дней')
plt.title('Coal. Уголь в $ за тонну. Скользящие средние')
plt.xlabel("Период", fontsize = 10)
plt.ylabel("$", fontsize = 10)
plt.legend()
plt.show()
На вышепредставленном графике на основании рекомендаций из технического анализа следует обратить внимание на пересечение короткой и длинной скользящих средних. Особенность пересчечения короткой скользящей средней с верху или с низу показывает изменение тренда.
# Уголь в $. Полосы Боллинджера с заданной даты (за меньший период времени)
n = 30
date = '2021-01-01'
coal_d = coal[date:]
coal_ma = coal_d.rolling(window=n).mean()
coal_sd = coal_d.rolling(window=n).std()
coal_line1 = coal_ma + (2 * coal_sd)
coal_line2 = coal_ma - (2 * coal_sd)
# График
plt.figure(figsize=(12, 4))
plt.grid(1)
plt.plot(coal_d, label='Биржевая котировка')
plt.plot(coal_line1, label='Верхняя полоса')
plt.plot(coal_line2, label='Нижняя полоса')
plt.title(f'Coal. Уголь в $ за тонну. Полосы Боллинджера c {date} по {n}-дневному периоду')
plt.xlabel("Период", fontsize = 10)
plt.ylabel("$", fontsize = 10)
plt.legend()
plt.show()
# На графике полос Боллинджера смотрим на ... дописать
# привожу к месячным значениям
coal2 = coal.resample("M").mean().squeeze().dropna()
coal2
Date 2015-01-31 59.47632 2015-02-28 61.71176 2015-03-31 61.54950 2015-04-30 59.24471 2015-05-31 59.20000 ... 2024-04-30 117.84682 2024-05-31 106.17909 2024-06-30 110.32421 2024-07-31 106.11682 2024-08-31 121.53077 Freq: M, Name: coal, Length: 116, dtype: float64
# декомпозиция временного ряда стоимости угля:
components = tsa.seasonal_decompose(coal2, model='additive')
ts = (coal2.to_frame('Original')
.assign(Trend=components.trend)
.assign(Seasonality=components.seasonal)
.assign(Residual=components.resid))
ts.plot(subplots=True, figsize=(14, 8));