hikyuu2/hikyuu/data_driver/jqdata_data_driver.py

278 lines
8.9 KiB
Python
Raw Normal View History

#!/usr/bin/python
# -*- coding: utf8 -*-
# cp936
#
# The MIT License (MIT)
#
# Copyright (c) 2010-2019 weituo2002
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
####################################################################
#
# 使用 jqdata 作为K线数据驱动可自行实现自己的K线数据驱动
2020-06-25 15:59:37 +08:00
#
# 感谢网友哥本哈斯根贡献
#
#####################################################################
2020-06-25 15:59:37 +08:00
from ..cpp.core import KDataDriver, DataDriverFactory
2020-10-02 17:31:33 +08:00
from hikyuu import KRecord, Query, Datetime, Parameter, KRecordList
from jqdatasdk import *
from datetime import *
class jqdataKDataDriver(KDataDriver):
def __init__(self):
super(jqdataKDataDriver, self).__init__('jqdata')
2020-06-25 15:59:37 +08:00
2021-01-20 23:23:01 +08:00
def clone(self):
return jqdataKDataDriver()
def _init(self):
"""【重载接口】(可选)初始化子类私有变量"""
2020-06-25 15:59:37 +08:00
self._max = {
Query.DAY: 10,
Query.WEEK: 2,
Query.MONTH: 1,
Query.QUARTER: 1,
#Query.HALFYEAR:1,
Query.YEAR: 1,
Query.MIN: 25,
Query.MIN5: 25,
Query.MIN15: 25,
Query.MIN30: 25,
Query.MIN60: 25
}
2021-02-06 14:45:52 +08:00
return True
2020-06-25 15:59:37 +08:00
2020-10-02 17:31:33 +08:00
def isIndexFirst(self):
return False
2021-02-06 14:45:52 +08:00
def canParallelLoad(self):
return False
2020-10-12 01:14:16 +08:00
def getKRecordList(self, market, code, query): # ktype, start_ix, end_ix, out_buffer):
"""
重载接口必须按指定的位置[start_ix, end_ix)读取K线数据至out_buffer
:param str market: 市场标识
:param str code: 证券代码
2020-06-30 23:27:23 +08:00
:param Query.KType ktype: K线类型
:param int start_ix: 起始位置
:param int end_ix: 结束位置
:param KRecordListPtr out_buffer: 传入的数据缓存读取数据后使用
out_buffer.append(krecord) 加入数据
"""
2021-02-06 14:45:52 +08:00
if query.query_type == Query.DATE:
2020-10-12 01:14:16 +08:00
print("未实现按日期查询")
return KRecordList()
2020-10-02 17:31:33 +08:00
start_ix = query.start
end_ix = query.end
2020-06-25 15:59:37 +08:00
if start_ix >= end_ix or start_ix < 0 or end_ix < 0:
2020-10-02 17:31:33 +08:00
return KRecordList()
2020-10-02 17:31:33 +08:00
data = self._get_bars(market, code, query.ktype)
2020-06-25 15:59:37 +08:00
if len(data) < start_ix:
2020-10-02 17:31:33 +08:00
return KRecordList()
2020-06-25 15:59:37 +08:00
2020-10-02 17:31:33 +08:00
result = KRecordList()
total = end_ix if end_ix < len(data) else len(data)
for i in range(start_ix, total):
record = KRecord()
record.datetime = Datetime(data.index[i])
2020-07-04 23:54:02 +08:00
record.open = data['open'][i]
record.high = data['high'][i]
record.low = data['low'][i]
record.close = data['close'][i]
record.amount = data['money'][i]
record.volume = data['volume'][i]
2020-10-02 17:31:33 +08:00
result.append(record)
return result
2020-06-25 15:59:37 +08:00
def getCount(self, market, code, ktype):
"""
重载接口必须获取K线数量
:param str market: 市场标识
:param str code: 证券代码
2020-06-30 23:27:23 +08:00
:param Query.KType ktype: K线类型
"""
data = self._get_bars(market, code, ktype)
return len(data)
2020-06-25 15:59:37 +08:00
def _getIndexRangeByDate(self, market, code, query):
"""
重载接口必须按日期获取指定的K线数据
:param str market: 市场标识
:param str code: 证券代码
2020-06-30 23:27:23 +08:00
:param Query query: 日期查询条件QueryByDate
"""
print("getIndexRangeByDate")
2021-02-06 14:45:52 +08:00
if query.query_type != Query.DATE:
return (0, 0)
2020-06-25 15:59:37 +08:00
start_datetime = query.startDatetime
end_datetime = query.endDatetime
if start_datetime >= end_datetime or start_datetime > Datetime.max():
return (0, 0)
2020-06-25 15:59:37 +08:00
data = self._get_bars(market, code, query.kType)
total = len(data)
if total == 0:
return (0, 0)
2020-06-25 15:59:37 +08:00
mid, low = 0, 0
2020-06-25 15:59:37 +08:00
high = total - 1
while low <= high:
tmp_datetime = Datetime(data.index[high])
if start_datetime > tmp_datetime:
mid = high + 1
break
2020-06-25 15:59:37 +08:00
tmp_datetime = Datetime(data.index[low])
if tmp_datetime >= start_datetime:
mid = low
break
2020-06-25 15:59:37 +08:00
mid = (low + high) // 2
tmp_datetime = Datetime(data.index[mid])
if start_datetime > tmp_datetime:
low = mid + 1
else:
high = mid - 1
2020-06-25 15:59:37 +08:00
if mid >= total:
return (0, 0)
2020-06-25 15:59:37 +08:00
start_pos = mid
low = mid
high = total - 1
while low <= high:
tmp_datetime = Datetime(data.index[high])
if end_datetime > tmp_datetime:
mid = high + 1
break
2020-06-25 15:59:37 +08:00
tmp_datetime = Datetime(data.index[low])
if tmp_datetime >= end_datetime:
mid = low
break
2020-06-25 15:59:37 +08:00
mid = (low + high) // 2
tmp_datetime = Datetime(data.index[mid])
if end_datetime > tmp_datetime:
low = mid + 1
else:
high = mid - 1
2020-06-25 15:59:37 +08:00
end_pos = total if mid >= total else mid
if start_pos >= end_pos:
2020-06-25 15:59:37 +08:00
return (0, 0)
return (start_pos, end_pos)
2020-06-25 15:59:37 +08:00
def getKRecord(self, market, code, pos, ktype):
"""
重载接口必须获取指定位置的K线记录
:param str market: 市场标识
:param str code: 证券代码
:param int pos: 指定位置大于等于0
2020-06-30 23:27:23 +08:00
:param Query.KType ktype: K线类型
"""
record = KRecord()
if pos < 0:
return record
2020-06-25 15:59:37 +08:00
data = self._get_bars(market, code, ktype)
if data is None:
return record
2020-06-25 15:59:37 +08:00
if pos < len(data):
2020-06-25 15:59:37 +08:00
record.datetime = Datetime(data.index[pos])
2020-07-04 23:54:02 +08:00
record.open = data['open'][pos]
record.high = data['high'][pos]
record.low = data['low'][pos]
record.close = data['close'][pos]
record.amount = data['money'][pos]
record.volume = data['volume'][pos]
2020-06-25 15:59:37 +08:00
return record
2020-06-25 15:59:37 +08:00
def _trans_ktype(self, ktype): #此处的周月季年数据只是近似的目前jqdata未提供聚宽网络平台上的get_bar函数不能直接取需要自行用日线数据拼装
ktype_map = {
Query.MIN: '1m',
Query.MIN5: '5m',
Query.MIN15: '15m',
Query.MIN30: '30m',
Query.MIN60: '60m',
Query.DAY: '1d',
Query.WEEK: '7d',
Query.MONTH: '30d',
Query.QUARTER: '90d',
Query.YEAR: '365d'
}
return ktype_map.get(ktype)
2020-06-25 15:59:37 +08:00
def _get_bars(self, market, code, ktype):
data = []
username = self.getParam('username')
password = self.getParam('password')
auth(username, password)
jqdataCode = normalize_code(code)
jqdata_ktype = self._trans_ktype(ktype)
if jqdata_ktype is None:
print("jqdata_ktype == None")
return data
print(jqdataCode)
security_info = get_security_info(jqdataCode)
2020-06-25 15:59:37 +08:00
if security_info is None: #有可能取不到任何信息
return data
#print(security_info)
data = get_price(jqdataCode, security_info.start_date, datetime.now(), jqdata_ktype)
return data
2020-06-25 15:59:37 +08:00
#DataDriverFactory.regKDataDriver(jqdataKDataDriver())
#jqdata_param = Parameter()
#jqdata_param.set('type', 'jqdata')
#jqdata_param.set('username', '用户名')
#jqdata_param.set('password', '密码')
#base_param = sm.getBaseInfoDriverParameter()
#block_param = sm.getBlockDriverParameter()
#kdata_param = sm.getKDataDriverParameter()
#preload_param = sm.getPreloadParameter()
#hku_param = sm.getHikyuuParameter()
#切换K线数据驱动重新初始化
2021-02-17 19:43:59 +08:00
#sm.init(base_param, block_param, jqdata_param, preload_param, hku_param)