输入/搜索内容
内置函数
结构体
内置变量与常量
通用约定
交易所
能力矩阵
中心化交易所
去中心化交易所
预测市场
证券与期货
富途证券
盈透证券
链上与自定义接入

通过TWS API(socket协议)直连托管者所在机器上运行的「IB Gateway」或「TWS(Trader Workstation)」,交易盈透证券账户中的股票、期货、期权等。以TWS为例:登录后点击右上角的配置按钮,选择「配置」→「API」→「设置」,不要勾选「只读API」,勾选「启用ActiveX和套接字客户端」,并记下「套接字端口」(TWS默认实盘7496、模拟盘7497;IB Gateway默认实盘4001、模拟盘4002),填入交易所配置的服务器地址。鉴权在TWS或IB Gateway的登录状态中完成,交易所配置不需要密钥。

名称与配置

exchange.GetName():Futures_IB(证券与期货);别名:IB、盈透。

配置项必填默认值说明
服务器地址是localhost:7496TWS或IB Gateway的API地址和端口,例如localhost:7496。
行情类型是1实时数据、冻结数据、延迟数据、延迟冻结数据之一。没有订阅实时行情的账户可以选择延迟数据。运行中可用exchange.IO("marketDataType", n)切换。可选:实时数据、冻结数据、延迟数据、延迟冻结数据

交易对与合约代码

交易对示例:AAPL.US、TSLA.US

用exchange.SetContractType()(或exchange.SetCurrency())设置,交易所对象配置的交易对就是初始品种。格式为代码.货币[.类型[.交易所]],类型缺省为股票STK,交易所缺省为SMART,整串作为一个品种:

  • 美股:AAPL.US、TSLA.US(US表示美元计价,HK表示港币计价,其它货币直接写货币代码)。
  • 期货(FUT):代码-到期月份[-乘数].货币.FUT.交易所,到期月份写成YYYYMM,交易所为IB的交易所代码。
  • 期权(OPT)与期货期权(FOP):代码-到期-C或P-行权价×100[-乘数].货币.OPT或FOP.交易所,行权价乘以100后写成整数。
  • 纯数字:直接作为IB的合约ID(conId)。

持仓、订单的Symbol是简写形式(如Z74.SGD),exchange.GetPositions()、exchange.GetOrders()传入简写或下单时用的完整代码(如Z74.SGD.STK.SGX)都可以。

exchange.SetContractType()向网关查询合约详情并返回,包括InstrumentID、PriceTick、VolumeMultiple(乘数,股票为1)、TradingHours、LiquidHours、IsTrading等;IsTrading按交易时段判断当前是否在交易,第二个参数传liquid时改按流动性时段判断。

专属IO指令
指令参数说明
status—与TWS/IB Gateway的会话是否已建立(不主动建立连接)。
time—获取IB服务器时间(毫秒时间戳)。
accounts—获取托管账户(账户号)列表。
reqId—分配一个新的请求ID(每次递增)。
orderId—取出下一个可用订单ID并占用它,之后托管者下单不再使用这个号,可用于api指令直接下单。
ignorecodes设置同步请求时忽略的TWS错误码(整表替换,传空数组清空),参数为错误码数组或数组的JSON字符串。2100到2200段的通知以及10167、399本来就不中止请求。返回:设置后的错误码列表(升序、去重)。
scanobject执行市场扫描器,参数为扫描订阅字段(对象或JSON字符串,键名同旧版ScannerSubscription,如Instrument、LocationCode、ScanCode、NumberOfRows、AbovePrice),必须包含Instrument,例如STK配合LocationCode为STK.US.MAJOR;ScanCode缺省为HOT_BY_VOLUME。(详见表下)
wait[number]等待并返回TWS/IB Gateway发来的下一条完整消息;参数为超时毫秒数(最多600秒),负数表示不等待,0或不传最多等30秒,超时返回空值。返回:{id, fields},id为TWS消息ID,fields为其余字段的字符串数组。
debug[bool]查询或设置调试模式:开启后把与TWS/IB Gateway收发的每一帧按TWS API日志的格式(每帧最多512字节)写入托管者的标准输出日志,不显示在机器人日志中。返回:当前的调试模式(true/false)。
marketDataTypenumber切换行情数据类型(1实时、2冻结、3延迟、4延迟冻结)。返回:true
apimsgId, ...fields | name[, params[, filterMsgId[, timeout]]]发送原始TWS消息:exchange.IO("api", 消息ID, 字段...)发送后返回true。(详见表下)

表中长说明的其余部分:

  • scan:返回:扫描结果数组,每项{rank, symbol, conId, secType, exchange, currency, localSymbol, tradingClass, marketName, ...},symbol是可以直接传给exchange.SetContractType()的品种代码(如AAPL.US)。
  • api:也可以按旧版写法exchange.IO("api", 请求名或消息ID, 参数数组, 等待的消息ID, 超时秒数)调用(请求名如PlaceOrder、CancelOrder,参数数组可以是JSON字符串):不给等待的消息ID时发送后返回true;给了就返回从发送到收到该消息ID为止的所有消息,每条为去掉消息ID后的字段字符串数组。

通用指令base、currency见exchange.IO。

