数据君的量化技术-第一篇来啦童鞋

有感兴趣量化技术,特别是大数据、人工智能在量化中的应用的童鞋们可以关注我的公众号:

馨视野(datahomex):

 

最近朋友圈铺天盖地全是数币,之前都是谈币色变,现在是不谈个币就表明你是非人类。

数据君好好研究了一下币圈交易,发现币圈量化大有可为啊(诡异一笑),币圈真是纯数字,天空中飘的都是一排排数字。

今天开始数据君就带大家开启量化技术的大门,本系列文章会介绍币圈交易数据的获取,量化策略的开发、评估,以及如何在量化交易中应用人工智能技术等等。

本篇主要介绍:

1、如何获取自己开发程序需要的交易平台的APP KEY

2、实时获取交易平台K线数据

3、如何通过平台接口实现程序化的下单操作

 

一、APP KEY 获取

        数据君以火币平台举例,其他平台操作都大同小异。

第一步、注册平台账户(直接省略,太简单直白了)

        注册地址:https://www.huobi.li/zh-cn/register/ ,支持手机或邮箱注册,量化君就直接手机注册了

第二步、创建API KEY

        用上面注册的账号登陆成功后,点击右上角个人头像,选择API管理菜单(如图),进入API创建页面

图片

 

    在创建API页面需要关注的是权限设置和绑定IP端操作(如下图):

  • 安全起见,权限只选读取和交易,限制程序自动提币的功能

  • 量化君只是测试用,IP段只设置本机地址,正式上线的程序一般都会部署在云上(比如阿里云),这里可以填写阿里云的对外地址

图片

 

        点击创建按钮后,会弹出消息框,上面的Access key 和 Secret Key 一定要记住,后续程序化交易这个就是你账号的凭证,当然数据君这里也提醒一下:

        千万不能泄露这2个key!

        千万不能泄露这2个key!

        千万不能泄露这2个key!

图片

        到这里万里长征第一步完成了

二、K线数据获取

        完成注册账号和APP key获取后,就可以通过平台提供的API 接口获取实时历史交易数据,也可以通过接口实现下单交易等操作,数据君个人认为平台提供的接口还是很详细规范,地址如下:

        https://huobiapi.github.io/docs/spot/v1/cn/#185368440e

        今天数据君先介绍历史K线数据的获取和保存,数据君一直习惯用python,所以这次也是使用python调用平台的 API接口,大家要有一点python基础(当然其他语言操作基本一样)

        先看下平台提供的接口文档里的说明:

图片

        火币提供的API接口都是Restful接口,对于有点开发经验的童鞋使用起来都非常友好,这是用python封装的通用的接口调用函数,如果是用python的童鞋可以直接拿去用,当然key需要改成自己的,代码如下:

 

# -*- coding: utf-8 -*-
import base64import datetimeimport hashlibimport hmacimport jsonimport urllibimport urllib.parseimport urllib.requestimport requests# 此处填写APIKEYACCESS_KEY = "***********" //填写自己的keySECRET_KEY = "***********" //填写自己的key# API 请求地址TRADE_URL = "https://api.huobipro.com"# 首次运行可通过get_accounts()获取acct_id,然后直接赋值,减少重复获取。ACCOUNT_ID = None#'Timestamp': '2017-06-02T06:13:49'def http_get_request(url, params, add_to_headers=None):    headers = {        "Content-type": "application/x-www-form-urlencoded",        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36',    }    if add_to_headers:        headers.update(add_to_headers)    postdata = urllib.parse.urlencode(params)    response = requests.get(url, postdata, headers=headers, timeout=5)     try:                if response.status_code == 200:            return response.json()        else:            return    except BaseException as e:        print("httpGet failed, detail is:%s,%s" %(response.text,e))        returndef http_post_request(url, params, add_to_headers=None):    headers = {        "Accept": "application/json",        'Content-Type': 'application/json'    }    if add_to_headers:        headers.update(add_to_headers)    postdata = json.dumps(params)    response = requests.post(url, postdata, headers=headers, timeout=10)    try:                if response.status_code == 200:            return response.json()        else:            return    except BaseException as e:        print("httpPost failed, detail is:%s,%s" %(response.text,e))        returndef api_key_get(params, request_path):    method = 'GET'    timestamp = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S')    params.update({'AccessKeyId': ACCESS_KEY,                   'SignatureMethod': 'HmacSHA256',                   'SignatureVersion': '2',                   'Timestamp': timestamp})    host_url = TRADE_URL    host_name = urllib.parse.urlparse(host_url).hostname    host_name = host_name.lower()    params['Signature'] = createSign(params, method, host_name, request_path, SECRET_KEY)    url = host_url + request_path    return http_get_request(url, params)def api_key_post(params, request_path):    method = 'POST'    timestamp = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S')    params_to_sign = {'AccessKeyId': ACCESS_KEY,                      'SignatureMethod': 'HmacSHA256',                      'SignatureVersion': '2',                      'Timestamp': timestamp}    host_url = TRADE_URL    host_name = urllib.parse.urlparse(host_url).hostname    host_name = host_name.lower()    params_to_sign['Signature'] = createSign(params_to_sign, method, host_name, request_path, SECRET_KEY)    url = host_url + request_path + '?' + urllib.parse.urlencode(params_to_sign)    return http_post_request(url, params)    def createSign(pParams, method, host_url, request_path, secret_key):    sorted_params = sorted(pParams.items(), key=lambda d: d[0], reverse=False)    encode_params = urllib.parse.urlencode(sorted_params)    payload = [method, host_url, request_path, encode_params]    payload = '\n'.join(payload)    payload = payload.encode(encoding='UTF8')    secret_key = secret_key.encode(encoding='UTF8')    digest = hmac.new(secret_key, payload, digestmod=hashlib.sha256).digest()    signature = base64.b64encode(digest)    signature = signature.decode()    return signature        
调用/market/history/kline接口,获取历史数据,代码如下:
# 获取KLinedef get_kline(symbol, period, size=150):    """    :param symbol    :param period: 可选值:{1min, 5min, 15min, 30min, 60min, 1day, 1mon, 1week, 1year }    :param size: 可选值:[1,2000]    :return:    """    params = {'symbol': symbol,              'period': period,              'size': size}    url = MARKET_URL + '/market/history/kline'    return http_get_request(url, params)

  数据君以获取dogeusdt交易对、5分钟级别的K线数据为例,单次最多可以获取2000条记录:

