Skip to content
This repository has been archived by the owner on Apr 15, 2020. It is now read-only.

Commit

Permalink
Merge pull request #9 from rainx/master
Browse files Browse the repository at this point in the history
update
  • Loading branch information
yutiansut committed Aug 14, 2017
2 parents 2724b8f + 1cf9a3f commit 47d6eca
Show file tree
Hide file tree
Showing 9 changed files with 280 additions and 15 deletions.
8 changes: 8 additions & 0 deletions ChangeLog.txt → ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
1.24
------
* 增加 TdxExHqDailyBarReader ,用于读取扩展行情(如期货,现货,期权等)的盘后日线数据 https://github.com/rainx/pytdx/issues/25

1.23
------
* 增加历史分时行情,分时成交,历史分时成交 https://github.com/rainx/pytdx/pull/24 wopalm

1.22
------
* 解决扩展行情,无法指定数据长度的问题 https://github.com/rainx/pytdx/issues/22 wopalm
Expand Down
14 changes: 13 additions & 1 deletion pytdx/bin/hqreader.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,30 @@
from pytdx.reader import TdxDailyBarReader, TdxFileNotFoundException, TdxNotAssignVipdocPathException
from pytdx.reader import TdxMinBarReader
from pytdx.reader import TdxLCMinBarReader
from pytdx.reader import TdxExHqDailyBarReader


Help_Text = '''
数据文件格式,
- daily 代表日K线
- ex_daily 代表扩展行情的日线
- min 代表5分钟或者1分钟线
- lc 代表lc1, lc5格式的分钟线
'''

@click.command()
@click.argument("input", type=click.Path(exists=True))
@click.option("-o", '--output', help="")
@click.option("-d", "--datatype", default="daily", help="数据文件格式, daily 代表日K线, min 代表5分钟或者1分钟线, lc 代表lc1, lc5格式的分钟线")
@click.option("-d", "--datatype", default="daily", help=Help_Text)
def main(input, output, datatype):
"""
通达信数据文件读取
"""

if datatype == 'daily':
reader = TdxDailyBarReader()
elif datatype == 'ex_daily':
reader = TdxExHqDailyBarReader()
elif datatype == 'lc':
reader = TdxLCMinBarReader()
else:
Expand Down
60 changes: 47 additions & 13 deletions pytdx/exhq.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@
from pytdx.parser.ex_get_instrument_count import GetInstrumentCount
from pytdx.parser.ex_get_instrument_quote import GetInstrumentQuote
from pytdx.parser.ex_get_minute_time_data import GetMinuteTimeData
from pytdx.parser.ex_get_history_minute_time_data import GetHistoryMinuteTimeData
from pytdx.parser.ex_get_transaction_data import GetTransactionData
from pytdx.parser.ex_get_history_transaction_data import GetHistoryTransactionData
from pytdx.parser.ex_get_instrument_bars import GetInstrumentBars
from pytdx.parser.ex_get_instrument_info import GetInstrumentInfo


from pytdx.params import TDXParams

import threading,datetime
import threading
import datetime
from pytdx.base_socket_client import BaseSocketClient, update_last_ack_time


