futu-sdk
Version:
futu-api 的高性能精简易用版;基于*.proto静态编译,提供高性能的多层封装但层层开放的易用接口,获取最原始最完整的量化数据;相较于Python, nodejs更接近Web, 从而轻而易举搭建一个可视化交易站点,这是进行可控量化交易的不二选择。
342 lines (326 loc) • 18.6 kB
text/typescript
import * as proto from 'futu-proto';
import REQ from './req';
import SUB from './sub';
export type Message = { protobuf: Uint8Array; errorCode: number; errorMessage: string };
export type ReqFn = (cmd: number, buf: Uint8Array, callback: (message: Message) => void) => () => void;
export type SubFn = (cmd: number, callback: (message: Message) => void) => () => void;
const decodeMessage = ({ protobuf, errorCode, errorMessage }: Message, decode: (protobuf: Uint8Array) => any) => {
if (errorCode) {
throw new Error(`errorCode: ${errorCode}, errorMessage: ${errorMessage}`);
}
const { s2c, retMsg, retType } = decode(protobuf);
if (retType) {
throw new Error(`retType: ${retType}, retMsg: ${retMsg}`);
}
return s2c;
};
export class WebRequest {
private reqFn: (cnd: (typeof REQ)[keyof typeof REQ], req: any, timeout?: number) => Promise<any>;
private subFn: (cnd: (typeof SUB)[keyof typeof SUB], callback: (res: any) => void) => () => void;
constructor(reqFn: Promise<ReqFn>, subFn: SubFn) {
this.reqFn = ({ name, cmd, description }, req, timeout = 5000) => {
return new Promise<any>(async (resolve, reject) => {
const buf = name.Request.encode(name.Request.create(req) as any).finish();
const unsubscribe = (await reqFn)(cmd, buf, message => {
try {
resolve(decodeMessage(message, name.Response.decode));
} catch ({ message }: any) {
reject(new Error(`${description}, ${message}`));
} finally {
clearTimeout(id);
unsubscribe();
}
});
const id = setTimeout(() => {
reject(new Error(`${description} timeout`));
unsubscribe();
}, timeout);
});
};
this.subFn = ({ name, cmd, description }, callback) => {
return subFn(cmd, message => {
try {
callback(decodeMessage(message, name.Response.decode));
} catch ({ message }: any) {
console.error(`${description}, ${message}`);
}
});
};
}
/** 初始化连接 */
InitWebSocket = (c2s: proto.InitWebSocket.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.InitWebSocket.IResponse['s2c']>> => {
return this.reqFn(REQ.InitWebSocket, { c2s }, timeout);
};
/** 请求全局状态 */
GetGlobalState = (c2s: proto.GetGlobalState.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.GetGlobalState.IResponse['s2c']>> => {
return this.reqFn(REQ.GetGlobalState, { c2s }, timeout);
};
/** 心跳 */
KeepAlive = (c2s: proto.KeepAlive.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.KeepAlive.IResponse['s2c']>> => {
return this.reqFn(REQ.KeepAlive, { c2s }, timeout);
};
/** 获取用户信息 */
GetUserInfo = (c2s: proto.GetUserInfo.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.GetUserInfo.IResponse['s2c']>> => {
return this.reqFn(REQ.GetUserInfo, { c2s }, timeout);
};
/** 获取延迟统计 */
GetDelayStatistics = (c2s: proto.GetDelayStatistics.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.GetDelayStatistics.IResponse['s2c']>> => {
return this.reqFn(REQ.GetDelayStatistics, { c2s }, timeout);
};
/** 订阅或者反订阅 */
Sub = (c2s: proto.Qot_Sub.IRequest['c2s']): Promise<NonNullable<proto.Qot_Sub.IResponse['s2c']>> => {
return this.reqFn(REQ.QotSub, { c2s });
};
/** 注册推送 */
RegQotPush = (c2s: proto.Qot_RegQotPush.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_RegQotPush.IResponse['s2c']>> => {
return this.reqFn(REQ.QotRegQotPush, { c2s }, timeout);
};
/** 获取订阅信息 */
GetSubInfo = (c2s: proto.Qot_GetSubInfo.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetSubInfo.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetSubInfo, { c2s }, timeout);
};
/** 获取基本行情 */
GetBasicQot = (c2s: proto.Qot_GetBasicQot.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetBasicQot.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetBasicQot, { c2s }, timeout);
};
/** 获取K线 */
GetKL = (c2s: proto.Qot_GetKL.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetKL.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetKL, { c2s }, timeout);
};
/** 获取分时 */
GetRT = (c2s: proto.Qot_GetRT.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetRT.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetRT, { c2s }, timeout);
};
/** 获取逐笔 */
GetTicker = (c2s: proto.Qot_GetTicker.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetTicker.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetTicker, { c2s }, timeout);
};
/** 获取摆盘 */
GetOrderBook = (c2s: proto.Qot_GetOrderBook.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetOrderBook.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetOrderBook, { c2s }, timeout);
};
/** 获取经纪队列 */
GetBroker = (c2s: proto.Qot_GetBroker.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetBroker.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetBroker, { c2s }, timeout);
};
/** 获取历史K线 */
GetHistoryKL = (c2s: proto.Qot_GetHistoryKL.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetHistoryKL.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetHistoryKL, { c2s }, timeout);
};
/** 获取多只股票历史单点K线 */
GetHistoryKLPoints = (c2s: proto.Qot_GetHistoryKLPoints.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetHistoryKLPoints.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetHistoryKLPoints, { c2s }, timeout);
};
/** 获取复权信息 */
GetRehab = (c2s: proto.Qot_GetRehab.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetRehab.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetRehab, { c2s }, timeout);
};
/** 在线拉取历史K线,不读本地历史数据DB */
RequestHistoryKL = (c2s: proto.Qot_RequestHistoryKL.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_RequestHistoryKL.IResponse['s2c']>> => {
return this.reqFn(REQ.QotRequestHistoryKL, { c2s }, timeout);
};
/** 拉取历史K线已经用掉的额度 */
RequestHistoryKLQuota = (c2s: proto.Qot_RequestHistoryKLQuota.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_RequestHistoryKLQuota.IResponse['s2c']>> => {
return this.reqFn(REQ.QotRequestHistoryKLQuota, { c2s }, timeout);
};
/** 在线拉取复权信息,不读本地历史数据DB */
RequestRehab = (c2s: proto.Qot_RequestRehab.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_RequestRehab.IResponse['s2c']>> => {
return this.reqFn(REQ.QotRequestRehab, { c2s }, timeout);
};
/** 获取股票停牌信息 */
GetSuspend = (c2s: proto.Qot_GetSuspend.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetSuspend.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetSuspend, { c2s }, timeout);
};
/** 获取静态信息 */
GetStaticInfo = (c2s: proto.Qot_GetStaticInfo.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetStaticInfo.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetStaticInfo, { c2s }, timeout);
};
/** 获取股票快照 */
GetSecuritySnapshot = (c2s: proto.Qot_GetSecuritySnapshot.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetSecuritySnapshot.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetSecuritySnapshot, { c2s }, timeout);
};
/** 获取板块集合下的板块 */
GetPlateSet = (c2s: proto.Qot_GetPlateSet.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetPlateSet.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetPlateSet, { c2s }, timeout);
};
/** 获取板块下的股票 */
GetPlateSecurity = (c2s: proto.Qot_GetPlateSecurity.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetPlateSecurity.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetPlateSecurity, { c2s }, timeout);
};
/** 获取相关股票 */
GetReference = (c2s: proto.Qot_GetReference.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetReference.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetReference, { c2s }, timeout);
};
/** 获取股票所属的板块 */
GetOwnerPlate = (c2s: proto.Qot_GetOwnerPlate.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetOwnerPlate.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetOwnerPlate, { c2s }, timeout);
};
/** 获取大股东持股变化列表 */
GetHoldingChangeList = (c2s: proto.Qot_GetHoldingChangeList.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetHoldingChangeList.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetHoldingChangeList, { c2s }, timeout);
};
/** 筛选期权 */
GetOptionChain = (c2s: proto.Qot_GetOptionChain.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetOptionChain.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetOptionChain, { c2s }, timeout);
};
/** 筛选窝轮 */
GetWarrant = (c2s: proto.Qot_GetWarrant.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetWarrant.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetWarrant, { c2s }, timeout);
};
/** 获取资金流向 */
GetCapitalFlow = (c2s: proto.Qot_GetCapitalFlow.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetCapitalFlow.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetCapitalFlow, { c2s }, timeout);
};
/** 获取资金分布 */
GetCapitalDistribution = (c2s: proto.Qot_GetCapitalDistribution.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetCapitalDistribution.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetCapitalDistribution, { c2s }, timeout);
};
/** 获取自选股分组下的股票 */
GetUserSecurity = (c2s: proto.Qot_GetUserSecurity.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetUserSecurity.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetUserSecurity, { c2s }, timeout);
};
/** 修改自选股分组下的股票 */
ModifyUserSecurity = (c2s: proto.Qot_ModifyUserSecurity.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_ModifyUserSecurity.IResponse['s2c']>> => {
return this.reqFn(REQ.QotModifyUserSecurity, { c2s }, timeout);
};
/** 条件选股 */
StockFilter = (c2s: proto.Qot_StockFilter.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_StockFilter.IResponse['s2c']>> => {
return this.reqFn(REQ.QotStockFilter, { c2s }, timeout);
};
/** 获取股票代码变化信息 */
GetCodeChange = (c2s: proto.Qot_GetCodeChange.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetCodeChange.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetCodeChange, { c2s }, timeout);
};
/** 新股IPO */
GetIpoList = (c2s: proto.Qot_GetIpoList.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetIpoList.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetIpoList, { c2s }, timeout);
};
/** 期货合约资料 */
GetFutureInfo = (c2s: proto.Qot_GetFutureInfo.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetFutureInfo.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetFutureInfo, { c2s }, timeout);
};
/** 获取市场交易日 */
RequestTradeDate = (c2s: proto.Qot_RequestTradeDate.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_RequestTradeDate.IResponse['s2c']>> => {
return this.reqFn(REQ.QotRequestTradeDate, { c2s }, timeout);
};
/** 设置到价提醒 */
SetPriceReminder = (c2s: proto.Qot_SetPriceReminder.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_SetPriceReminder.IResponse['s2c']>> => {
return this.reqFn(REQ.QotSetPriceReminder, { c2s }, timeout);
};
/** 获取到价提醒 */
GetPriceReminder = (c2s: proto.Qot_GetPriceReminder.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetPriceReminder.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetPriceReminder, { c2s }, timeout);
};
/** 获取自选股分组列表 */
GetUserSecurityGroup = (c2s: proto.Qot_GetUserSecurityGroup.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetUserSecurityGroup.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetUserSecurityGroup, { c2s }, timeout);
};
/** 获取股票对应市场状态 */
GetMarketState = (c2s: proto.Qot_GetMarketState.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetMarketState.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetMarketState, { c2s }, timeout);
};
/** 获取期权链到期日 */
GetOptionExpirationDate = (c2s: proto.Qot_GetOptionExpirationDate.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Qot_GetOptionExpirationDate.IResponse['s2c']>> => {
return this.reqFn(REQ.QotGetOptionExpirationDate, { c2s }, timeout);
};
/** 获取交易帐号列表 */
GetAccList = (c2s: proto.Trd_GetAccList.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Trd_GetAccList.IResponse['s2c']>> => {
return this.reqFn(REQ.TrdGetAccList, { c2s }, timeout);
};
/** 解锁,针对OpenD解锁一次即可 */
UnlockTrade = (c2s: proto.Trd_UnlockTrade.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Trd_UnlockTrade.IResponse['s2c']>> => {
return this.reqFn(REQ.TrdUnlockTrade, { c2s }, timeout);
};
/** 订阅接收推送数据的交易账户 */
SubAccPush = (c2s: proto.Trd_SubAccPush.IRequest['c2s']): Promise<NonNullable<proto.Trd_SubAccPush.IResponse['s2c']>> => {
return this.reqFn(REQ.TrdSubAccPush, { c2s });
};
/** 获取账户资金 */
GetFunds = (c2s: proto.Trd_GetFunds.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Trd_GetFunds.IResponse['s2c']>> => {
return this.reqFn(REQ.TrdGetFunds, { c2s }, timeout);
};
/** 获取账户持仓 */
GetPositionList = (c2s: proto.Trd_GetPositionList.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Trd_GetPositionList.IResponse['s2c']>> => {
return this.reqFn(REQ.TrdGetPositionList, { c2s }, timeout);
};
/** 获取最大交易数量 */
GetMaxTrdQtys = (c2s: proto.Trd_GetMaxTrdQtys.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Trd_GetMaxTrdQtys.IResponse['s2c']>> => {
return this.reqFn(REQ.TrdGetMaxTrdQtys, { c2s }, timeout);
};
/** 获取当日订单列表 */
GetOrderList = (c2s: proto.Trd_GetOrderList.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Trd_GetOrderList.IResponse['s2c']>> => {
return this.reqFn(REQ.TrdGetOrderList, { c2s }, timeout);
};
/** 下单 */
PlaceOrder = (c2s: proto.Trd_PlaceOrder.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Trd_PlaceOrder.IResponse['s2c']>> => {
return this.reqFn(REQ.TrdPlaceOrder, { c2s }, timeout);
};
/** 修改订单 */
ModifyOrder = (c2s: proto.Trd_ModifyOrder.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Trd_ModifyOrder.IResponse['s2c']>> => {
return this.reqFn(REQ.TrdModifyOrder, { c2s }, timeout);
};
/** 获取当日成交列表 */
GetOrderFillList = (c2s: proto.Trd_GetOrderFillList.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Trd_GetOrderFillList.IResponse['s2c']>> => {
return this.reqFn(REQ.TrdGetOrderFillList, { c2s }, timeout);
};
/** 获取历史订单列表 */
GetHistoryOrderList = (c2s: proto.Trd_GetHistoryOrderList.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Trd_GetHistoryOrderList.IResponse['s2c']>> => {
return this.reqFn(REQ.TrdGetHistoryOrderList, { c2s }, timeout);
};
/** 获取历史成交列表 */
GetHistoryOrderFillList = (c2s: proto.Trd_GetHistoryOrderFillList.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Trd_GetHistoryOrderFillList.IResponse['s2c']>> => {
return this.reqFn(REQ.TrdGetHistoryOrderFillList, { c2s }, timeout);
};
/** 获取融资融券数据 */
GetMarginRatio = (c2s: proto.Trd_GetMarginRatio.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Trd_GetMarginRatio.IResponse['s2c']>> => {
return this.reqFn(REQ.TrdGetMarginRatio, { c2s }, timeout);
};
/** 获取订单收费明细数据 */
GetOrderFee = (c2s: proto.Trd_GetOrderFee.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Trd_GetOrderFee.IResponse['s2c']>> => {
return this.reqFn(REQ.TrdGetOrderFee, { c2s }, timeout);
};
/** 获取资金流水 */
FlowSummary = (c2s: proto.Trd_FlowSummary.IRequest['c2s'], timeout = 5000): Promise<NonNullable<proto.Trd_FlowSummary.IResponse['s2c']>> => {
return this.reqFn(REQ.TrdFlowSummary, { c2s }, timeout);
};
/** 推送通知 */
Notify = (callback: (res: NonNullable<proto.Notify.IResponse['s2c']>) => void) => {
return this.subFn(SUB.Notify, callback);
};
/** 推送基本行情 */
UpdateBasicQot = (callback: (res: NonNullable<proto.Qot_UpdateBasicQot.IResponse['s2c']>) => void) => {
return this.subFn(SUB.QotUpdateBasicQot, callback);
};
/** 推送K线 */
UpdateKL = (callback: (res: NonNullable<proto.Qot_UpdateKL.IResponse['s2c']>) => void) => {
return this.subFn(SUB.QotUpdateKL, callback);
};
/** 获取分时 */
UpdateRT = (callback: (res: NonNullable<proto.Qot_UpdateRT.IResponse['s2c']>) => void) => {
return this.subFn(SUB.QotUpdateRT, callback);
};
/** 推送逐笔 */
UpdateTicker = (callback: (res: NonNullable<proto.Qot_UpdateTicker.IResponse['s2c']>) => void) => {
return this.subFn(SUB.QotUpdateTicker, callback);
};
/** 推送买卖盘 */
UpdateOrderBook = (callback: (res: NonNullable<proto.Qot_UpdateOrderBook.IResponse['s2c']>) => void) => {
return this.subFn(SUB.QotUpdateOrderBook, callback);
};
/** 推送经纪队列 */
UpdateBroker = (callback: (res: NonNullable<proto.Qot_UpdateBroker.IResponse['s2c']>) => void) => {
return this.subFn(SUB.QotUpdateBroker, callback);
};
/** 推送到价提醒 */
UpdatePriceReminder = (callback: (res: NonNullable<proto.Qot_UpdatePriceReminder.IResponse['s2c']>) => void) => {
return this.subFn(SUB.QotUpdatePriceReminder, callback);
};
/** 订单状态变动通知(推送) */
UpdateOrder = (callback: (res: NonNullable<proto.Trd_UpdateOrder.IResponse['s2c']>) => void) => {
return this.subFn(SUB.TrdUpdateOrder, callback);
};
/** 成交通知(推送) */
UpdateOrderFill = (callback: (res: NonNullable<proto.Trd_UpdateOrderFill.IResponse['s2c']>) => void) => {
return this.subFn(SUB.TrdUpdateOrderFill, callback);
};
}