当前位置: 首页 > news >正文

Python美股量化交易填坑记录——3.盈透(Interactive Brokers)证券API接口

Python美股量化交易填坑记录——3.盈透(Interactive Brokers)证券API接口

ChristopherShen

ChristopherShen

​​编辑

北京师范大学 心理学硕士

收录于 · 全球网络券商大全 - 盈透证券

74 人赞同了该文章

之前的2篇帖子介绍了德美利(TD Ameritrade)接口:

行情接口:https://zhuanlan.zhihu.com/p/386828885

交易接口:https://zhuanlan.zhihu.com/p/386870269

现在介绍盈透的API接口。

个人认为盈透的优势有:

  • 老牌券商,各方面的体系完善,信誉好。
  • 佣金相对较低,虽然不能跟免佣券商德美利、第一证券、尊嘉、羊驼、微牛)比,但比起富途和老虎,还是很良心的了。
  • 盘前交易时段从美东时间4:00a.m.开始,这一点大部分免佣券商都做不到(尊嘉除外)
  • 接受中国大陆的注册。
  • API历史数据全。(我曾成功下载过SPY过去20年的15分钟k线数据)
  • 融资利率低(年化不到2%:https://www.interactivebrokers.com/cn/index.php?f=2365)。
  • 使用盈透的量化交易者很多,方便初学者求助,比如vnpy(其实给我的体验不太好)。

劣势也很明显:

  • 不免佣。
  • 实时行情需付费购买。
  • API接口不能脱离笨重的客户端。
  • 安全机制很繁琐。

1.前期准备

  • 申请一个新用户。默认情况下,一个人只有一个账号和一个用户身份。但其实一个账号下可以有多个用户。因为我的需求是手机和机器人同时在线查看盈透行情和下单,所以我需要2个用户身份,否则后上线的设备会把先上线的设备踢下线。发起申请的位置在:管理账户→使用者及访问权限→配置→使用者→添加。等待1个工作日后,新用户生效。(备注:新用户的行情权限需单独购买)
  • 购买实时行情。入口在:使用者设置→交易平台→市场数据订阅→配置→当前GFIS订阅→配置。下图是我目前购买的行情,一共每月7.25刀。API接口的行情权限不用再单独购买(富途需单独购买:60刀/月,很坑!)。

美股各大指数的行情需单独购买,比如CBOE提供标普和道指,3.5刀每月。

Indices - North America

  • 下载客户端(win/mac/linux)。比较坑的一点是:如果是linux系统,则必须有图形界面才能安装盈透客户端。所以我目前配置了一台Windows Server 2019的服务器(2G内存都卡!真是笨重!)来安装盈透客户端。盈透客户端有2种:一种是功能比较全的TWS(Trader Workstation),另一种是相对轻便的IB网关(IB Gateway)。(备注:客户端若使用中文,则会导致API报错,建议使用默认的英文界面)
  • 安装python包:ib_insync。和德美利的情况类似,官网的API文档晦涩难懂,所以某些技术大牛制作了简易的python包。此包的论坛:https://groups.io/g/insync,我在这里得到了很多帮助!此包的简介:https://github.com/erdewit/ib_insync,此包的详细说明文档:https://ib-insync.readthedocs.io/readme.html
pip install ib_insync

2.连接客户端

德美利的第一步是连接服务器,而盈透的客户端已经连接服务器了,所以我们只需要连接客户端就行。

 from ib_insync import *ib = IB()ib.connect('127.0.0.1', 7496, clientId=991)

上面的端口号(7496)和客户ID(991),需要在客户端中设置,位置是:File→Global Configuration→API→settings,第一项(Enable ActiveX and Socket Clients)要勾选,Read-Only API的勾要去掉,Socket port处我填入7496(可以自定义,之后保持一致就好),Master API client ID处我填入999,即上面代码的客户ID不是主客户ID,但也可以使用,我这么做是因为我为不同的机器人分配了不同的客户ID。


3.行情接口

与德美利机器人的思路一样,行情接口依旧分为策略机器人(下单机器人)与询价机器人(行情机器人)两部分,前者与德美利的策略机器人一样(通过csv发送股票代码给询价机器人,然后从csv中读取询价机器人的询价结果)。(备注:两个机器人必须使用不同的clientId,否则会有冲突)

下面重点介绍盈透的询价机器人:

slm_ib_high()负责在盘前查询昨日的最高价,它的参数contract1下面再讲。它核心的ib.reqHistoricalData()在调取历史数据时会很常用。

def slm_ib_high(contract1):is_error=1while is_error==1:try:x1=ib.reqHistoricalData(contract1,endDateTime='',durationStr='1 D',barSizeSetting='1 day',whatToShow='TRADES',useRTH=True)x2=x1[0]x3=x2.highexcept:Log('slm_ib_high出错,等待2秒后重算!@','#FF0000')Sleep(2000)else:is_error=0return(x3)

slm_ib_reqMktData()负责对读取的待查询股票进行逐一查询,并将股价导出至csv,供策略机器人使用,即整体思路与德美利机器人一致。这里需要重点说明的是,盈透接口查询股价时,只是提供股票代码是不够的,还必须提供交易所代码(下文主要使用'SMART')和货币币种(下文使用'USD'),三者组合成为一个合约,即contract1 。

def slm_ib_reqMktData(stock_list=stock_list):x=slm_read_csv()date1=x[0]stock_list=x[1]n0=len(stock_list)Log('n=',n0,';stock_list=',stock_list)for i in range(n0): # 逐个标的地进行订阅和输出code_ob=stock_list[i]Log('i=',i,',code_ob=',code_ob)is_qihuo=1     if '/' in code_ob else 0is_option_ob=1 if '@' in code_ob or '_' in code_ob else 0# 定义合约:if '@' in code_ob:n = len(code_ob) + 1m = code_ob.find('@')code_symbol = code_ob[0:m]code_date = code_ob[(m + 1):(m + 9)]code_callput = code_ob[(m + 9):(m + 10)]code_price = code_ob[(m + 10):n]contract1 = Option(code_symbol, code_date, code_price, code_callput, 'SMART')elif '_' in code_ob:slm_create_one_error('期权非尊嘉格式,请更正!')elif '/' in code_ob:code_ob2=code_ob[1:]cds = ib.reqContractDetails(Future(code_ob2,currency='USD',exchange='NYMEX'))df0=util.df(cds).sort_values('contractMonth')df1=df0.reset_index(drop=True)contract1=df1.contract[1]else:contract1 = Stock(code_ob, 'SMART', 'USD')# 检查合约:ib.qualifyContracts(contract1)# 提交订阅:ib.reqMktData(contract1)ib.sleep(1)# 获取订阅结果:ticker1 = ib.ticker(contract1)Log(ticker1)# 处理订阅结果:t1=ticker1.time.timestamp()import numpy as npbidPrice=np.nan_to_num(ticker1.bid) # 买一价askPrice=np.nan_to_num(ticker1.ask) # 卖一价lastPrice=np.nan_to_num(ticker1.last)highPrice=np.nan_to_num(ticker1.high)while highPrice<=0:Log('行情异常:highPrice=',highPrice,'!')if is_option_ob==0 and is_qihuo==0 :Log('使用reqHistoricalData,获取昨日最高价!')highPrice=slm_ib_high(contract1=contract1)else:Log('期权和期货不可用reqHistoricalData,等待开盘,5秒后再用reqMktData……')Sleep(5000)ib.reqMktData(contract1)ib.sleep(1)ticker1 = ib.ticker(contract1)t1=ticker1.time.timestamp()bidPrice=np.nan_to_num(ticker1.bid) # 买一价askPrice=np.nan_to_num(ticker1.ask) # 卖一价highPrice=np.nan_to_num(ticker1.high)y={'code': code_ob,'timestamp':t1, 'BID_PRICE': bidPrice, 'ASK_PRICE': askPrice, 'LAST_PRICE': lastPrice, 'HIGH_PRICE': highPrice}import pandas as pdy1 = pd.DataFrame(y, index=[0])code_ob2=code_ob[1:] if is_qihuo==1 else code_obLog('code_ob2=', code_ob2)y1.to_csv(wd1+'/fmz/price/'+ date1 + '_' + code_ob2 + '.csv', index=False)Log(code_ob,'导出到csv的价格:',y)t2=pd.to_datetime(t1, unit='s', utc=True).tz_convert('US/Eastern')t3=str(t2)[:19]y1['datetime']=t3columns=y1.columns.values.tolist()row1=y1[:1].values.tolist()if i==0: rows=row1else: rows=rows+row1return([columns,rows])

就我目前的使用感受来说,盈透接口的稳定性还是要强于德美利的,但也不是完美无瑕,还是有一些不稳定的地方,之后我会加一些try进来。


4.交易接口

slm_buy_sell_ib()负责根据用户输入的价格p_ex和数量amount_ex进行买入或卖出的操作action。跟行情接口一样,需要先把标的调整为合约格式,使用Stock()或Option()。而且需要指定订单ID,为避免订单ID重复,我这里简单使用了一个当前时间的“时分秒+毫秒”的十位数字。

def slm_buy_sell_ib(action, amount_ex, p_ex):# 调整标的格式:if is_option == 1:if '@' in code_ex:n = len(code_ex) + 1m = code_ex.find('@')code_symbol = code_ex[0:m]code_date = code_ex[(m + 1):(m + 9)]code_callput = code_ex[(m + 9):(m + 10)]code_price = code_ex[(m + 10):n]contract1 = Option(code_symbol, code_date, code_price, code_callput, 'SMART')else:slm_create_one_error('期权非尊嘉格式,请更正!')elif is_option == 0: contract1 = Stock(code_ex, 'SMART', 'USD')else: slm_create_one_error('盈透code_ex类型错误!')ib.qualifyContracts(contract1)# 设置订单:order1_id=slm_time_num()if p_ex == -1:order1=MarketOrder(action, totalQuantity=amount_ex, lmtPrice=p_ex, orderId=order1_id, outsideRth=False, tif='GTC',usePriceMgmtAlgo=True)elif p_ex > 0:order1=LimitOrder( action, totalQuantity=amount_ex, lmtPrice=p_ex, orderId=order1_id, outsideRth=True,  tif='GTC',usePriceMgmtAlgo=True)else:slm_create_one_error('盈透p_ex错误!')# 下单:trade1 = ib.placeOrder(contract1, order1)Sleep(2000)  # 等2秒再检查订单状态ib.sleep(1)# 查询订单状态:order1_status=0while order1_status == 0:x1 = ib.trades()for i in range(len(x1)):x2=x1[i]order_id_i=x2.orderStatus.orderIdif order_id_i==order1_id :order1_status_str=x2.orderStatus.statusLog('订单状态为:', order1_status_str)if order1_status_str == 'Filled':Log('订单已成交!')order1_status=1breakLog('订单编号为:', order1_id, ',交易不成功,等5秒再查订单状态……')Sleep(5000)ib.sleep(1)if order1_status == 1:Log('订单编号为:', order1_id, ',交易成功!', '#00FF00')else:Log('订单编号为:', order1_id, ',订单异常,请立即查找原因!@', '#FF0000')return (order1_id)

备注:

除了本文使用的ib_insync包外,盈透还有一款比较有名的python包:IbPy2。但因为已经停止维护和更新了,所以本文并未介绍。感兴趣的同学可以参考如下资料:

blampe/IbPy

量化交易30天 Day14 - 串接券商API做交易(一) IB + IbPy - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天

Python股票自动交易从零开始~第十集~交易自动操作~美股_哔哩哔哩_bilibili

下一篇帖子将介绍羊驼的行情接口(https://alpaca.markets/data)。

http://www.dtcms.com/a/453987.html

相关文章:

  • 网站有访问量 为什么没有询盘淘宝客的网站怎么做的
  • 力扣:9.回文数の题解
  • 北京做兼职网站浙江省龙泉市建设局网站
  • UE5 小知识点 —— 11 - 下坠
  • 网站的二次开发是什么意思高端网站建设加盟
  • TCN (时序卷积网络) 从零实现
  • 基于视觉摄像头的人体动作识别技术详解
  • 快速了解并使用pandas库
  • 生成式人工智能在教育中的应用:法律挑战、伦理困境与综合治理框架
  • 电商网站会员体制怎么做零基础学网页设计
  • 网站推广的方法及技巧百度竞价ocpc
  • 如何部署thinkphp网站北京王府井美食
  • 网站后台使用网站pv uv是什么意思
  • Blender体积烟雾云团火焰毒雾电能生成器资产预设 Physical Volume Generator v1.1 (1)
  • C++网络编程(三)TCP通信流程
  • iBizModel 属性界面模式(PSDEFUIMODE)与属性搜索模式(PSDEFSFITEM)模型详解
  • 屏幕分辨率统计
  • 上海服装品牌网站建设30张女性人像摄影作品欣赏
  • 小迪Web自用笔记58
  • 云南省建设工程质量协会网站app怎么开发制作
  • 做淘宝优惠网站北京公司请做网站工资
  • 专业的单位网站开发网页制作开发
  • dhcp enable 概念及题目
  • 北京市政建设集团有限责任公司网站文化传播 wordpress
  • 【AI超级个体】AI-Native 能力思考(二):从“方案提供者”到“成果交付者”
  • 成为超人 33:人生指南针
  • 东莞网站设计与制作公司2022年卡一卡二卡三精品
  • 常见反爬虫策略与破解方案汇总
  • 没域名 打开网站自己制作网页的步骤
  • Java---注解