07.03.2018       Выпуск 220 (05.03.2018 - 11.03.2018)       Статьи

Работа с Anaconda на примере поиска корреляции курсов криптовалют

Цель этой статьи — предоставить легкое введение в анализ данных с использованием Anaconda. Мы пройдем через написание простого скрипта Python для извлечения, анализа и визуализации данных по различным криптовалютам.

Читать>>




Экспериментальная функция:

Ниже вы видите текст статьи по ссылке. По нему можно быстро понять ссылка достойна прочтения или нет

Просим обратить внимание, что текст по ссылке и здесь может не совпадать.

Цель этой статьи — предоставить легкое введение в анализ данных с использованием Anaconda. Мы пройдем через написание простого скрипта Python для извлечения, анализа и визуализации данных по различным криптовалютам.

Шаг 1 — Настройка рабочей среды.

Единственные навыки, которые вам понадобятся, это базовое понимание Python.

Шаг 1.1 — Установка Anaconda

Дистрибутив Anaconda можно скачать на

официальном сайте

.

Установка проходит в стандартном Step-by-Step режиме.

Шаг 1.2 — Настройка рабочей среды проекта

После того, как Anaconda будет установлена, нужно создать и активировать новую среду для организации наших зависимостей.

Зачем использовать среды? Если вы планируете разрабатывать несколько проектов Python на своем компьютере, полезно хранить зависимости (программные библиотеки и пакеты) отдельно, чтобы избежать конфликтов. Anaconda создаст специальный каталог среды для зависимостей каждого проекта, чтобы все было организовано и разделено.

Сделать это можно либо через командную строку

conda create --name cryptocurrency-analysis python=3.6
run source activate cryptocurrency-analysis

(Linux/macOS)

или

activate cryptocurrency-analysis

(Windows)

либо через Anaconda Navigator

В данном случае среда активируется автоматически

Затем необходимо установить необходимые зависимости

NumPy

,

Pandas

,

nb_conda

,

Jupiter

,

Plotly

,

Quandl

.

conda install numpy pandas nb_conda jupyter plotly quandl

либо через Anaconda Navigator, поочередно каждый пакет

Это может занять несколько минут.

Шаг 1.3 — Запуск Jupyter Notebook

Так же существует вариант через командную строку

jupyter notebook

и откройте браузер на

http://localhost:8888/

и через Anaconda Navigator

Шаг 1.4 — Импорт зависимостей

После того, как вы откроете пустой Jupyter Notebook, первое, что нужно сделать — это импорт необходимых зависимостей.

import os
import numpy as np
import pandas as pd
import pickle
import quandl
from datetime import datetime

Затем импорт и активация автономного режима Plotly.

import plotly.offline as py
import plotly.graph_objs as go
import plotly.figure_factory as ff
py.init_notebook_mode(connected=True)

Шаг 2 — Получение данных о ценах на биткоин

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

Шаг 2.1 — Определение функции Quandl

Начнем с того, что определим функцию для загрузки и кэширования наборов данных из Quandl.

def get_quandl_data(quandl_id):
    '''Download and cache Quandl dataseries'''
    cache_path = '{}.pkl'.format(quandl_id).replace('/','-')
    try:
        f = open(cache_path, 'rb')
        df = pickle.load(f)   
        print('Loaded {} from cache'.format(quandl_id))
    except (OSError, IOError) as e:
        print('Downloading {} from Quandl'.format(quandl_id))
        df = quandl.get(quandl_id, returns="pandas")
        df.to_pickle(cache_path)
        print('Cached {} at {}'.format(quandl_id, cache_path))
    return df

Мы используем

pickle

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

Функция вернет данные в виде набора данных pandas.

Шаг 2.2 — Получение курса биткоина на бирже Kraken

Реализуем это следующим образом:

btc_usd_price_kraken = get_quandl_data('BCHARTS/KRAKENUSD')

Для проверки корректности отрабатывания скрипта мы можем посмотреть первые 5 строк полученного ответа используя метод head().

btc_usd_price_kraken.head()

Результат:

DateOpenHighLowCloseVolume (BTC)Volume (Currency)Weighted Price
2014-01-07874.67040892.06753810.00000810.0000015.62237813151.472844841.835522
2014-01-08810.00000899.84281788.00000824.9828719.18275616097.329584839.156269
2014-01-09825.56345870.00000807.42084841.869348.1583356784.249982831.572913
2014-01-10839.99000857.34056817.00000857.330568.0245106780.220188844.938794
2014-01-11858.20000918.05471857.16554899.8410518.74828516698.566929890.671709

И построить график для визуализации полученного массива

btc_trace = go.Scatter(x=btc_usd_price_kraken.index, y=btc_usd_price_kraken['Weighted Price'])
py.iplot([btc_trace])

