数字货币量化系统之数据分析

通过上一博文数字货币行情数据获取,我们已经学会如何通过交易所提供的开放接口获取交易数据了,这一节我们将通过获取的数据进行更深层次的分析。

分析步骤

1、获取加密货币市场行情
2、可视化数据

  • 2.1 收盘价可视化
  • 2.2 日成交量可视化

3、金融数据分析

  • 3.1 价格相关分析
  • 3.2 日收益率分析
  • 3.3 累计日收益率分析

加密货币数据分析

运用所学的知识,对3个交易对市场行情进行分析。

  • BTC/USDT
  • ETH/USDT
  • BCH/USDT

Step 0: 引入相关模块/包

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

Step 1: 获取加密货币市场行情

import datetime
import cryptocoin_data_utils as cdu
btc_df = cdu.get_single_kline_data(symbol='btc_usdt', kline_type='1day')
eth_df = cdu.get_single_kline_data(symbol='eth_usdt', kline_type='1day')
bch_df = cdu.get_single_kline_data(symbol='bch_usdt', kline_type='1day')
btc_df.head()
datetime open high low close vol symbol
0 2017-10-10 16:00:00 1 4901 1 4901 19.26 BTC/USDT
1 2017-10-11 16:00:00 4901 4999 4790 4989 0.580096 BTC/USDT
2 2017-10-12 16:00:00 4989 5922 4989 5741.7 20.7398427 BTC/USDT
3 2017-10-13 16:00:00 5741.7 5849.95 5473.77 5849.95 19.25958 BTC/USDT
4 2017-10-14 16:00:00 5849.95 5849.95 5686.41 5848 8.65860682 BTC/USDT
eth_df.head()
datetime open high low close vol symbol
0 2017-10-10 16:00:00 1 310 1 300 260.826 ETH/USDT
1 2017-10-11 16:00:00 300 300 285 285 0.33326666 ETH/USDT
2 2017-10-12 16:00:00 285 304.8 285 304.8 2.39326666 ETH/USDT
3 2017-10-13 16:00:00 304.8 343.99 304.8 343.8 8.284 ETH/USDT
4 2017-10-14 16:00:00 343.8 348 331 331 25.58901316 ETH/USDT
bch_df.head()
datetime open high low close vol symbol
0 2018-11-18 16:00:00 245 254.9999 203.001 234.2346 9480.54967848 BCH/USDT
1 2018-11-19 16:00:00 234.2346 259.97 196.2657 255 15922.975 BCH/USDT
2 2018-11-20 16:00:00 255 257.0754 216.71 240 8035.08557488 BCH/USDT
3 2018-11-21 16:00:00 240 241.48 219.13 220.5 4822.2932 BCH/USDT
4 2018-11-22 16:00:00 220.5 223.4319 197.4958 209 5841.8491 BCH/USDT
btc_df.to_csv('./btc_usdt_data.csv', index=False)
eth_df.to_csv('./eth_usdt_data.csv', index=False)
bch_df.to_csv('./bch_usdt_data.csv', index=False)

Step 2: 可视化数据

2.1 收盘价可视化

btc_df = pd.read_csv('./btc_usdt_data.csv', index_col='datetime', parse_dates=True)
eth_df = pd.read_csv('./eth_usdt_data.csv', index_col='datetime', parse_dates=True)
bch_df = pd.read_csv('./bch_usdt_data.csv', index_col='datetime', parse_dates=True)
# 检查是否有重复的index
btc_df[btc_df.index.duplicated()]
btc_df.loc['2018-02-03']
open high low close vol symbol
datetime
2018-02-03 16:00:00 9188.9281 9470.6318 8450.0 8837.6286 46148.596221 BTC/USDT
if btc_df.index.duplicated().any():
    print('BTC索引去重')
    btc_df = btc_df[~btc_df.index.duplicated()]

if eth_df.index.duplicated().any():
    print('ETH索引去重')
    eth_df = eth_df.loc[~eth_df.index.duplicated()]

if bch_df.index.duplicated().any():
    print('BCH索引去重')
    bch_df = bch_df.loc[~bch_df.index.duplicated()]
btc_df['close'].plot(label='BTH/USDT', figsize=(16,8), title='Close Price')
eth_df['close'].plot(label='ETH/USDT')
bch_df['close'].plot(label='BCH/USDT')
plt.legend()

file

2.2 日成交量可视化

btc_df['vol'].plot(label='BTC/USDT', figsize=(16, 8), title='Volume Traded')
eth_df['vol'].plot(label='ETH/USDT')
bch_df['vol'].plot(label='BCH/USDT')
plt.legend()

file

eth_df['vol'].idxmax()
Timestamp('2019-04-03 16:00:00')

