blog.b4tman.ru/content/post/2020-11-13-pandas-stoks.md

5.5 KiB
Raw Blame History

title date tags
Анализ корреляций биржевых колебаний 2020-11-12
Python
pandas
jupyter
MOEX
stoks
ETF

Поэкспирементировал в Jupyter Lab и нарисовал несколько графиков на тему корреляции колебаний курса ETF и акций.

Ставим зависимости, если надо.

# !conda install snappy python-snappy pyarrow fastparquet 
# !pip install pandas_datareader

Настраиваем графики и импортируем библиотеки.

%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 биржи в локальный каталог.


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

Загружаем кешированные на диске данные.


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.

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))

Обрабатываем данные, чтобы убрать всё кроме нужного режима торгов, и интерполируем цену.


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 и медианой этого показателя. Затем соединяем таблицы и строим графики.

# 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


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


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


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


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