Здесь мы используем Plotly для генерации наших визуализаций. Это менее традиционный выбор, чем некоторые из более известных библиотек, таких как Matplotlib, но я думаю, что Plotly — отличный выбор, поскольку он создает полностью интерактивные диаграммы с использованием

D3.js

.

Шаг 2.3 — Получение курса биткоина на нескольких биржах

Характер обмена заключается в том, что ценообразование определяется предложением и спросом, поэтому ни одна биржа не содержит «истинной цены» Биткойна. Чтобы решить эту проблему мы будем извлекать дополнительно данные из трех более крупных бирж для расчета совокупного индекса цены.

Мы будем загружать данные каждой биржи в словарь.

exchanges = ['COINBASE','BITSTAMP','ITBIT']

exchange_data = {}

exchange_data['KRAKEN'] = btc_usd_price_kraken

for exchange in exchanges:
    exchange_code = 'BCHARTS/{}USD'.format(exchange)
    btc_exchange_df = get_quandl_data(exchange_code)
    exchange_data[exchange] = btc_exchange_df
Шаг 2.4 — Объединение всех цен в единый набор данных

Определим простую функцию для объединения данных.

def merge_dfs_on_column(dataframes, labels, col):
    series_dict = {}
    for index in range(len(dataframes)):
        series_dict[labels[index]] = dataframes[index][col]
        
    return pd.DataFrame(series_dict)

Затем объединим все данные по столбцу «Weighted Price».

btc_usd_datasets = merge_dfs_on_column(list(exchange_data.values()), list(exchange_data.keys()), 'Weighted Price')

Теперь посмотрим последние пять строк, используя метод tail (), чтобы убедиться, что все выглядит нормально и так как мы хотели.

btc_usd_datasets.tail()

Результат:

DateBITSTAMPCOINBASEITBITKRAKENavg_btc_price_usd
2018-02-2810624.38289310643.05357310621.09942610615.58798710626.030970
2018-03-0110727.27260010710.94606410678.15687210671.65395310697.007372
2018-03-0210980.29865810982.18188110973.43404510977.06790910978.245623
2018-03-0311332.93446811317.10826211294.62076311357.53909511325.550647
2018-03-0411260.75125311250.77121111285.69072511244.83646811260.512414
Шаг 2.5 — Сравнение наборов данных о ценах.

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

def df_scatter(df, title, seperate_y_axis=False, y_axis_label='', scale='linear', initial_hide=False):
    label_arr = list(df)
    series_arr = list(map(lambda col: df[col], label_arr))
    
    layout = go.Layout(
        title=title,
        legend=dict(orientation="h"),
        xaxis=dict(type='date'),
        yaxis=dict(
            title=y_axis_label,
            showticklabels= not seperate_y_axis,
            type=scale
        )
    )
    
    y_axis_config = dict(
        overlaying='y',
        showticklabels=False,
        type=scale )
    
    visibility = 'visible'
    if initial_hide:
        visibility = 'legendonly'
        
    trace_arr = []
    for index, series in enumerate(series_arr):
        trace = go.Scatter(
            x=series.index, 
            y=series, 
            name=label_arr[index],
            visible=visibility
        )
        
        if seperate_y_axis:
            trace['yaxis'] = 'y{}'.format(index + 1)
            layout['yaxis{}'.format(index + 1)] = y_axis_config    
        trace_arr.append(trace)

    fig = go.Figure(data=trace_arr, layout=layout)
    py.iplot(fig)

И вызовем ее

df_scatter(btc_usd_datasets, 'Цена биткоина на биржах (USD) ')

Результат:

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

btc_usd_datasets.replace(0, np.nan, inplace=True)

И пересоздадим график

df_scatter(btc_usd_datasets, 'Bitcoin Price (USD) By Exchange')

Результат:

Шаг 2.6 — Расчет средней цены

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

btc_usd_datasets['avg_btc_price_usd'] = btc_usd_datasets.mean(axis=1)

Этот новый столбец является нашим индексом цены биткоина. Построим его график, чтобы убедиться, что он выглядит нормально.

btc_trace = go.Scatter(x=btc_usd_datasets.index, y=btc_usd_datasets['avg_btc_price_usd'])
py.iplot([btc_trace])

Результат:

Мы будем использовать эти данные позже, чтобы конвертировать обменные курсы других криптовалют в USD.

Шаг 3 — Получение данных по альтернативным криптовалютам

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

Шаг 3.1 — Определение функций для работы с Poloniex API.

Для получения данных мы будем использовать

API Poloniex

. Определим две вспомогательные функции для загрузки и кэширования JSON данных из этого API.

Сначала мы определим функцию

get_json_data

, которая будет загружать и кэшировать данные JSON из предоставленного URL.