Q: 2018年2月5日,2018年9月5日,2018年9月13日, 2019年4月3日 这四天以太坊发生了什么?

A: 2018年2月5日,Truebit将Dogecoin带入以太坊区块链。http://www.o-o-o.link/article/6034.html

bch_df['vol'].idxmax()
Timestamp('2019-07-16 16:00:00')

Step 3: 金融数据分析

3.1 价格相关性分析

from pandas.plotting import scatter_matrix
coins_index = bch_df.index
coins_df = pd.DataFrame(columns=['BTC/USDT', 'ETH/USDT', 'BCH/USDT'], index=bch_df.index)
coins_df.head()
BTC/USDT ETH/USDT BCH/USDT
datetime
2018-11-18 16:00:00 NaN NaN NaN
2018-11-19 16:00:00 NaN NaN NaN
2018-11-20 16:00:00 NaN NaN NaN
2018-11-21 16:00:00 NaN NaN NaN
2018-11-22 16:00:00 NaN NaN NaN
coins_df['BTC/USDT'] = btc_df['close']
coins_df['ETH/USDT'] = eth_df['close']
coins_df['BCH/USDT'] = bch_df['close']
coins_df.head()
BTC/USDT ETH/USDT BCH/USDT
datetime
2018-11-18 16:00:00 5217.2507 157.3733 234.2346
2018-11-19 16:00:00 4947.8746 149.3194 255.0000
2018-11-20 16:00:00 4631.8422 137.7829 240.0000
2018-11-21 16:00:00 4561.4075 133.2573 220.5000
2018-11-22 16:00:00 4406.7303 124.1879 209.0000
scatter_matrix(coins_df, figsize=(10, 10), hist_kwds={'bins': 50});
# 说明该图可以按照对角线看,第一行第一列表示BTC自己对比,第一行第二列表示BTC/ETH 对比,第一行第三列表示BTC/BCH 对比

file

import seaborn as sns

sns.pairplot(coins_df)
# 从下图可以看出以太坊和BCH相关性比较强

file

coins_df.corr()
BTC/USDT ETH/USDT BCH/USDT
BTC/USDT 1.000000 0.814809 0.800630
ETH/USDT 0.814809 1.000000 0.937294
BCH/USDT 0.800630 0.937294 1.000000

结论:

根据corr()得出的结果可以看出 ETH和BCH有很强的正相关性,我们可以根据这个相关性来对 ETH、BCH做出买卖,如果ETH一段时间内飞涨,
而BCH没有涨动,我们可以买入BCH,同理如果有一个暴跌,另外一个还没有跌时,我们可以卖出。

3.2 日收益率分析

日收益率计算公式:

$r_t = \frac{pt}{p{t-1}} -1$

  • $p_t$: $t$ 时刻的价格

  • $p_{t-1}$: $t-1$ 时刻的价格

  • 方法1:用shift()操作

btc_df['returns'] = (btc_df['close'] / btc_df['close'].shift(1) ) - 1
btc_df.head()
open high low close vol symbol returns
datetime
2017-10-10 16:00:00 1.00 4901.00 1.00 4901.00 19.260000 BTC/USDT NaN
2017-10-11 16:00:00 4901.00 4999.00 4790.00 4989.00 0.580096 BTC/USDT 0.017956
2017-10-12 16:00:00 4989.00 5922.00 4989.00 5741.70 20.739843 BTC/USDT 0.150872
2017-10-13 16:00:00 5741.70 5849.95 5473.77 5849.95 19.259580 BTC/USDT 0.018853
2017-10-14 16:00:00 5849.95 5849.95 5686.41 5848.00 8.658607 BTC/USDT -0.000333
btc_df['returns'] = btc_df['close'].pct_change(1)
btc_df.head()
open high low close vol symbol returns
datetime
2017-10-10 16:00:00 1.00 4901.00 1.00 4901.00 19.260000 BTC/USDT NaN
2017-10-11 16:00:00 4901.00 4999.00 4790.00 4989.00 0.580096 BTC/USDT 0.017956
2017-10-12 16:00:00 4989.00 5922.00 4989.00 5741.70 20.739843 BTC/USDT 0.150872
2017-10-13 16:00:00 5741.70 5849.95 5473.77 5849.95 19.259580 BTC/USDT 0.018853
2017-10-14 16:00:00 5849.95 5849.95 5686.41 5848.00 8.658607 BTC/USDT -0.000333
eth_df['returns'] = eth_df['close'].pct_change(1)
bch_df['returns'] = bch_df['close'].pct_change(1)
eth_df.head()
open high low close vol symbol returns
datetime
2017-10-10 16:00:00 1.0 310.00 1.0 300.0 260.826000 ETH/USDT NaN
2017-10-11 16:00:00 300.0 300.00 285.0 285.0 0.333267 ETH/USDT -0.050000
2017-10-12 16:00:00 285.0 304.80 285.0 304.8 2.393267 ETH/USDT 0.069474
2017-10-13 16:00:00 304.8 343.99 304.8 343.8 8.284000 ETH/USDT 0.127953
2017-10-14 16:00:00 343.8 348.00 331.0 331.0 25.589013 ETH/USDT -0.037231
bch_df.head()
open high low close vol symbol returns
datetime
2018-11-18 16:00:00 245.0000 254.9999 203.0010 234.2346 9480.549678 BCH/USDT NaN
2018-11-19 16:00:00 234.2346 259.9700 196.2657 255.0000 15922.975000 BCH/USDT 0.088652
2018-11-20 16:00:00 255.0000 257.0754 216.7100 240.0000 8035.085575 BCH/USDT -0.058824
2018-11-21 16:00:00 240.0000 241.4800 219.1300 220.5000 4822.293200 BCH/USDT -0.081250
2018-11-22 16:00:00 220.5000 223.4319 197.4958 209.0000 5841.849100 BCH/USDT -0.052154
  • 使用直方图查看日收益率的稳定性
