[update] 币安接口、欧式期权接口、t.d.x选择IP
This commit is contained in:
parent
c14bb707d9
commit
35df2e2412
11
README.md
11
README.md
@ -16,14 +16,14 @@ gitee 链接: https://gitee.com/vnpy2/vnpy
|
|||||||
+ 直接使用,无需pip install easytrader;
|
+ 直接使用,无需pip install easytrader;
|
||||||
+ 任然需要安装组件 pip install -r vnpy/api/easytrader/requirement.txt
|
+ 任然需要安装组件 pip install -r vnpy/api/easytrader/requirement.txt
|
||||||
- vnpy.gateway.gj 国金证券的gateway
|
- vnpy.gateway.gj 国金证券的gateway
|
||||||
+ 使用了tdx作为股票基础数据
|
+ 使用了t.d.x作为股票基础数据
|
||||||
+ 使用了天勤作为行情服务
|
+ 使用了天.勤.作为行情服务
|
||||||
+ 使用了easytrader的remote_client作为接入.
|
+ 使用了easytrader的remote_client作为接入.
|
||||||
- prod.stock_qj 运行例子
|
- prod.stock_qj 运行例子
|
||||||
+ run_es_restful_server.py 放在A机器,安装国金全能客户端。
|
+ run_es_restful_server.py 放在A机器,安装国金全能客户端。
|
||||||
+ run_main_gj01.py 放在B机器,运行vn_trader客户端
|
+ run_main_gj01.py 放在B机器,运行vn_trader客户端
|
||||||
|
|
||||||
15、天勤行情接入
|
15、天.勤.行情接入
|
||||||
|
|
||||||
- vnpy.data.tq 定制downloder,扩展下载字段
|
- vnpy.data.tq 定制downloder,扩展下载字段
|
||||||
- prod.jobs.refill_tq_future.ticks, 下载tick
|
- prod.jobs.refill_tq_future.ticks, 下载tick
|
||||||
@ -113,7 +113,7 @@ gitee 链接: https://gitee.com/vnpy2/vnpy
|
|||||||
|
|
||||||
|
|
||||||
- 提供指数行情订阅
|
- 提供指数行情订阅
|
||||||
- 使用RabbitMQ指数源,或tdx单一数据源
|
- 使用RabbitMQ指数源,或t.d.x单一数据源
|
||||||
- 提供自定义合约功能,实时提供其合成后的tick行情
|
- 提供自定义合约功能,实时提供其合成后的tick行情
|
||||||
- 增加天勤行情,实现上期所5档行情和指数行情
|
- 增加天勤行情,实现上期所5档行情和指数行情
|
||||||
|
|
||||||
@ -124,8 +124,7 @@ gitee 链接: https://gitee.com/vnpy2/vnpy
|
|||||||
4、 增加App: tick_recorder, 直接异步写入csv文件
|
4、 增加App: tick_recorder, 直接异步写入csv文件
|
||||||
|
|
||||||
|
|
||||||
3、 增加tdx 免费数据源,包括
|
3、 增加t.d.x 免费数据源,包括
|
||||||
|
|
||||||
|
|
||||||
- 提供主力合约/指数合约的信息获取
|
- 提供主力合约/指数合约的信息获取
|
||||||
- 提供期货/股票数据bar 和分笔成交数据下载
|
- 提供期货/股票数据bar 和分笔成交数据下载
|
||||||
|
@ -26,9 +26,9 @@ class Area(Enum):
|
|||||||
# 上期所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~2:30
|
# 上期所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~2:30
|
||||||
NIGHT_MARKET_SQ1 = {'AU': 0.05, 'AG': 1, 'SC': 0.1}
|
NIGHT_MARKET_SQ1 = {'AU': 0.05, 'AG': 1, 'SC': 0.1}
|
||||||
# 上期所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~1:00
|
# 上期所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~1:00
|
||||||
NIGHT_MARKET_SQ2 = {'CU': 10, 'PB': 5, 'AL': 5, 'ZN': 5, 'WR': 1, 'NI': 10}
|
NIGHT_MARKET_SQ2 = {'CU': 10, 'PB': 5, 'AL': 5, 'ZN': 5, 'WR': 1, 'NI': 10, 'SS':5,'BC':10}
|
||||||
# 上期所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~23:00
|
# 上期所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~23:00
|
||||||
NIGHT_MARKET_SQ3 = {'RU': 5, 'RB': 1, 'HC': 1, 'SP': 2, 'FU': 1, 'BU': 2, 'NR': 5, 'C': 1, 'CS': 1, 'LU':1}
|
NIGHT_MARKET_SQ3 = {'RU': 5, 'RB': 1, 'HC': 1, 'SP': 2, 'FU': 1, 'BU': 2, 'NR': 5, 'C': 1, 'CS': 1, 'LU':1,'PF':2}
|
||||||
# 郑商所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~23:00
|
# 郑商所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~23:00
|
||||||
NIGHT_MARKET_ZZ = {'TA': 2, 'JR': 1, 'OI': 0, 'RO': 1, 'PM': 1, 'WH': 1, 'CF': 5, 'SR': 0, 'FG': 1,
|
NIGHT_MARKET_ZZ = {'TA': 2, 'JR': 1, 'OI': 0, 'RO': 1, 'PM': 1, 'WH': 1, 'CF': 5, 'SR': 0, 'FG': 1,
|
||||||
'MA': 1, 'RS': 1, 'RM': 1, 'RI': 1, 'ZC': 0.2}
|
'MA': 1, 'RS': 1, 'RM': 1, 'RI': 1, 'ZC': 0.2}
|
||||||
@ -42,7 +42,7 @@ MARKET_ZJ = {'IC': 0.2, 'IF': 0.2, 'IH': 0.2, 'T': 0.005, 'TF': 0.005, 'TS': 0.0
|
|||||||
# 只有日盘得合约
|
# 只有日盘得合约
|
||||||
MARKET_DAY_ONLY = {'IC': 0.2, 'IF': 0.2, 'IH': 0.2, 'T': 0.005, 'TF': 0.005, 'TS': 0.005,
|
MARKET_DAY_ONLY = {'IC': 0.2, 'IF': 0.2, 'IH': 0.2, 'T': 0.005, 'TF': 0.005, 'TS': 0.005,
|
||||||
'JD': 1, 'BB': 0.05, 'CS': 1, 'FB': 0.05, 'L': 5, 'V': 5,
|
'JD': 1, 'BB': 0.05, 'CS': 1, 'FB': 0.05, 'L': 5, 'V': 5,
|
||||||
'JR': 1, 'LR': 1, 'PM': 1, 'RI': 1, 'RS': 1, 'SM': 2, 'WH': 1, 'AP': 1, 'CJ': 1, 'UR': 1}
|
'JR': 1, 'LR': 1, 'PM': 1, 'RI': 1, 'RS': 1, 'SM': 2, 'WH': 1, 'AP': 1, 'CJ': 1, 'UR': 1,"LH":5,'PK':2}
|
||||||
|
|
||||||
# 夜盘23:00收盘的合约
|
# 夜盘23:00收盘的合约
|
||||||
NIGHT_MARKET_23 = {**NIGHT_MARKET_DL, **NIGHT_MARKET_ZZ, **NIGHT_MARKET_SQ3}
|
NIGHT_MARKET_23 = {**NIGHT_MARKET_DL, **NIGHT_MARKET_ZZ, **NIGHT_MARKET_SQ3}
|
||||||
|
@ -854,7 +854,7 @@ class CtaGridTrade(CtaComponent):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def save(self):
|
def save(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
保存网格至本地Json文件
|
保存网格至本地Json文件
|
||||||
2017/11/23 update: 保存时,空的列表也保存
|
2017/11/23 update: 保存时,空的列表也保存
|
||||||
@ -865,7 +865,9 @@ class CtaGridTrade(CtaComponent):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# 更新开仓均价
|
# 更新开仓均价
|
||||||
|
if not kwargs.get('count_avg_price', True):
|
||||||
self.recount_avg_open_price()
|
self.recount_avg_open_price()
|
||||||
|
|
||||||
grids_save_path = get_folder_path('data')
|
grids_save_path = get_folder_path('data')
|
||||||
|
|
||||||
# 确保json名字与策略一致
|
# 确保json名字与策略一致
|
||||||
@ -893,7 +895,7 @@ class CtaGridTrade(CtaComponent):
|
|||||||
|
|
||||||
self.write_log(u'GrideTrade保存文件{}完成'.format(grid_json_file))
|
self.write_log(u'GrideTrade保存文件{}完成'.format(grid_json_file))
|
||||||
|
|
||||||
def load(self, direction, open_status_filter=[]):
|
def load(self, direction, open_status_filter=[], **kwargs):
|
||||||
"""
|
"""
|
||||||
加载本地Json至网格
|
加载本地Json至网格
|
||||||
:param direction: Direction.SHORT,做空网格;Direction.LONG,做多网格
|
:param direction: Direction.SHORT,做空网格;Direction.LONG,做多网格
|
||||||
@ -950,6 +952,7 @@ class CtaGridTrade(CtaComponent):
|
|||||||
grids.append(grid)
|
grids.append(grid)
|
||||||
|
|
||||||
# 更新开仓均价
|
# 更新开仓均价
|
||||||
|
if not kwargs.get('count_avg_price',True):
|
||||||
self.recount_avg_open_price()
|
self.recount_avg_open_price()
|
||||||
return grids
|
return grids
|
||||||
|
|
||||||
|
@ -152,6 +152,43 @@ class BinanceFutureData(RestClient):
|
|||||||
|
|
||||||
return bars
|
return bars
|
||||||
|
|
||||||
|
def get_fund_rate(self, symbol=""):
|
||||||
|
|
||||||
|
params = {}
|
||||||
|
if symbol:
|
||||||
|
params.update({"symbol": symbol})
|
||||||
|
|
||||||
|
# Get response from server
|
||||||
|
resp = self.request(
|
||||||
|
"GET",
|
||||||
|
"/fapi/v1/premiumIndex",
|
||||||
|
data={},
|
||||||
|
params=params
|
||||||
|
)
|
||||||
|
|
||||||
|
# Break if request failed with other status code
|
||||||
|
if resp.status_code // 100 != 2:
|
||||||
|
msg = f"获取资费失败,状态码:{resp.status_code},信息:{resp.text}"
|
||||||
|
self.write_log(msg)
|
||||||
|
return {} if symbol else []
|
||||||
|
else:
|
||||||
|
datas = resp.json()
|
||||||
|
if not datas:
|
||||||
|
msg = f"获取资费为空"
|
||||||
|
self.write_log(msg)
|
||||||
|
return {} if symbol else []
|
||||||
|
|
||||||
|
if isinstance(datas, list):
|
||||||
|
for d in datas:
|
||||||
|
for k in list(d.keys()):
|
||||||
|
if k in ['nextFundingTime', 'time']:
|
||||||
|
d.update({k: datetime.fromtimestamp(d.get(k) / 1000).strftime('%Y-%m-%d %H:%M:%S')})
|
||||||
|
elif isinstance(datas, dict):
|
||||||
|
for k in list(datas.keys()):
|
||||||
|
if k in ['nextFundingTime', 'time']:
|
||||||
|
datas.update({k: datetime.fromtimestamp(datas.get(k) / 1000).strftime('%Y-%m-%d %H:%M:%S')})
|
||||||
|
return datas
|
||||||
|
|
||||||
def export_to(self, bars, file_name):
|
def export_to(self, bars, file_name):
|
||||||
"""导出bar到文件"""
|
"""导出bar到文件"""
|
||||||
if len(bars) == 0:
|
if len(bars) == 0:
|
||||||
@ -218,6 +255,7 @@ class BinanceFutureData(RestClient):
|
|||||||
contracts = load_json(f, auto_save=False)
|
contracts = load_json(f, auto_save=False)
|
||||||
return contracts
|
return contracts
|
||||||
|
|
||||||
|
|
||||||
def save_contracts(self):
|
def save_contracts(self):
|
||||||
"""保存合约配置"""
|
"""保存合约配置"""
|
||||||
contracts = self.get_contracts()
|
contracts = self.get_contracts()
|
||||||
|
@ -191,8 +191,11 @@ class TdxFutureData(object):
|
|||||||
if last_datetime_str:
|
if last_datetime_str:
|
||||||
try:
|
try:
|
||||||
last_datetime = datetime.strptime(last_datetime_str, '%Y-%m-%d %H:%M:%S')
|
last_datetime = datetime.strptime(last_datetime_str, '%Y-%m-%d %H:%M:%S')
|
||||||
if (datetime.now() - last_datetime).total_seconds() > 60 * 60 * 2:
|
ip = self.best_ip.get('ip')
|
||||||
|
is_bad_ip = ip and ip in self.best_ip.get('exclude_ips',[])
|
||||||
|
if (datetime.now() - last_datetime).total_seconds() > 60 * 60 * 2 or is_bad_ip :
|
||||||
self.best_ip = {}
|
self.best_ip = {}
|
||||||
|
if not is_bad_ip:
|
||||||
self.exclude_ips = []
|
self.exclude_ips = []
|
||||||
except Exception as ex: # noqa
|
except Exception as ex: # noqa
|
||||||
self.best_ip = {}
|
self.best_ip = {}
|
||||||
|
@ -60,7 +60,8 @@ STATUS_BINANCEF2VT: Dict[str, Status] = {
|
|||||||
|
|
||||||
ORDERTYPE_VT2BINANCEF: Dict[OrderType, str] = {
|
ORDERTYPE_VT2BINANCEF: Dict[OrderType, str] = {
|
||||||
OrderType.LIMIT: "LIMIT",
|
OrderType.LIMIT: "LIMIT",
|
||||||
OrderType.MARKET: "MARKET"
|
OrderType.MARKET: "MARKET",
|
||||||
|
OrderType.STOP: "STOP_MARKET"
|
||||||
}
|
}
|
||||||
ORDERTYPE_BINANCEF2VT: Dict[str, OrderType] = {v: k for k, v in ORDERTYPE_VT2BINANCEF.items()}
|
ORDERTYPE_BINANCEF2VT: Dict[str, OrderType] = {v: k for k, v in ORDERTYPE_VT2BINANCEF.items()}
|
||||||
|
|
||||||
@ -172,7 +173,7 @@ class BinancefGateway(BaseGateway):
|
|||||||
self.status.update({'con': True})
|
self.status.update({'con': True})
|
||||||
|
|
||||||
self.count += 1
|
self.count += 1
|
||||||
if self.count < 2:
|
if self.count < 60:
|
||||||
return
|
return
|
||||||
self.count = 0
|
self.count = 0
|
||||||
if len(self.query_functions) > 0:
|
if len(self.query_functions) > 0:
|
||||||
|
@ -198,7 +198,7 @@ class BinanceoGateway(BaseGateway):
|
|||||||
self.status.update({'con': True})
|
self.status.update({'con': True})
|
||||||
|
|
||||||
self.count += 1
|
self.count += 1
|
||||||
if self.count < 2:
|
if self.count < 60:
|
||||||
return
|
return
|
||||||
self.count = 0
|
self.count = 0
|
||||||
if len(self.query_functions) > 0:
|
if len(self.query_functions) > 0:
|
||||||
|
@ -608,10 +608,10 @@ def save_images_to_excel(file_name, sheet_name, image_names):
|
|||||||
print(u'save_images_to_excel exception:{}'.format(str(ex)), traceback.format_exc(), file=sys.stderr)
|
print(u'save_images_to_excel exception:{}'.format(str(ex)), traceback.format_exc(), file=sys.stderr)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def display_dual_axis(df, columns1, columns2=[], invert_yaxis1=False, invert_yaxis2=False, file_name=None,
|
def display_dual_axis(df, columns1, columns2=[], invert_yaxis1=False, invert_yaxis2=False, file_name=None,
|
||||||
sheet_name=None,
|
sheet_name=None,
|
||||||
image_name=None):
|
image_name=None,
|
||||||
|
label_column='index'):
|
||||||
"""
|
"""
|
||||||
显示(保存)双Y轴的走势图
|
显示(保存)双Y轴的走势图
|
||||||
:param df: DataFrame
|
:param df: DataFrame
|
||||||
@ -622,6 +622,7 @@ def display_dual_axis(df, columns1, columns2=[], invert_yaxis1=False, invert_yax
|
|||||||
:param file_name: 保存的excel 文件名称
|
:param file_name: 保存的excel 文件名称
|
||||||
:param sheet_name: excel 的sheet
|
:param sheet_name: excel 的sheet
|
||||||
:param image_name: 保存的image 文件名
|
:param image_name: 保存的image 文件名
|
||||||
|
:param label_cloumn: 显示在x轴的label所在字段,例如 df的index,或者 'datetime'
|
||||||
颜色色系:https://www.osgeo.cn/matplotlib/tutorials/colors/colormaps.html
|
颜色色系:https://www.osgeo.cn/matplotlib/tutorials/colors/colormaps.html
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
@ -648,7 +649,8 @@ def display_dual_axis(df, columns1, columns2=[], invert_yaxis1=False, invert_yax
|
|||||||
|
|
||||||
# 修改x轴得label为时间
|
# 修改x轴得label为时间
|
||||||
xt = ax1.get_xticks()
|
xt = ax1.get_xticks()
|
||||||
xt2 = [df.index[int(i)] for i in xt[1:-2]]
|
label_values = df.index.values if label_column == 'index' else df[label_column].values
|
||||||
|
xt2 = [label_values[int(i)] for i in xt[1:-2]]
|
||||||
xt2.insert(0, '')
|
xt2.insert(0, '')
|
||||||
xt2.append('')
|
xt2.append('')
|
||||||
ax1.set_xticklabels(xt2)
|
ax1.set_xticklabels(xt2)
|
||||||
|
Loading…
Reference in New Issue
Block a user