jsonData = get_kline(symbol='dogeusdt',period='5min',size=2000)df=parse_json(jsonData.get('data'))

        火币restful接口不能按指定时间段获取,如需要按指定时间段获取,需要用websocket API接口,数据君考虑后面测试评估量化策略,所以获取的数据会做持久化保留到本地数据库,详细保留的数据如下图:


图片

        看到这里的童鞋,离长征成功不远了~~~

三、实现程序化下单

        激动人心的时刻来了,数据君来实现一次程序化的下单,平台的下单接口如下图,

        下单接口可以进行买入和卖出的操作,参数众多,说明如下:

参数名称是否必需默认值描述
account-idTRUENA账户  ID,取值参考 GET /v1/account/accounts。现货交易使用 ‘spot’ 账户的 account-id;逐仓杠杆交易,请使用  ‘margin’ 账户的 account-id;全仓杠杆交易,请使用 ‘super-margin’ 账户的 account-id
symbolTRUENA交易对,即btcusdt,  ethbtc...(取值参考GET /v1/common/symbols)
typeTRUENA订单类型,包括buy-market,  sell-market, buy-limit, sell-limit, buy-ioc, sell-ioc, buy-limit-maker,  sell-limit-maker(说明见下文), buy-stop-limit, sell-stop-limit, buy-limit-fok,  sell-limit-fok, buy-stop-limit-fok, sell-stop-limit-fok
amountTRUENA订单交易量(市价买单为订单交易额)
priceFALSENA订单价格(对市价单无效)
sourceFALSEspot-api现货交易填写“spot-api”,逐仓杠杆交易填写“margin-api”,全仓杠杆交易填写“super-margin-api”,  C2C杠杆交易填写"c2c-margin-api"
client-order-idFALSENA用户自编订单号(最大长度64个字符,须在24小时内保持唯一性)
stop-priceFALSENA止盈止损订单触发价格
operatorFALSENA止盈止损订单触发价运算符  gte – greater than and equal (>=), lte – less than and equal (<=)

        下单接口调用代码如下:

 

//获取账户信息的接口//通常在程序启动时候初始化一次就行def get_accounts():    """    :return:     """    path = "/v1/account/accounts"    params = {}    return api_key_get(params, path)def send_order(amount, source, symbol, _type, price=0):    """    :param amount:     :param source: 如果使用借贷资产交易,请在下单接口,请求参数source中填写'margin-api' 现货交易填写“spot-api”,逐仓杠杆交易填写“margin-api”,全仓杠杆交易填写“super-margin-api”, C2C杠杆交易填写"c2c-margin-api"    :param symbol:     :param _type: 可选值 {buy-market:市价买, sell-market:市价卖, buy-limit:限价买, sell-limit:限价卖}    :param price:     :return:     """    try:        accounts = get_accounts()        acct_id = accounts['data'][0]['id']    except BaseException as e:        print ('get acct_id error.%s' % e)        acct_id = ACCOUNT_ID    params = {"account-id": acct_id,              "amount": amount,              "symbol": symbol,              "type": _type,              "source": source}    if price:        params["price"] = price    url = '/v1/order/orders/place'    return api_key_post(params, url)

        现在数据君就通过程序,以市价的方式买入一笔doge测试看看:

print(send_order(amount='10',source='spot-api',symbol='dogeusdt',_type='buy-market'))

 出师不利,报错信息看IP地址不合法,我们要把IP地址加到前面在创建API Key页面中的绑定IP一栏里面!图片

 加入IP地址后,再买一次发现买入成功了,撒花一下(如下图)

图片

 登陆平台,在订单页面可以看到确实买入成功,如下图:

图片

 接着量化君通过程序实现把刚才买入的doge以市价直接卖出,结果如下:

图片

 登陆平台订单页面,再次确认一下:

为啥有3笔呢,刚数据君程序里忘了把买入改成卖出,所以又多买了一笔,看看手续费,扎心了,所以程序化交易得谨慎再谨慎再谨慎,乌龙指都这么来的!!!

 

总结

        今天数据君终于在量化的路上迈出了坚实的一步,成功实现程序化买了一次和卖了一次!

        当然这和真正的量化差的很远,准确的说根本不是量化,不过万事开头难,这也算是有了好的开头,链路都走通了,二次撒花庆祝!!

        后面数据君会为童鞋们带来真正的量化技术,仿佛看到了不远的将来一堆金币在向数据君招手(诡异二笑)!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值