btc_df['returns'].hist(bins=100)

file

eth_df['returns'].hist(bins=100)

file

bch_df['returns'].hist(bins=100)

file

btc_df['returns'].hist(bins=100, label='BTC/USDT', figsize=(10, 8), alpha=0.5)
eth_df['returns'].hist(bins=100, label='ETH/USDT', alpha=0.5)
bch_df['returns'].hist(bins=100, label='BCH/USDT', alpha=0.5)
plt.legend()

file

  • 使用盒子图比较不同加密货币的日收益率
returns_df = pd.concat([btc_df['returns'], eth_df['returns'], bch_df['returns']], axis=1)
returns_df.columns = ['BTC Returns', 'ETH Returns', 'BCH Returns']
returns_df.head()
BTC Returns ETH Returns BCH Returns
datetime
2017-10-10 16:00:00 NaN NaN NaN
2017-10-11 16:00:00 0.017956 -0.050000 NaN
2017-10-12 16:00:00 0.150872 0.069474 NaN
2017-10-13 16:00:00 0.018853 0.127953 NaN
2017-10-14 16:00:00 -0.000333 -0.037231 NaN
plt.figure(figsize=(10, 8))
sns.boxplot(data=returns_df)

file


3.3 累计日收益率

以下是某个加密货币的价格:

日期                        价格
01/01/2018                   10
01/02/2018                   15
01/03/2018                   20
01/04/2018                   25

日收益 : $\frac{pt}{p{t-1}}$,表示和前一天相比的获利/损失。大于1,表示获利;小于1,表示损失。

日收益率 : $\frac{pt}{p{t-1}} - 1$,表示和前一天相比的获利/损失的百分比。大于0,表示获利;小于0,表示损失。

日期                         日收益                        日收益率%
01/01/2018                 10/10 =  1                           -   
01/02/2018                 15/10 =  3/2                       50%
01/03/2018                 20/15 =  4/3                       33%
01/04/2018                 25/20 =  5/4                       20%

累计收益:

日期                           累计收益                      累计收益率%
01/01/2018                  10/10 =  1                         -  
01/02/2018                  15/10 =  3/2                       50 %
01/03/2018                  20/10 =  2                         100 %
01/04/2018                  25/10 =  5/2                       150 %

累计日收益 : $\frac{p_t}{p_1}$,表示和第一天相比的获利/损失。大于1,表示获利;小于1,表示损失。

累计日收益率 : $\frac{p_t}{p_1} - 1$,表示和第一天相比的获利/损失的百分比。大于0,表示获利;小于0,表示损失。

btc_df.head()
open high low close vol symbol returns
datetime
2017-10-10 16:00:00 1.00 4901.00 1.00 4901.00 19.260000 BTC/USDT NaN
2017-10-11 16:00:00 4901.00 4999.00 4790.00 4989.00 0.580096 BTC/USDT 0.017956
2017-10-12 16:00:00 4989.00 5922.00 4989.00 5741.70 20.739843 BTC/USDT 0.150872
2017-10-13 16:00:00 5741.70 5849.95 5473.77 5849.95 19.259580 BTC/USDT 0.018853
2017-10-14 16:00:00 5849.95 5849.95 5686.41 5848.00 8.658607 BTC/USDT -0.000333
btc_df['Cumulative Returns'] = btc_df['close'] / btc_df.iloc[0]['close'] - 1
btc_df.head()
open high low close vol symbol returns Cumulative Returns
datetime
2017-10-10 16:00:00 1.00 4901.00 1.00 4901.00 19.260000 BTC/USDT NaN 0.000000
2017-10-11 16:00:00 4901.00 4999.00 4790.00 4989.00 0.580096 BTC/USDT 0.017956 0.017956
2017-10-12 16:00:00 4989.00 5922.00 4989.00 5741.70 20.739843 BTC/USDT 0.150872 0.171536
2017-10-13 16:00:00 5741.70 5849.95 5473.77 5849.95 19.259580 BTC/USDT 0.018853 0.193624
2017-10-14 16:00:00 5849.95 5849.95 5686.41 5848.00 8.658607 BTC/USDT -0.000333 0.193226
eth_df['Cumulative Returns'] = eth_df['close'] / eth_df.iloc[0]['close'] - 1
bch_df['Cumulative Returns'] = bch_df['close'] / bch_df.iloc[0]['close'] - 1
btc_df['Cumulative Returns'].plot(label='BTC', figsize=(22, 10), title='Cumulative Returns')
eth_df['Cumulative Returns'].plot(label='ETH')
bch_df['Cumulative Returns'].plot(label='BCH')
plt.legend()

