数字量化系统之数字货币行情数据获取及分析

加密货币行情数据获取及分析。

一、获取数据

交易对的ticker数据获取

  • 单个交易对的ticker数据获取及处理
  • 多个交易对的ticker数据获取及处理

交易对的K线数据数据获取

  • 单个交易对的K线数据获取及处理
  • 多个交易对的K线数据获取及处理

工具模块

  • 1、request
  • 2、Pandas
  • 3、datetime

我们这里以okex交易所提供的API接口为例,获取这两组数据,注意,这里因为GFW的关系无法直接访问,所以,需要使用代理科学上网。

二、代码实战

编辑器

我们使用 Pycharm 编辑器,Conda作为python的运行环境。

file

代码

main.py

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

"""
@author: Corwien
@file: main.py
@time: 19/11/30 20:18
"""

import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
import pandas as pd
from datetime import datetime

# 如果数据多,会自动隐藏,这里设置不自动隐藏
pd.set_option('expand_frame_repr', False)

# ----------------- 代理相关 Begin -----------------
# 使用代理
# proxies = {'https': "socks5://root:W123456@167.179.117.142:10404"}
#proxies = {'https': "http://root:W123456@167.179.117.142:10404"}

# 这里的代理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=20):
    '''
    单个交易对的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=5):
    """
    多个交易对的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

def main():
    """
    主函数
    """

    # 1.获取交易对的ticker信息
    # 1.1获取单个交易对
    #symbol = 'btc_usdt'
    #ticker_df = get_single_ticker_data(symbol)
    #print(ticker_df)

    # 1.2 获取多个交易对的ticker数据
    #symbols = ['btc_usdt', 'eth_usdt', 'eos_usdt']
    #tickers_df = get_tickers_data(symbols)
    #print(tickers_df)

    # 2.获取交易对的K线信息
    # 2.1 获取单个交易对K线
    #symbol = 'btc_usdt'
    #kline_df = get_single_kline_data(symbol, kline_type='1hour')
    #print(kline_df)

    # 2.2 多个交易对的K线数据获取及处理
    symbols = ['btc_usdt', 'eth_usdt', 'eos_usdt', 'bch_usdt']
    klines_df = get_klines_data(symbols)
    print(klines_df)

if __name__ == '__main__':
    main()

运行上边的代码,打印多个交易对的K线数据:

/Users/kaiyiwang/anaconda3/bin/python /Users/kaiyiwang/Code/quant/bitLearn/main.py
             datetime    open    high     low   close          vol    symbol
0 2019-12-01 04:36:00  7283.9  7286.2  7283.8  7286.2   1.22558669  BTC/USDT
1 2019-12-01 04:37:00  7286.2  7290.6  7286.2  7288.5  16.87775011  BTC/USDT
2 2019-12-01 04:38:00  7289.7  7305.4  7289.7    7294  72.68640118  BTC/USDT
3 2019-12-01 04:39:00  7292.6  7322.9  7292.6  7316.1    188.53823  BTC/USDT
4 2019-12-01 04:40:00  7314.8  7314.8  7302.3  7308.9   5.07364692  BTC/USDT
0 2019-12-01 04:36:00  147.13  147.24  147.12  147.24   139.439291  ETH/USDT
1 2019-12-01 04:37:00  147.24  147.27  147.24  147.26    75.129606  ETH/USDT
2 2019-12-01 04:38:00  147.26  147.53  147.26  147.37   783.329827  ETH/USDT
3 2019-12-01 04:39:00  147.36  147.78  147.36  147.63   361.270089  ETH/USDT
4 2019-12-01 04:40:00  147.64  147.64  147.44  147.55    91.603368  ETH/USDT
0 2019-12-01 04:36:00   2.686   2.687   2.686   2.687     426.5304  EOS/USDT
1 2019-12-01 04:37:00   2.687   2.688   2.687   2.687     773.2268  EOS/USDT
2 2019-12-01 04:38:00   2.687   2.693   2.687    2.69   26926.8609  EOS/USDT
3 2019-12-01 04:39:00    2.69   2.692    2.69   2.692    2153.2226  EOS/USDT
4 2019-12-01 04:40:00   2.692   2.692    2.69   2.692    2329.0641  EOS/USDT
0 2019-12-01 04:36:00  211.36  211.51  211.36  211.51       5.4225  BCH/USDT
1 2019-12-01 04:37:00  211.51  211.51  211.35  211.45      40.0456  BCH/USDT
2 2019-12-01 04:38:00  211.52  211.79  211.46  211.54      68.4088  BCH/USDT
3 2019-12-01 04:39:00  211.57  211.92  211.57   211.9      20.8741  BCH/USDT
4 2019-12-01 04:40:00  211.83  211.83  211.63  211.74       9.0196  BCH/USDT

Process finished with exit code 0

我们已经可以成功获取Okex提供的行情数据了,但是可以看到上边的代码写的不够好,不够清爽简洁,对于通用的代码,我们可以直接将其抽出来放到工具文件中,然后在 main.py 中直接引入即可。

代码优化

main.py 中获取数据的方法都抽到帮助文件cyptocoin_data_utils.py:

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

"""
@author: Corwien
@file: cyptocoin_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 -----------------
# 使用代理
# proxies = {'https': "socks5://root:W123456@167.179.117.142:10404"}
#proxies = {'https': "http://root:W123456@167.179.117.142:10404"}

# 这里的代理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=20):
    '''
    单个交易对的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=5):
    """
    多个交易对的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

main.py 中引入上边的文件(包):

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

"""
@author: Corwien
@file: main.py
@time: 19/11/30 20:18
"""

import pandas as pd
import cyptocoin_data_utils as cdu

# 如果数据多,会自动隐藏,这里设置不自动隐藏
pd.set_option('expand_frame_repr', False)

def main():
    """
    主函数
    """

    # 1.获取交易对的ticker信息
    # 1.1获取单个交易对
    #symbol = 'btc_usdt'
    #ticker_df = cdu.get_single_ticker_data(symbol)
    #print(ticker_df)

    # 1.2 获取多个交易对的ticker数据
    #symbols = ['btc_usdt', 'eth_usdt', 'eos_usdt']
    #tickers_df = cdu.get_tickers_data(symbols)
    #print(tickers_df)

    # 2.获取交易对的K线信息
    # 2.1 获取单个交易对K线
    #symbol = 'btc_usdt'
    #kline_df = cdu.get_single_kline_data(symbol, kline_type='1hour')
    #print(kline_df)

    # 2.2 多个交易对的K线数据获取及处理
    symbols = ['btc_usdt', 'eth_usdt', 'eos_usdt', 'bch_usdt']
    klines_df = cdu.get_klines_data(symbols)

    # 保存数据到本地
    klines_df.to_csv('./cyptocoin_sample.csv', index=False)  # index=False 去掉索引
    print(klines_df)

if __name__ == '__main__':
    main()

通过优化后,我们的项目是不是很简洁清晰很多。

保存数据到本地

    # 保存数据到本地
    klines_df.to_csv('./cyptocoin_sample.csv', index=False)  # index=False 去掉索引

为者常成,行者常至