def get_json_data(json_url, cache_path):
    try:        
        f = open(cache_path, 'rb')
        df = pickle.load(f)   
        print('Loaded {} from cache'.format(json_url))
    except (OSError, IOError) as e:
        print('Downloading {}'.format(json_url))
        df = pd.read_json(json_url)
        df.to_pickle(cache_path)
        print('Cached response at {}'.format(json_url, cache_path))
    return df

Затем мы определим функцию для форматирования HTTP-запросов Poloniex API и вызова нашей новой функции

get_json_data

для сохранения полученных данных.

base_polo_url = 'https://poloniex.com/public?command=returnChartData&currencyPair={}&start={}&end={}&period={}'
start_date = datetime.strptime('2015-01-01', '%Y-%m-%d') 
end_date = datetime.now() 
pediod = 86400 

def get_crypto_data(poloniex_pair):
    json_url = base_polo_url.format(poloniex_pair, start_date.timestamp(), end_date.timestamp(), pediod)
    data_df = get_json_data(json_url, poloniex_pair)
    data_df = data_df.set_index('date')
    return data_df

Эта функция на входе получает пару криптовалют например, «BTC_ETH» и вернет исторические данные по обменному курсу двух валют.

Шаг 3.2 — Загрузка данных из Poloniex

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

Мы загрузим данные об обмене для девяти популярных криптовалют —

Ethereum

,

Litecoin

,

Ripple

,

Ethereum Classic

,

Stellar

,

Dash

,

Siacoin

,

Monero

, and

NEM

.

altcoins = ['ETH','LTC','XRP','ETC','STR','DASH','SC','XMR','XEM']
altcoin_data = {}
for altcoin in altcoins:
    coinpair = 'BTC_{}'.format(altcoin)
    crypto_price_df = get_crypto_data(coinpair)
    altcoin_data[altcoin] = crypto_price_df

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

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

altcoin_data['ETH'].tail()
dateclosehighlowopenquoteVolumevolumeweightedAverage
2018-03-010.0797350.0829110.0792320.08272917981.7336931454.2061330.080871
2018-03-020.0775720.0797190.0770140.07971918482.9855541448.7327060.078382
2018-03-030.0745000.0776230.0743560.07756215058.8256461139.6403750.075679
2018-03-040.0751110.0776300.0743890.07450012258.662182933.4809510.076149
2018-03-050.0753730.0757000.0747230.07527710993.285936826.5766930.075189
Шаг 3.3 — Конвертирование цен в USD.

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

for altcoin in altcoin_data.keys():
    altcoin_data[altcoin]['price_usd'] =  altcoin_data[altcoin]['weightedAverage'] * btc_usd_datasets['avg_btc_price_usd']

Этим мы создали новый столбец в каждом наборе данных альтернативных криптовалют с ценами в USD.

Затем мы можем повторно использовать нашу функцию

merge_dfs_on_column

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

combined_df = merge_dfs_on_column(list(altcoin_data.values()), list(altcoin_data.keys()), 'price_usd')

Теперь добавим в набор данных цены биткоина в качестве конечного столбца.

combined_df['BTC'] = btc_usd_datasets['avg_btc_price_usd']

В результате мы имеем набор данных, содержащий ежедневные цены в USD для десяти криптовалют, которые мы рассматриваем.

Используем нашу функцию

df_scatter

, чтобы отобразить все цены криптовалют на графике.

df_scatter(combined_df, 'Цены Криптовалют (USD)', seperate_y_axis=False, y_axis_label='(USD)', scale='log')

Этот график дает довольно солидную «общую картину» того, как обменные курсы каждой валюты менялись в течение последних нескольких лет.

В данном примере мы используем логарифмическую шкалу оси Y, чтобы сравнить все валюты на одном и том же участке. Вы можете попробовать различные значения параметров (например, scale = 'linear'), чтобы получить разные точки зрения на данные.

Шаг 3.4 — Вычисление корреляции криптовалют.

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

Мы можем проверить нашу корреляционную гипотезу, используя метод Pandas

corr ()

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

pct_change ()

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

Сначала мы вычислим корреляции для 2016 года.

combined_df_2016 = combined_df[combined_df.index.year == 2016]
combined_df_2016.pct_change().corr(method='pearson')

Результат:

DASHETCETHLTCSCSTRXEMXMRXRPBTC
DASH1.0000000.0039920.122695-0.0121940.0266020.0580830.0145710.1215370.088657-0.014040
ETC0.0039921.000000-0.181991-0.131079-0.008066-0.102654-0.080938-0.105898-0.054095-0.170538
ETH0.122695-0.1819911.000000-0.0646520.1696420.0350930.0432050.0872160.085630-0.006502
LTC-0.012194-0.131079-0.0646521.0000000.0122530.1135230.1606670.1294750.0537120.750174
SC0.026602-0.0080660.1696420.0122531.0000000.1432520.1061530.0479100.0210980.035116
STR0.058083-0.1026540.0350930.1135230.1432521.0000000.2251320.0279980.3201160.079075
XEM0.014571-0.0809380.0432050.1606670.1061530.2251321.0000000.0164380.1013260.227674
XMR0.121537-0.1058980.0872160.1294750.0479100.0279980.0164381.0000000.0276490.127520
XRP0.088657-0.0540950.0856300.0537120.0210980.3201160.1013260.0276491.0000000.044161
BTC-0.014040-0.170538-0.0065020.7501740.0351160.0790750.2276740.1275200.0441611.000000