Expand All @@ -46,12 +50,13 @@
Out[8]: 64.0
"""


class TdxExHq_API(BaseSocketClient):

def setup(self):
ExSetupCmd1(self.client).call_api()

### API LIST
# API LIST

@update_last_ack_time
def get_markets(self):
Expand Down Expand Up @@ -81,6 +86,24 @@ def get_minute_time_data(self, market, code):
cmd.setParams(market, code)
return cmd.call_api()

@update_last_ack_time
def get_history_minute_time_data(self, market, code, date):
cmd = GetHistoryMinuteTimeData(self.client)
cmd.setParams(market, code, date=date)
return cmd.call_api()

@update_last_ack_time
def get_transaction_data(self, market, code, start=0, count=1800):
cmd = GetTransactionData(self.client)
cmd.setParams(market, code, start=start, count=count)
return cmd.call_api()

@update_last_ack_time
def get_history_transaction_data(self, market, code, date, start=0, count=1800):
cmd = GetHistoryTransactionData(self.client)
cmd.setParams(market, code, date, start=start, count=count)
return cmd.call_api()

@update_last_ack_time
def get_instrument_info(self, start, count=100):
cmd = GetInstrumentInfo(self.client)
Expand All @@ -90,26 +113,37 @@ def get_instrument_info(self, start, count=100):
def do_heartbeat(self):
self.get_instrument_count()


if __name__ == '__main__':
import pprint

api = TdxExHq_API()
with api.connect('121.14.110.210', 7727):
log.info("获取市场代码")
#pprint.pprint(api.to_df(api.get_markets()))
log.info("查询市场中商品数量")
pprint.pprint(api.get_instrument_count())
log.info("查询五档行情")
# log.info("获取市场代码")
# pprint.pprint(api.to_df(api.get_markets()))
# log.info("查询市场中商品数量")
# pprint.pprint(api.get_instrument_count())
# log.info("查询五档行情")
#pprint.pprint(api.to_df(api.get_instrument_quote(47, "IF1709")))
#pprint.pprint(api.get_instrument_quote(8, "10000889"))
#pprint.pprint(api.get_instrument_quote(31, "00020"))
log.info("查询分时行情")
#pprint.pprint(api.to_df(api.get_minute_time_data(47, "IF1709")))
#pprint.pprint(api.get_minute_time_data(8, "10000889"))
# log.info("查询分时行情")
#api.get_minute_time_data(47, "IFL0")
#pprint.pprint(api.to_df(api.get_minute_time_data(47, "IFL0")))
#pprint.pprint(api.to_df(api.get_minute_time_data(8, "10000889")).tail())
#pprint.pprint(api.get_minute_time_data(31, "00020"))
log.info("查询历史分时行情")
pprint.pprint(api.to_df(api.get_history_minute_time_data(31, "00020", 20170811)).tail())
log.info("查询分时成交")
pprint.pprint(api.to_df(api.get_transaction_data(31, "00020")).tail())

log.info("查询历史分时成交")
pprint.pprint(api.to_df(api.get_history_transaction_data(31, "00020", 20170811)).tail())
#data = api.get_history_minute_time_data(47, 'IFL0', 20170811)
# pprint.pprint(data)

log.info("查询k线")
# log.info("查询k线")
#pprint.pprint(api.to_df(api.get_instrument_bars(TDXParams.KLINE_TYPE_DAILY, 8, "10000843")))
#pprint.pprint(api.to_df(api.get_instrument_bars(TDXParams.KLINE_TYPE_DAILY, 31, "00700")))
log.info("查询代码列表")
pprint.pprint(api.to_df(api.get_instrument_info(10000, 98)))
# log.info("查询代码列表")
#pprint.pprint(api.to_df(api.get_instrument_info(10000, 98)))
53 changes: 53 additions & 0 deletions pytdx/parser/ex_get_history_minute_time_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# coding=utf-8

from pytdx.parser.base import BaseParser
from pytdx.helper import get_datetime, get_volume, get_price
from collections import OrderedDict
import struct


class GetHistoryMinuteTimeData(BaseParser):

def setParams(self, market, code, date):
pkg = bytearray.fromhex("01 01 30 00 01 01 10 00 10 00 0c 24")
code = code.encode("utf-8")
pkg.extend(struct.pack("<IB9s", date, market, code))
#pkg = bytearray.fromhex('01 01 30 00 01 01 10 00 10 00 0c 24 3b c8 33 01 2f 49 46 4c 30 00 38 ec 2d 00')
self.send_pkg = pkg

def parseResponse(self, body_buf):
# print('测试', body_buf)
# fileobj = open("//Users//wy//data//a.bin", 'wb') # make partfile
# fileobj.write(body_buf) # write data into partfile
# fileobj.close()
pos = 0
market, code, _, num = struct.unpack('<B9s8sH', body_buf[pos: pos + 20])
pos += 20
# print(market, code.decode(), num)
result = []
for i in range(num):

(raw_time, price, avg_price, volume, amount) = struct.unpack("<HffII", body_buf[pos: pos + 18])

pos += 18
hour = raw_time // 60
minute = raw_time % 60

result.append(OrderedDict([
("hour", hour),
("minute", minute),
("price", price),
("avg_price", avg_price),
("volume", volume),
("open_interest", amount),
]))

return result


if __name__ == '__main__':
from pytdx.exhq import TdxExHq_API
api = TdxExHq_API()
cmd = GetHistoryMinuteTimeData(api)
cmd.setParams(8, "10000843", 20180811)
print(cmd.send_pkg)
46 changes: 46 additions & 0 deletions pytdx/parser/ex_get_history_transaction_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# coding=utf-8

from pytdx.parser.base import BaseParser
from pytdx.helper import get_datetime, get_volume, get_price
from collections import OrderedDict
import struct


class GetHistoryTransactionData(BaseParser):

def setParams(self, market, code, date, start, count):
# if type(code) is six.text_type:
code = code.encode("utf-8")

# if type(date) is (type(date) is six.text_type) or (type(date) is six.binary_type):
# date = int(date)

# pkg1 = bytearray.fromhex('01 01 30 00 02 01 16 00 16 00 06 24 3b c8 33 01 1f 30 30 30 32 30 00 00 00 01 00 00 00 00 f0 00')
pkg = bytearray.fromhex('01 01 30 00 02 01 16 00 16 00 06 24')
pkg.extend(struct.pack("<IB9siH", date, market, code, start, count))
self.send_pkg = pkg

def parseResponse(self, body_buf):

pos = 0
market, code, _, num = struct.unpack('<B9s4sH', body_buf[pos: pos + 16])
pos += 16
result = []
for i in range(num):

(raw_time, price, volume, zengcang, nature) = struct.unpack("<HIIIH", body_buf[pos: pos + 16])

pos += 16
hour = raw_time // 60
minute = raw_time % 60

result.append(OrderedDict([
("hour", hour),
("minute", minute),
("price", price),
("volume", volume),
("zengcang", zengcang),
("nature", nature),
]))

return result
42 changes: 42 additions & 0 deletions pytdx/parser/ex_get_transaction_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# coding=utf-8

from pytdx.parser.base import BaseParser
from pytdx.helper import get_datetime, get_volume, get_price, get_time
from collections import OrderedDict
import struct
import six


class GetTransactionData(BaseParser):

def setParams(self, market, code, start, count):
if type(code) is six.text_type:
code = code.encode("utf-8")
pkg = bytearray.fromhex('01 01 08 00 03 01 12 00 12 00 fc 23')
pkg.extend(struct.pack("<B9siH", market, code, start, count))
self.send_pkg = pkg

def parseResponse(self, body_buf):

pos = 0
market, code, _, num = struct.unpack('<B9s4sH', body_buf[pos: pos + 16])
pos += 16
result = []
for i in range(num):

(raw_time, price, volume, zengcang, nature) = struct.unpack("<HIIIH", body_buf[pos: pos + 16])

pos += 16
hour = raw_time // 60
minute = raw_time % 60

result.append(OrderedDict([
("hour", hour),
("minute", minute),
("price", price),
("volume", volume),
("zengcang", zengcang),
("nature", nature),
]))

return result
2 changes: 2 additions & 0 deletions pytdx/reader/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from pytdx.reader.daily_bar_reader import TdxDailyBarReader, TdxFileNotFoundException, TdxNotAssignVipdocPathException
from pytdx.reader.min_bar_reader import TdxMinBarReader
from pytdx.reader.lc_min_bar_reader import TdxLCMinBarReader
from pytdx.reader.exhq_daily_bar_reader import TdxExHqDailyBarReader

__all__ = [
'TdxDailyBarReader',
'TdxFileNotFoundException',
'TdxNotAssignVipdocPathException',
'TdxMinBarReader',
'TdxLCMinBarReader',
'TdxExHqDailyBarReader',
]
68 changes: 68 additions & 0 deletions pytdx/reader/exhq_daily_bar_reader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#coding=utf-8
from __future__ import unicode_literals, division

import pandas as pd
import os

import struct
from pytdx.reader.base_reader import TdxFileNotFoundException, TdxNotAssignVipdocPathException
from pytdx.reader.base_reader import BaseReader

"""
读取通达信数据
"""


class TdxExHqDailyBarReader(BaseReader):

def __init__(self, vipdoc_path=None):
self.vipdoc_path = vipdoc_path

def parse_data_by_file(self, fname):

if not os.path.isfile(fname):
raise TdxFileNotFoundException('no tdx kline data, pleaes check path %s', fname)

with open(fname, 'rb') as f:
content = f.read()
return self.unpack_records('<IffffIIf', content)

return []


def get_df(self, code_or_file):

# 只传入了一个参数
data = [self._df_convert(row) for row in self.parse_data_by_file(code_or_file)]

df = pd.DataFrame(data=data, columns=('date', 'open', 'high', 'low', 'close', 'amount', 'volume','jiesuan'))
df.index = pd.to_datetime(df.date)
return df[['open', 'high', 'low', 'close', 'amount', 'volume','jiesuan']]

def _df_convert(self, row):
t_date = str(row[0])
datestr = t_date[:4] + "-" + t_date[4:6] + "-" + t_date[6:]

new_row = (
datestr,
row[1],
row[2],
row[3],
row[4],
row[5],
row[6],
row[7]
)

return new_row


if __name__ == '__main__':
tdx_reader = TdxExHqDailyBarReader()
try:
print(tdx_reader.get_df("/Users/rainx/tmp/vipdoc/ds/29#A1801.day"))
#print(tdx_reader.get_df("/Volumes/share/transfer/76#AG200.day"))

except TdxFileNotFoundException as e:
pass

2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

setup(
name='pytdx',
version='1.22',
version='1.24',
description='A Python Interface to TDX protocol',
author='RainX<Jing Xu>',
author_email='i@rainx.cc',
Expand Down

0 comments on commit 47d6eca

Please sign in to comment.