常用用法
检查与网关的会话,读取服务器时间和托管账户
javascript
function main() { // status 不主动建立连接:第一次请求之前为 false Log("会话已建立:", exchange.IO("status")) var t = exchange.IO("time") // 毫秒时间戳,这次请求会建立会话 Log("IB服务器时间:", _D(t), "与本机相差(毫秒):", t - Date.now()) Log("托管账户:", exchange.IO("accounts")) // 下单默认用第一个 Log("会话已建立:", exchange.IO("status")) }
用市场扫描器选出涨幅榜股票,再取行情
javascript
function main() { var rows = exchange.IO("scan", { Instrument: "STK", LocationCode: "STK.US.MAJOR", ScanCode: "TOP_PERC_GAIN", NumberOfRows: 10, AbovePrice: 5 }) if (!rows) { Log("扫描失败:", GetLastError()) return } rows.forEach(function (r) { Log(r.rank, r.symbol, "conId:", r.conId, r.exchange, r.currency) }) // symbol 可以直接用作品种代码 exchange.SetContractType(rows[0].symbol) Log(rows[0].symbol, exchange.GetTicker()) }
没有实时行情订阅时改用延迟行情,忽略部分行情未订阅的错误
javascript
function main() { exchange.IO("marketDataType", 3) // 1实时、2冻结、3延迟、4延迟冻结 // 10090(部分行情未订阅)不再中止请求;整表替换,返回设置后的列表 Log("忽略的错误码:", exchange.IO("ignore", [10090])) exchange.SetContractType("AAPL.US") Log(exchange.GetTicker()) exchange.IO("ignore", []) // 清空 }
发送原始TWS请求,收集应答或用wait逐条读取消息
javascript
function main() { exchange.IO("debug", true) // 收发的每一帧写入托管者标准输出日志 // 旧版命名调用:ReqMktData 快照请求,收集消息直到 tickSnapshotEnd(消息ID 57),最多10秒 var id = exchange.IO("reqId") var msgs = exchange.IO("api", "ReqMktData", [id, "AAPL.US", "", true, false], 57, 10) if (msgs) { Log("收到", msgs.length, "条消息(不含消息ID):", msgs) } // 原始帧:消息ID 49(reqCurrentTime,版本 1),发送后返回 true exchange.IO("api", 49, 1) while (true) { var m = exchange.IO("wait", 5000) if (!m) { Log("5秒内没有消息") break } if (m.id == 49) { Log("服务器时间(秒):", m.fields[1]) // fields[0] 是消息版本 break } Log("其它消息:", m.id, m.fields) } exchange.IO("debug", false) }

函数支持差异

不支持(调用时报错并返回空值):exchange.GetTrades、exchange.GetHistoryOrders、exchange.GetFundings、exchange.SetMarginLevel、exchange.ModifyOrder、exchange.CreateConditionOrder、exchange.ModifyConditionOrder、exchange.CancelConditionOrder、exchange.GetConditionOrder、exchange.GetConditionOrders、exchange.GetHistoryConditionOrders。

以回退方式支持:

  • exchange.GetRecords:原生周期为1分钟、3分钟、5分钟、15分钟、30分钟、1小时、2小时、4小时、6小时、1天、1周;其它60秒整数倍的周期由托管者用原生K线合成,其余周期(如秒级)不可用(本交易所对象不支持exchange.GetTrades())。

保证金、账户与模拟盘

账户:使用TWS/IB Gateway登录的第一个托管账户。exchange.GetAssets()按币种返回各币种的净清算值(NetLiquidationByCurrency,没有时取该币种的现金余额),冻结数量为0;exchange.GetAccount()的Balance与Equity为账户基础币种计的净清算总值,Info中有TWS下发的全部账户值。exchange.GetPositions()的Price为每单位均价(期货、期权的平均成本已除以合约乘数,原值见Info中的AvgCost),Profit为0(IB持仓查询不提供浮动盈亏)。

注意事项
  • 托管者以实盘ID作为连接TWS的客户端号(clientId),实盘重启后客户端号不变,仍可撤销此前挂出的订单。TWS只允许订单的原始客户端号(或主客户端)撤销订单。exchange.GetOrders()返回网关上全部未完成的订单(不传品种时为所有合约);exchange.GetOrder()只能查到当前未完成的订单和本次运行中见过的订单,此前已完结的订单查不到。订单的Time为0(TWS的订单回报不带下单时间)。
  • 行情为快照:exchange.GetDepth()只有买一、卖一一档,没有有效买卖价时报错;exchange.GetTickers()返回本次运行中已经使用过的合约的行情,既没有最新价也没有昨收价的合约不列出。美股exchange.GetTicker()的Volume已由TWS的手数(100股)换算成股数。
  • exchange.GetMarkets()通过市场扫描器(STK、STK.US.MAJOR、按成交量排序的HOT_BY_VOLUME)取得合约列表,再逐个查询合约详情取精度,只包含扫描结果中的合约。
  • 下单数量是股数(期货、期权为张数),不是金额;价格传-1或0时按市价单(MKT)提交。默认GTC,下单函数最后的选项对象可传{tif: "ioc"}或{tif: "fok"},不支持postOnly;选项对象中outsideRth: true允许在常规交易时段以外成交(默认不允许),account指定下单账户。
  • closebuy、closesell只是按反方向(卖出、买入)下单,没有只减仓保证:没有对应持仓时会开出反向仓位。
  • 订单被网关拒绝时,订单Info中的Reject字段记录拒单原因。