blog.b4tman.ru/content/post/2020-11-13-pandas-stoks.md
2020-11-13 12:21:02 +03:00

211 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Анализ корреляций биржевых колебаний
date: 2020-11-12
tags: [Python, pandas, jupyter, MOEX, stoks, ETF]
---
Поэкспирементировал в Jupyter Lab и нарисовал несколько графиков на тему корреляции колебаний курса ETF и акций.
<!--more-->
Ставим зависимости, если надо.
```python
# !conda install snappy python-snappy pyarrow fastparquet
# !pip install pandas_datareader
```
```
```
Настраиваем графики и импортируем библиотеки.
```python
%matplotlib inline
%config InlineBackend.figure_format = 'svg' #векторный формат
from matplotlib import pyplot as plt
plt.style.use('ggplot') # Красивые графики
plt.rcParams['figure.figsize'] = (12, 5) # Размер картинок
import numpy as np
import pandas as pd
from datetime import timedelta
from datetime import datetime
import math
import os
import pandas_datareader.data as web
```
```
```
Скачиваем информацию через API биржи в локальный каталог.
```python
tikers = 'SBER,AFKS,GAZP,MAIL,YNDX,FXUS,FXIT,FXCN,FXDE,FXWO,FXRW'.split(',')
def download_data(tiker, path):
filepath = os.path.join(path, f'{tiker}_2020.parquet')
if os.path.exists(filepath):
return
df = web.DataReader(tiker, 'moex', start='2020-01-01', end='2020-11-12')
df.to_parquet(filepath, engine='fastparquet')
for tiker in tikers:
print(f'downloading: {tiker}')
download_data(tiker, "D:\\data2\\Documents\\notebooks")
```
downloading: SBER
downloading: AFKS
downloading: GAZP
downloading: MAIL
downloading: YNDX
downloading: FXUS
downloading: FXIT
downloading: FXCN
downloading: FXDE
downloading: FXWO
downloading: FXRW
```
```
Загружаем кешированные на диске данные.
```python
def load_data(tiker, path):
result = None
filepath = os.path.join(path, f'{tiker}_2020.parquet')
if os.path.exists(filepath):
result = pd.read_parquet(filepath)
return result
dfs = {}
for tiker in tikers:
dfs[tiker] = load_data(tiker, "D:\\data2\\Documents\\notebooks")
```
```
```
Значения полей `BOARDID` (режимы торгов) у акций и ETF разные. Для акций берём `TQBR` а для фондов `TQTF`.
```python
dfs['FXIT']['BOARDID'].unique(), dfs['YNDX']['BOARDID'].unique()
```
(array(['TQTD', 'TQTF', 'SOTC', 'RPMO', 'PSRP', 'PSTF', 'PTTF'],
dtype=object),
array(['TQBR', 'SPEQ', 'SOTC', 'RPMO', 'RPEU', 'RPEO', 'MXBD', 'EQRP',
'PSRP', 'EQRD', 'LIQR', 'PSRD', 'PSRE', 'PTEQ', 'PSEQ'],
dtype=object))
```
```
Обрабатываем данные, чтобы убрать всё кроме нужного режима торгов, и интерполируем цену.
```python
def price_data(x_df, boardid='TQBR'):
xdf = x_df.copy()
xdf = xdf.where(xdf['BOARDID'] == boardid)
xdf.dropna(axis=0, how='all', inplace=True)
xdf.dropna(axis=1, how='all', inplace=True)
if 0 == xdf.size:
return xdf
xdf['OPEN'] = xdf['OPEN'].interpolate(method='polynomial', order=2);
xdf['CLOSE'] = xdf['CLOSE'].interpolate(method='polynomial', order=2);
xdf['WAPRICE'] = xdf['WAPRICE'].interpolate(method='polynomial', order=2);
return xdf
# для простоты, считаем что если имя начинается на FX то это ETF
for tiker in tikers:
dfs[tiker] = price_data(dfs[tiker], boardid='TQTF' if 'FX' in tiker else 'TQBR')
```
```
```
Нормализуем графики с помомщью отношения средневзвешеной (по объёму торгов) цены `WAPRICE` и медианой этого показателя.
Затем соединяем таблицы и строим графики.
```python
# WAPRICE/median
def calc_wdm(df):
return df['WAPRICE'] / df['WAPRICE'].median()
for tiker in tikers:
dfs[tiker][tiker] = calc_wdm(dfs[tiker])
df_base = dfs['FXIT'][[]]
def merge_dfs(base):
result = base
for tiker in tikers:
result = result.merge(dfs[tiker][[tiker]], how='outer', on='TRADEDATE')
return result
xxdf = merge_dfs(df_base)
xxdf['diff_us'] = xxdf['FXUS'] - xxdf['FXIT']
# рисуем графики
xxdf.plot(y='FXUS,FXIT,FXCN,FXDE,FXWO,FXRW'.split(','), kind='line', title='ETF: WAPRICE / median')
xxdf.plot(y='SBER,AFKS,GAZP,MAIL,YNDX'.split(','), kind='line', title='RU: WAPRICE / median')
xxdf.plot(y='diff_us'.split(','), kind='line', title='FXUS - FXIT')
xxdf.plot(y='FXIT,YNDX'.split(','), kind='line', title='FXIT & YNDX')
xxdf.plot(y='FXWO,FXRW,FXUS'.split(','), kind='line', title='FXUS & FXWO & FXRW');
```
```
```
Все ETF Finex достаточно сильно коррелируют, за исключением FXRW конечно.
![svg](/img/pstoks-201113/output_8_1.svg)
```
```
На российском рынке по произвольно выбранным акциям корреляция слабая.
![svg](/img/pstoks-201113/output_8_2.svg)
```
```
Разница в колебаниях FXUS и FXIT.
![svg](/img/pstoks-201113/output_8_3.svg)
```
```
Между Яндексом и FXIT некоторая корреляция есть.
![svg](/img/pstoks-201113/output_8_4.svg)
```
```
Между FXWO и FXUS корреляция очень сильная.
![svg](/img/pstoks-201113/output_8_5.svg)