From 23fb096ab7238d12233a74d6790c5badc6e3126f Mon Sep 17 00:00:00 2001 From: msincenselee Date: Sat, 4 Jan 2020 12:22:22 +0800 Subject: [PATCH] =?UTF-8?q?[=E6=96=B0=E5=8A=9F=E8=83=BD]=20tdx=20=E6=9C=9F?= =?UTF-8?q?=E8=B4=A7=E6=8C=87=E6=95=B0=E6=95=B0=E6=8D=AE=EF=BC=8C=E6=AF=8F?= =?UTF-8?q?=E5=A4=A9=E8=87=AA=E5=8A=A8=E5=A2=9E=E9=87=8F=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E8=87=B3csv=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy/data/tdx/future_contracts.json | 514 ++++++++++++++++++++++++ vnpy/data/tdx/refill_tdx_future_bars.py | 95 +++++ vnpy/data/tdx/tdx_common.py | 2 +- vnpy/data/tdx/tdx_future_data.py | 137 ++++--- vnpy/data/tdx/test_tdx_future.py | 19 +- 5 files changed, 703 insertions(+), 64 deletions(-) create mode 100644 vnpy/data/tdx/future_contracts.json create mode 100644 vnpy/data/tdx/refill_tdx_future_bars.py diff --git a/vnpy/data/tdx/future_contracts.json b/vnpy/data/tdx/future_contracts.json new file mode 100644 index 00000000..c71c6d46 --- /dev/null +++ b/vnpy/data/tdx/future_contracts.json @@ -0,0 +1,514 @@ +{ + "A": { + "underlying_symbol": "A", + "mi_symbol": "a2005", + "full_symbol": "A2005", + "exchange": "DCE", + "symbol_size": "10", + "price_tick": "1" + }, + "AG": { + "underlying_symbol": "AG", + "mi_symbol": "ag2007", + "full_symbol": "AG2007", + "exchange": "SHFE", + "symbol_size": "15", + "price_tick": "1" + }, + "AL": { + "underlying_symbol": "AL", + "mi_symbol": "al2002", + "full_symbol": "AL2002", + "exchange": "SHFE", + "symbol_size": "5", + "price_tick": "5" + }, + "AP": { + "underlying_symbol": "AP", + "mi_symbol": "AP005", + "full_symbol": "AP2005", + "exchange": "CZCE", + "symbol_size": "10", + "price_tick": "1" + }, + "AU": { + "underlying_symbol": "AU", + "mi_symbol": "au2006", + "full_symbol": "AU2006", + "exchange": "SHFE", + "symbol_size": "1000", + "price_tick": "0.05" + }, + "B": { + "underlying_symbol": "B", + "mi_symbol": "b2003", + "full_symbol": "B2003", + "exchange": "DCE", + "symbol_size": "10", + "price_tick": "1" + }, + "BB": { + "underlying_symbol": "BB", + "mi_symbol": "bb2012", + "full_symbol": "BB2012", + "exchange": "DCE", + "symbol_size": "500", + "price_tick": "0.05" + }, + "BU": { + "underlying_symbol": "BU", + "mi_symbol": "bu2006", + "full_symbol": "BU2006", + "exchange": "SHFE", + "symbol_size": "10", + "price_tick": "2" + }, + "C": { + "underlying_symbol": "C", + "mi_symbol": "c2005", + "full_symbol": "C2005", + "exchange": "DCE", + "symbol_size": "10", + "price_tick": "1" + }, + "CF": { + "underlying_symbol": "CF", + "mi_symbol": "CF005", + "full_symbol": "CF2005", + "exchange": "CZCE", + "symbol_size": "5", + "price_tick": "5" + }, + "CJ": { + "underlying_symbol": "CJ", + "mi_symbol": "CJ005", + "full_symbol": "CJ2005", + "exchange": "CZCE", + "symbol_size": "5", + "price_tick": "5" + }, + "CS": { + "underlying_symbol": "CS", + "mi_symbol": "cs2005", + "full_symbol": "CS2005", + "exchange": "DCE", + "symbol_size": "10", + "price_tick": "1" + }, + "CU": { + "underlying_symbol": "CU", + "mi_symbol": "cu2003", + "full_symbol": "CU2003", + "exchange": "SHFE", + "symbol_size": "5", + "price_tick": "10" + }, + "CY": { + "underlying_symbol": "CY", + "mi_symbol": "CY005", + "full_symbol": "CY2005", + "exchange": "CZCE", + "symbol_size": "5", + "price_tick": "5" + }, + "EB": { + "underlying_symbol": "EB", + "mi_symbol": "eb2005", + "full_symbol": "EB2005", + "exchange": "DCE", + "symbol_size": "5", + "price_tick": "1" + }, + "EG": { + "underlying_symbol": "EG", + "mi_symbol": "eg2005", + "full_symbol": "EG2005", + "exchange": "DCE", + "symbol_size": "10", + "price_tick": "1" + }, + "FB": { + "underlying_symbol": "FB", + "mi_symbol": "fb2005", + "full_symbol": "FB2005", + "exchange": "DCE", + "symbol_size": "500", + "price_tick": "0.05" + }, + "FG": { + "underlying_symbol": "FG", + "mi_symbol": "FG005", + "full_symbol": "FG2005", + "exchange": "CZCE", + "symbol_size": "20", + "price_tick": "1" + }, + "FU": { + "underlying_symbol": "FU", + "mi_symbol": "fu2005", + "full_symbol": "FU2005", + "exchange": "SHFE", + "symbol_size": "10", + "price_tick": "1" + }, + "HC": { + "underlying_symbol": "HC", + "mi_symbol": "hc2005", + "full_symbol": "HC2005", + "exchange": "SHFE", + "symbol_size": "10", + "price_tick": "1" + }, + "I": { + "underlying_symbol": "I", + "mi_symbol": "i2005", + "full_symbol": "I2005", + "exchange": "DCE", + "symbol_size": "100", + "price_tick": "0.5" + }, + "IC": { + "underlying_symbol": "IC", + "mi_symbol": "IC2003", + "full_symbol": "IC2003", + "exchange": "CFFEX", + "symbol_size": "200", + "price_tick": "0.2" + }, + "IF": { + "underlying_symbol": "IF", + "mi_symbol": "IF2003", + "full_symbol": "IF2003", + "exchange": "CFFEX", + "symbol_size": "300", + "price_tick": "0.2" + }, + "IH": { + "underlying_symbol": "IH", + "mi_symbol": "IH2003", + "full_symbol": "IH2003", + "exchange": "CFFEX", + "symbol_size": "300", + "price_tick": "0.2" + }, + "J": { + "underlying_symbol": "J", + "mi_symbol": "j2005", + "full_symbol": "J2005", + "exchange": "DCE", + "symbol_size": "100", + "price_tick": "0.5" + }, + "JD": { + "underlying_symbol": "JD", + "mi_symbol": "jd2005", + "full_symbol": "JD2005", + "exchange": "DCE", + "symbol_size": "10", + "price_tick": "1" + }, + "JM": { + "underlying_symbol": "JM", + "mi_symbol": "jm2005", + "full_symbol": "JM2005", + "exchange": "DCE", + "symbol_size": "60", + "price_tick": "0.5" + }, + "JR": { + "underlying_symbol": "JR", + "mi_symbol": "JR011", + "full_symbol": "JR2011", + "exchange": "CZCE", + "symbol_size": "20", + "price_tick": "1" + }, + "L": { + "underlying_symbol": "L", + "mi_symbol": "l2005", + "full_symbol": "L2005", + "exchange": "DCE", + "symbol_size": "5", + "price_tick": "5" + }, + "LR": { + "underlying_symbol": "LR", + "mi_symbol": "LR007", + "full_symbol": "LR2007", + "exchange": "CZCE", + "symbol_size": "20", + "price_tick": "1" + }, + "M": { + "underlying_symbol": "M", + "mi_symbol": "m2005", + "full_symbol": "M2005", + "exchange": "DCE", + "symbol_size": "10", + "price_tick": "1" + }, + "MA": { + "underlying_symbol": "MA", + "mi_symbol": "MA005", + "full_symbol": "MA2005", + "exchange": "CZCE", + "symbol_size": "10", + "price_tick": "1" + }, + "NI": { + "underlying_symbol": "NI", + "mi_symbol": "ni2003", + "full_symbol": "NI2003", + "exchange": "SHFE", + "symbol_size": "1", + "price_tick": "10" + }, + "NR": { + "underlying_symbol": "NR", + "mi_symbol": "nr2004", + "full_symbol": "NR2004", + "exchange": "INE", + "symbol_size": "10", + "price_tick": "5" + }, + "OI": { + "underlying_symbol": "OI", + "mi_symbol": "OI005", + "full_symbol": "OI2005", + "exchange": "CZCE", + "symbol_size": "10", + "price_tick": "1" + }, + "P": { + "underlying_symbol": "P", + "mi_symbol": "p2005", + "full_symbol": "P2005", + "exchange": "DCE", + "symbol_size": "10", + "price_tick": "2" + }, + "PB": { + "underlying_symbol": "PB", + "mi_symbol": "pb2002", + "full_symbol": "PB2002", + "exchange": "SHFE", + "symbol_size": "5", + "price_tick": "5" + }, + "PM": { + "underlying_symbol": "PM", + "mi_symbol": "PM011", + "full_symbol": "PM2011", + "exchange": "CZCE", + "symbol_size": "50", + "price_tick": "1" + }, + "PP": { + "underlying_symbol": "PP", + "mi_symbol": "pp2005", + "full_symbol": "PP2005", + "exchange": "DCE", + "symbol_size": "5", + "price_tick": "1" + }, + "RB": { + "underlying_symbol": "RB", + "mi_symbol": "rb2005", + "full_symbol": "RB2005", + "exchange": "SHFE", + "symbol_size": "10", + "price_tick": "1" + }, + "RI": { + "underlying_symbol": "RI", + "mi_symbol": "RI011", + "full_symbol": "RI2011", + "exchange": "CZCE", + "symbol_size": "20", + "price_tick": "1" + }, + "RM": { + "underlying_symbol": "RM", + "mi_symbol": "RM005", + "full_symbol": "RM2005", + "exchange": "CZCE", + "symbol_size": "10", + "price_tick": "1" + }, + "RR": { + "underlying_symbol": "RR", + "mi_symbol": "rr2005", + "full_symbol": "RR2005", + "exchange": "DCE", + "symbol_size": "10", + "price_tick": "1" + }, + "RS": { + "underlying_symbol": "RS", + "mi_symbol": "RS011", + "full_symbol": "RS2011", + "exchange": "CZCE", + "symbol_size": "10", + "price_tick": "1" + }, + "RU": { + "underlying_symbol": "RU", + "mi_symbol": "ru2005", + "full_symbol": "RU2005", + "exchange": "SHFE", + "symbol_size": "10", + "price_tick": "5" + }, + "SA": { + "underlying_symbol": "SA", + "mi_symbol": "SA005", + "full_symbol": "SA2005", + "exchange": "CZCE", + "symbol_size": "20", + "price_tick": "1" + }, + "SC": { + "underlying_symbol": "SC", + "mi_symbol": "sc2003", + "full_symbol": "SC2003", + "exchange": "INE", + "symbol_size": "1000", + "price_tick": "0.1" + }, + "SF": { + "underlying_symbol": "SF", + "mi_symbol": "SF005", + "full_symbol": "SF2005", + "exchange": "CZCE", + "symbol_size": "5", + "price_tick": "2" + }, + "SM": { + "underlying_symbol": "SM", + "mi_symbol": "SM005", + "full_symbol": "SM2005", + "exchange": "CZCE", + "symbol_size": "5", + "price_tick": "2" + }, + "SN": { + "underlying_symbol": "SN", + "mi_symbol": "sn2006", + "full_symbol": "SN2006", + "exchange": "SHFE", + "symbol_size": "1", + "price_tick": "10" + }, + "SP": { + "underlying_symbol": "SP", + "mi_symbol": "sp2005", + "full_symbol": "SP2005", + "exchange": "SHFE", + "symbol_size": "10", + "price_tick": "2" + }, + "SR": { + "underlying_symbol": "SR", + "mi_symbol": "SR005", + "full_symbol": "SR2005", + "exchange": "CZCE", + "symbol_size": "10", + "price_tick": "1" + }, + "SS": { + "underlying_symbol": "SS", + "mi_symbol": "ss2006", + "full_symbol": "SS2006", + "exchange": "SHFE", + "symbol_size": "5", + "price_tick": "5" + }, + "T": { + "underlying_symbol": "T", + "mi_symbol": "T2003", + "full_symbol": "T2003", + "exchange": "CFFEX", + "symbol_size": "10000", + "price_tick": "0.005" + }, + "TA": { + "underlying_symbol": "TA", + "mi_symbol": "TA005", + "full_symbol": "TA2005", + "exchange": "CZCE", + "symbol_size": "5", + "price_tick": "2" + }, + "TF": { + "underlying_symbol": "TF", + "mi_symbol": "TF2003", + "full_symbol": "TF2003", + "exchange": "CFFEX", + "symbol_size": "10000", + "price_tick": "0.005" + }, + "TS": { + "underlying_symbol": "TS", + "mi_symbol": "TS2003", + "full_symbol": "TS2003", + "exchange": "CFFEX", + "symbol_size": "20000", + "price_tick": "0.005" + }, + "UR": { + "underlying_symbol": "UR", + "mi_symbol": "UR005", + "full_symbol": "UR2005", + "exchange": "CZCE", + "symbol_size": "20", + "price_tick": "1" + }, + "V": { + "underlying_symbol": "V", + "mi_symbol": "v2005", + "full_symbol": "V2005", + "exchange": "DCE", + "symbol_size": "5", + "price_tick": "5" + }, + "WH": { + "underlying_symbol": "WH", + "mi_symbol": "WH005", + "full_symbol": "WH2005", + "exchange": "CZCE", + "symbol_size": "20", + "price_tick": "1" + }, + "WR": { + "underlying_symbol": "WR", + "mi_symbol": "wr2012", + "full_symbol": "WR2012", + "exchange": "SHFE", + "symbol_size": "10", + "price_tick": "1" + }, + "Y": { + "underlying_symbol": "Y", + "mi_symbol": "y2005", + "full_symbol": "Y2005", + "exchange": "DCE", + "symbol_size": "10", + "price_tick": "2" + }, + "ZC": { + "underlying_symbol": "ZC", + "mi_symbol": "ZC005", + "full_symbol": "ZC2005", + "exchange": "CZCE", + "symbol_size": "100", + "price_tick": "0.2" + }, + "ZN": { + "underlying_symbol": "ZN", + "mi_symbol": "zn2003", + "full_symbol": "ZN2003", + "exchange": "SHFE", + "symbol_size": "5", + "price_tick": "5" + } +} \ No newline at end of file diff --git a/vnpy/data/tdx/refill_tdx_future_bars.py b/vnpy/data/tdx/refill_tdx_future_bars.py new file mode 100644 index 00000000..59f969b8 --- /dev/null +++ b/vnpy/data/tdx/refill_tdx_future_bars.py @@ -0,0 +1,95 @@ +# flake8: noqa +""" +下载通达信指数合约1分钟bar => vnpy项目目录/bar_data/ + +""" +import os +import sys +import json +from collections import OrderedDict +import pandas as pd + +vnpy_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..')) +if vnpy_root not in sys.path: + sys.path.append(vnpy_root) + +os.environ["VNPY_TESTING"] = "1" + +from vnpy.data.tdx.tdx_future_data import * + +# 保存的1分钟指数 bar目录 +bar_data_folder = os.path.abspath(os.path.join(vnpy_root, 'bar_data')) + +# 开始日期(每年大概需要几分钟) +start_date = '20160101' + +# 创建API对象 +api_01 = TdxFutureData() + +# 更新本地合约缓存信息 +api_01.update_mi_contracts() + + +def bar_to_dict(bar_data: BarData): + d = OrderedDict({ + 'datetime': bar_data.datetime, + 'symbol': bar_data.symbol, + 'vt_symbol': bar_data.vt_symbol, + 'exchange': bar_data.exchange.value, + 'open': bar_data.open_price, + 'close': bar_data.close_price, + 'high': bar_data.high_price, + 'low': bar_data.low_price, + 'volume': bar_data.volume, + 'open_interest': bar_data.open_interest, + 'trading_day': bar_data.trading_day + }) + return d + + +for underlying_symbol in api_01.future_contracts.keys(): + index_symbol = underlying_symbol + '99' + print(f'开始更新:{index_symbol}') + # csv数据文件名 + bar_file_path = os.path.abspath(os.path.join(bar_data_folder, f'{underlying_symbol}99_{start_date}_1m.csv')) + + # 如果文件存在, + if os.path.exists(bar_file_path): + + df_old = pd.read_csv(bar_file_path, index_col=0) + df_old = df_old.rename(lambda x: pd.to_datetime(x, format="%Y-%m-%d %H:%M:%S")) + # 取最后一条时间 + last_dt = df_old.index[-1] + start_dt = last_dt - timedelta(days=1) + print(f'文件{bar_file_path}存在,最后时间:{start_date}') + else: + df_old = None + start_dt = datetime.strptime(start_date, '%Y%m%d') + print(f'文件{bar_file_path}不存在,开始时间:{start_date}') + + result, bars = api_01.get_bars(symbol=index_symbol, + period='1min', + callback=None, + start_dt=start_dt, + return_bar=False) + # [dict] => dataframe + df_extern = pd.DataFrame(bars) + df_extern.set_index('datetime', inplace=True) + + if df_old is not None: + # 扩展数据 + print('扩展数据') + data_df = pd.concat([df_old, df_extern], axis=0) + else: + data_df = df_extern + + # 数据按时间戳去重 + print('按时间戳去重') + data_df = data_df[~data_df.index.duplicated(keep='first')] + # 排序 + data_df = data_df.sort_index() + # print(data_df.head()) + print(data_df.tail()) + data_df.to_csv(bar_file_path, index=True) + print(f'更新{index_symbol}数据 => 文件{bar_file_path}') + diff --git a/vnpy/data/tdx/tdx_common.py b/vnpy/data/tdx/tdx_common.py index 84cb46d5..3884c5e6 100644 --- a/vnpy/data/tdx/tdx_common.py +++ b/vnpy/data/tdx/tdx_common.py @@ -126,4 +126,4 @@ class FakeStrategy(object): self.write_log(content, level=ERROR) def display_bar(self, bar, bar_is_completed=True, freq=1): - print(u'{} {}'.format(bar.vtSymbol, bar.datetime)) + print(u'{} {}'.format(bar.vt_symbol, bar.datetime)) diff --git a/vnpy/data/tdx/tdx_future_data.py b/vnpy/data/tdx/tdx_future_data.py index b3baf2eb..56fb15c9 100644 --- a/vnpy/data/tdx/tdx_future_data.py +++ b/vnpy/data/tdx/tdx_future_data.py @@ -17,7 +17,7 @@ import traceback from datetime import datetime, timedelta, time from logging import ERROR -from typing import Dict +from typing import Dict, Callable from pandas import to_datetime from pytdx.exhq import TdxExHq_API @@ -91,7 +91,7 @@ def get_tdx_marketid(symbol): class TdxFutureData(object): # ---------------------------------------------------------------------- - def __init__(self, strategy, best_ip={}): + def __init__(self, strategy=None, best_ip={}): """ 构造函数 :param strategy: 上层策略,主要用与使用write_log() @@ -195,8 +195,17 @@ class TdxFutureData(object): save_cache_json(best_future_ip, TDX_FUTURE_CONFIG) return best_future_ip - # ---------------------------------------------------------------------- - def qryInstrument(self): + def _get_vn_exchange(self, symbol): + """获取""" + underlying_symbol = get_underlying_symbol(symbol).upper() + info = self.future_contracts.get(underlying_symbol, None) + if info: + return Exchange(info.get('exchange')) + else: + market_id = get_tdx_marketid(symbol) + return Tdx_Vn_Exchange_Map.get(str(market_id), Exchange.INE) + + def qry_instrument(self): """ 查询/更新合约信息 :return: @@ -225,19 +234,29 @@ class TdxFutureData(object): def get_bars(self, symbol: str, period: str, - callback, + callback: Callable = None, bar_freq: int = 1, - start_dt: datetime = None): + start_dt: datetime = None, + end_dt: datetime = None, + return_bar=True): """ 返回k线数据 symbol:合约 period: 周期: 1min,3min,5min,15min,30min,1day,3day,1hour,2hour,4hour,6hour,12hour + callback: 逐一bar去驱动回调函数, 只有 return_bar = True时才回调 + bar_freq: 回调时的参数 + start_dt: 取数据的开始时间 + end_dt: 取数据的结束时间 + return_bar: 返回 第二个数据内容,True:BarData, False:dict """ ret_bars = [] tdx_symbol = symbol.upper().replace('_', '') tdx_symbol = tdx_symbol.replace('99', 'L9') - tdx_index_symbol = get_underlying_symbol(symbol) + 'L9' + underlying_symbol = get_underlying_symbol(symbol).upper() + tdx_index_symbol = underlying_symbol + 'L9' + vn_exchange = self._get_vn_exchange(underlying_symbol) + self.connect() if self.api is None: return False, ret_bars @@ -253,7 +272,11 @@ class TdxFutureData(object): qry_start_date = datetime.now() - timedelta(days=10) else: qry_start_date = start_dt - end_date = datetime.combine(datetime.now() + timedelta(days=1), time(ALL_MARKET_END_HOUR, 0)) + if end_dt is None: + self.write_log(u'没有设置结束时间,缺省为当日') + end_date = datetime.combine(datetime.now() + timedelta(days=1), time(ALL_MARKET_END_HOUR, 0)) + else: + end_date = end_dt if qry_start_date > end_date: qry_start_date = end_date self.write_log('{}开始下载tdx:{} {}数据, {} to {}.' @@ -290,12 +313,6 @@ class TdxFutureData(object): data = data.assign(datetime=to_datetime(data['datetime'])) data = data.assign(ticker=symbol) data['instrument_id'] = data['ticker'] - # if future['market'] == 28 or future['market'] == 47: - # # 大写字母: 郑州商品 or 中金所期货 - # data['instrument_id'] = data['ticker'] - # else: - # data['instrument_id'] = data['ticker'].apply(lambda x: x.lower()) - data['symbol'] = symbol data = data.drop( ['year', 'month', 'day', 'hour', 'minute', 'price', 'amount', 'ticker'], @@ -312,11 +329,11 @@ class TdxFutureData(object): str(datetime.now()), tdx_symbol, len(data))) return False, ret_bars - data['total_turnover'] = data['volume'] + data['total_turnover'] = data['volume'] * data['close'] data["limit_down"] = 0 data["limit_up"] = 999999 - data['trading_date'] = data['datetime'] - data['trading_date'] = data['trading_date'].apply(lambda x: (x.strftime('%Y-%m-%d'))) + data['trading_day'] = data['datetime'] + data['trading_day'] = data['trading_day'].apply(lambda x: (x.strftime('%Y-%m-%d'))) monday_ts = data['datetime'].dt.weekday == 0 # 星期一 night_ts1 = data['datetime'].dt.hour > ALL_MARKET_END_HOUR night_ts2 = data['datetime'].dt.hour < ALL_MARKET_BEGIN_HOUR @@ -326,52 +343,54 @@ class TdxFutureData(object): monday_ts2 = monday_ts & night_ts2 # 星期一的夜盘(00:00~04:00), 再减两天 data.loc[monday_ts2, 'datetime'] -= timedelta(days=2) # data['datetime'] -= timedelta(minutes=1) # 直接给Strategy使用, RiceQuant格式, 不需要减1分钟 - data['dt_datetime'] = data['datetime'] + # data['dt_datetime'] = data['datetime'] data['date'] = data['datetime'].apply(lambda x: (x.strftime('%Y-%m-%d'))) data['time'] = data['datetime'].apply(lambda x: (x.strftime('%H:%M:%S'))) - data['datetime'] = data['datetime'].apply(lambda x: float(x.strftime('%Y%m%d%H%M%S'))) - data = data.set_index('dt_datetime', drop=False) - # data = data[int(last_date.strftime('%Y%m%d%H%M%S')):int(end_date.strftime('%Y%m%d%H%M%S'))] - # data = data[str(last_date):str(end_date)] + # data['datetime'] = data['datetime'].apply(lambda x: float(x.strftime('%Y%m%d%H%M%S'))) + data = data.set_index('datetime', drop=False) + if return_bar: + self.write_log('dataframe => [bars]') + for index, row in data.iterrows(): + add_bar = BarData(gateway_name='tdx', + symbol=symbol, + exchange=vn_exchange, + datetime=index) + try: + add_bar.date = row['date'] + add_bar.time = row['time'] + add_bar.trading_day = row['trading_day'] + add_bar.open_price = float(row['open']) + add_bar.high_price = float(row['high']) + add_bar.low_price = float(row['low']) + add_bar.close_price = float(row['close']) + add_bar.volume = float(row['volume']) + add_bar.openInterest = float(row['open_interest']) + except Exception as ex: + self.write_error( + 'error when convert bar:{},ex:{},t:{}'.format(row, str(ex), traceback.format_exc())) + # print('error when convert bar:{},ex:{},t:{}'.format(row, str(ex), traceback.format_exc())) + return False, ret_bars - for index, row in data.iterrows(): - add_bar = BarData() - try: - add_bar.symbol = row['symbol'] - add_bar.datetime = index - add_bar.date = row['date'] - add_bar.time = row['time'] - add_bar.trading_date = row['trading_date'] - add_bar.open_price = float(row['open']) - add_bar.high_price = float(row['high']) - add_bar.low_price = float(row['low']) - add_bar.close_price = float(row['close']) - add_bar.volume = float(row['volume']) - add_bar.openInterest = float(row['open_interest']) - except Exception as ex: - self.write_error( - 'error when convert bar:{},ex:{},t:{}'.format(row, str(ex), traceback.format_exc())) - # print('error when convert bar:{},ex:{},t:{}'.format(row, str(ex), traceback.format_exc())) - return False - - if start_dt is not None and index < start_dt: - continue - ret_bars.append(add_bar) - - if callback is not None: - freq = bar_freq - bar_is_completed = True - if period != '1min' and index == data['dt_datetime'][-1]: - # 最后一个bar,可能是不完整的,强制修改 - # - 5min修改后freq基本正确 - # - 1day在VNPY合成时不关心已经收到多少Bar, 所以影响也不大 - # - 但其它分钟周期因为不好精确到每个品种, 修改后的freq可能有错 - if index > current_datetime: - bar_is_completed = False - # 根据秒数算的话,要+1,例如13:31,freq=31,第31根bar - freq = NUM_MINUTE_MAPPING[period] - int((index - current_datetime).total_seconds() / 60) - callback(add_bar, bar_is_completed, freq) + if start_dt is not None and index < start_dt: + continue + ret_bars.append(add_bar) + if callback is not None: + freq = bar_freq + bar_is_completed = True + if period != '1min' and index == data['datetime'][-1]: + # 最后一个bar,可能是不完整的,强制修改 + # - 5min修改后freq基本正确 + # - 1day在VNPY合成时不关心已经收到多少Bar, 所以影响也不大 + # - 但其它分钟周期因为不好精确到每个品种, 修改后的freq可能有错 + if index > current_datetime: + bar_is_completed = False + # 根据秒数算的话,要+1,例如13:31,freq=31,第31根bar + freq = NUM_MINUTE_MAPPING[period] - int((index - current_datetime).total_seconds() / 60) + callback(add_bar, bar_is_completed, freq) + else: + self.write_log('dataframe => [ dict ]') + ret_bars = list(data.T.to_dict().values()) return True, ret_bars except Exception as ex: self.write_error('exception in get:{},{},{}'.format(tdx_symbol, str(ex), traceback.format_exc())) diff --git a/vnpy/data/tdx/test_tdx_future.py b/vnpy/data/tdx/test_tdx_future.py index 627ea4f6..5c4a54c5 100644 --- a/vnpy/data/tdx/test_tdx_future.py +++ b/vnpy/data/tdx/test_tdx_future.py @@ -1,7 +1,7 @@ # flake8: noqa import os import sys - +import json vnpy_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..')) if vnpy_root not in sys.path: sys.path.append(vnpy_root) @@ -22,7 +22,7 @@ str_markets = json.dumps(markets, indent=1, ensure_ascii=False) print(u'{}'.format(str_markets)) # 获取所有的期货合约明细 -api_01.qryInstrument() +# api_01.qry_instrument() # 获取某个合约得最新价 # price = api_01.get_price('rb2005') @@ -59,8 +59,19 @@ corr = df.corr() print(corr) corr_rate = round(abs(corr.iloc[0, 1]) * 100, 2) """ -# api.get_bars(symbol, period='5min', callback=display_bar) -# api_01.get_bars('IF99', period='1day', callback=t1.display_bar) +# 获取bar,并通过回调方式,提高给策略,逐一onbar +# api_01.get_bars('IF99', period='1min', callback=t1.display_bar, bar_freq=1) + +# 获取bar,只返回 list[dict] +result, bars = api_01.get_bars('IF99', period='1min', return_bar=False) +if result: + print('前十根bar') + for bar in bars[0:10]: + print(bar) + print('后十根bar') + for bar in bars[-10:]: + print(bar) + # result,datas = api_01.get_transaction_data(symbol='ni1905') # api_02 = TdxFutureData(t2) # api_02.get_bars('IF99', period='1min', callback=t1.display_bar)