post pandas-stoks
This commit is contained in:
		
							
								
								
									
										210
									
								
								content/post/2020-11-13-pandas-stoks.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								content/post/2020-11-13-pandas-stoks.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,210 @@
 | 
			
		||||
---
 | 
			
		||||
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 конечно.
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
На российском рынке по произвольно выбранным акциям корреляция слабая.
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Разница в колебаниях FXUS и FXIT.
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Между Яндексом и FXIT некоторая корреляция есть.    
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Между FXWO и FXUS корреляция очень сильная.
 | 
			
		||||

 | 
			
		||||
		Reference in New Issue
	
	Block a user