Коэффициенты, близкие к 1 или -1, означают, что данные сильно коррелируют или обратно коррелируют соответственно, а коэффициенты, близкие к нулю, означают, что значения имеют тенденцию колебаться независимо друг от друга.

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

def correlation_heatmap(df, title, absolute_bounds=True):
    heatmap = go.Heatmap(
        z=df.corr(method='pearson').as_matrix(),
        x=df.columns,
        y=df.columns,
        colorbar=dict(title='Pearson Coefficient'),
    )
    
    layout = go.Layout(title=title)
    
    if absolute_bounds:
        heatmap['zmax'] = 1.0
        heatmap['zmin'] = -1.0
        
    fig = go.Figure(data=[heatmap], layout=layout)
    py.iplot(fig)
correlation_heatmap(combined_df_2016.pct_change(), "Корреляция криптовалют (2016)")

Здесь темно-красные значения представляют собой сильные корреляции, а синие значения представляют собой сильные обратные корреляции. Все остальные цвета представляют собой разную степень слабых/несуществующих корреляций.

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

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

combined_df_2017 = combined_df[combined_df.index.year == 2017]
combined_df_2017.pct_change().corr(method='pearson')

Результат:

DASHETCETHLTCSCSTRXEMXMRXRPBTC
DASH1.0000000.3875550.5069110.3401530.2914240.1830380.3259680.4984180.0911460.307095
ETC0.3875551.0000000.6014370.4820620.2984060.2103870.3218520.4473980.1147800.416562
ETH0.5069110.6014371.0000000.4376090.3730780.2593990.3992000.5546320.2123500.410771
LTC0.3401530.4820620.4376091.0000000.3391440.3075890.3790880.4372040.3239050.420645
SC0.2914240.2984060.3730780.3391441.0000000.4029660.3313500.3786440.2438720.325318
STR0.1830380.2103870.2593990.3075890.4029661.0000000.3395020.3274880.5098280.230957
XEM0.3259680.3218520.3992000.3790880.3313500.3395021.0000000.3360760.2681680.329431
XMR0.4984180.4473980.5546320.4372040.3786440.3274880.3360761.0000000.2266360.409183
XRP0.0911460.1147800.2123500.3239050.2438720.5098280.2681680.2266361.0000000.131469
BTC0.3070950.4165620.4107710.4206450.3253180.2309570.3294310.4091830.1314691.000000
correlation_heatmap(combined_df_2017.pct_change(), "Корреляция криптовалют (2017)")
combined_df_2018 = combined_df[combined_df.index.year == 2018]
combined_df_2018.pct_change().corr(method='pearson')
DASHETCETHLTCSCSTRXEMXMRXRPBTC
DASH1.0000000.7755610.8565490.8479470.7331680.7172400.7691350.9130440.7796510.901523
ETC0.7755611.0000000.8088200.6674340.5308400.5512070.6417470.6960600.6376740.694228
ETH0.8565490.8088201.0000000.7007080.6248530.6303800.7523030.8168790.6521380.787141
LTC0.8479470.6674340.7007081.0000000.6837060.5966140.5936160.7659040.6441550.831780
SC0.7331680.5308400.6248530.6837061.0000000.6152650.6951360.6260910.7194620.723976
STR0.7172400.5512070.6303800.5966140.6152651.0000000.7904200.6428100.8540570.669746
XEM0.7691350.6417470.7523030.5936160.6951360.7904201.0000000.7443250.8297370.734044
XMR0.9130440.6960600.8168790.7659040.6260910.6428100.7443251.0000000.6680160.888284
XRP0.7796510.6376740.6521380.6441550.7194620.8540570.8297370.6680161.0000000.712146
BTC0.9015230.6942280.7871410.8317800.7239760.6697460.7340440.8882840.7121461.000000
correlation_heatmap(combined_df_2018.pct_change(), "Корреляция криптовалют (2018)")

И вот мы видим то, о чем и предполагали — почти все криптовалюты стали более взаимосвязанными друг с другом по всем направлениям.

На этом будем считать, что введение в работу с данными в Anaconda успешно пройдено.



Лучшая Python рассылка




Разместим вашу рекламу

Пиши: mail@pythondigest.ru

Нашли опечатку?

Выделите фрагмент и отправьте нажатием Ctrl+Enter.

Система Orphus