file

辅助函数

cryptocoin_data_utils.py

# -*- coding:utf-8 -*-

"""
@author: Corwien
@file: cryptocoin_data_utils.py
@time: 19/12/1 12:47
"""
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
import pandas as pd
from datetime import datetime

# ----------------- 代理相关 Begin -----------------
# 这里的代理IP是从showdocsocks软件「复制终端代理命令」找到的
proxies = {'https': "http://127.0.0.1:1087", 'http': "http://127.0.0.1:1087"}
# ----------------- 代理相关 End -----------------

# HTTPS certificate warning(去掉https警告提示)
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

def get_single_ticker_data(symbol):
    '''
    单个交易对的ticker数据获取
    '''

    ticker_url = 'https://www.okex.com/api/v1/ticker.do?symbol={}'.format(symbol)

    # 异常处理,api请求超时等问题,设置超时时间,防止程序阻塞
    try:
        res_obj = requests.get(ticker_url, timeout=5, verify=False, proxies=proxies)  # 获取到的是一个对象
    except Exception as e:
        print('错误:', e)
        return None

    ticker_df = None

    json_obj = res_obj.json()

    if res_obj.status_code == 200:
        if 'error_code' in res_obj:
            print('错误码:{}'.format(json_obj['error_code']))

        else:

            raw_df = pd.DataFrame(json_obj) # json -> df

            ticker_df = pd.DataFrame(index=[0], columns=['datetime', 'symbol'] + raw_df.index.tolist())
            ticker_df['datetime'] = pd.to_datetime(datetime.utcnow())
            ticker_df['symbol'] = symbol.replace('_', '/').upper()
            ticker_df[raw_df.index.tolist()] = raw_df['ticker'].values
    else:
        print('状态码:{}'.format(res_obj.status_code))

    return ticker_df

def get_tickers_data(symbols):
    """
    多个交易对的数据获取和处理
    :param symbols:
    :return:
    """
    tickers_df = pd.DataFrame()
    for symbol in symbols:
        ticker_df = get_single_ticker_data(symbol)
        if ticker_df is None:
            continue
        tickers_df = tickers_df.append(ticker_df)

    return tickers_df

def get_single_kline_data(symbol, kline_type='1min', size=2000):
    '''
    单个交易对的K线数据获取
    size 最大2000
    '''

    kline_url = 'https://www.okex.com/api/v1/kline.do?symbol={}&type={}&size={}'.format(symbol, kline_type, size)

    # 异常处理,api请求超时等问题,设置超时时间,防止程序阻塞
    try:
        res_obj = requests.get(kline_url, timeout=5, verify=False, proxies=proxies)  # 获取到的是一个对象
    except Exception as e:
        print('错误:', e)
        return None

    kline_df = None

    json_obj = res_obj.json()

    if res_obj.status_code == 200:
        if 'error_code' in res_obj:
            print('错误码:{}'.format(json_obj['error_code']))
        else:
            raw_df = pd.DataFrame(json_obj) # json ->
            kline_df = raw_df.copy()
            kline_df.columns = ['datetime', 'open', 'high', 'low', 'close', 'vol']
            kline_df['datetime'] = pd.to_datetime(kline_df['datetime'], unit='ms')
            kline_df['symbol'] = symbol.replace('_', '/').upper()
    else:
        print('状态码:{}'.format(res_obj.status_code))

    return kline_df

def get_klines_data(symbols, kline_type='1min', size=2000):
    """
    多个交易对的K线数据获取和处理
    :param symbols:
    :return:
    """
    klines_df = pd.DataFrame()
    for symbol in symbols:
        kline_df = get_single_kline_data(symbol, kline_type, size)
        if kline_df is None:
            continue
        klines_df = klines_df.append(kline_df)

    return klines_df

为者常成,行者常至