Open-source unofficial Futu Websocket API for Node.js
# the "futu-api" npm package was transferred back to Futu OpenAPI development team.
# npm install --save futu-api
or build locally
npm install
npm run build
// TODO: Run FutuOpenD software first
// Make sure websocket_port is set
import Futu, { Proto } from 'futu-api';
const { Qot_Common, Trd_Common } = Proto;
/**
* type FutuConfig = {
// server
ip?: string // default: 'localhost'
port?: number // default: 33333
recvNotify?: boolean // default: true
// user
userID: number
pwdMd5: string
// account
accMarket?: Proto.Trd_Common.TrdMarket // default: TrdMarket_HK
accEnv?: Proto.Trd_Common.TrdEnv // default: TrdEnv_Real
accType?: Proto.Trd_Common.TrdAccType // default: TrdAccType_Cash
// websocket
isSSL?: boolean // default: false
wsKey?: string // default: null
reqTimeout?: number // default: 10000
}
*/
const FutuConfig = {
userID: 1234,
pwdMd5: "129619259239abcdef",
}
const targetSecurity = {
code: 'YMmain',
market: Qot_Common.QotMarket.QotMarket_US_Security
}
/**
* Init
*
* In case the websocket connection ends unexpectedly,
* you can subscribe to data again if you put ft.qotSub into callback function.
*/
const ft = new Futu(FutuConfig, async function onOpenListener(ft) {
// Example 0: subscribe to trading account changes
await ft.trdSubAccPush()
// Example 1: get static info
let staticInfo = await ft.qotGetStaticInfo({
market: Qot_Common.QotMarket.QotMarket_HK_Security,
secType: Qot_Common.SecurityType.SecurityType_Warrant
})
console.log(staticInfo)
// Example 2: get snapshot of a list of securities.
// we get snapshot of HK.00700 Tencent Holdings Ltd. here
let snapshot = await ft.qotGetSecuritySnapshot({
securityList: [{
market: Qot_Common.QotMarket.QotMarket_HK_Security,
code: '00700'
}]
})
console.log(snapshot)
// Example 3: place order
// place order stock: HK.00700, price: 1.0, qty: 100
let resp = await ft.trdPlaceOrder({
trdSide: Trd_Common.TrdSide.TrdSide_Buy,
code: '00700',
price: 1.0,
orderType: Trd_Common.OrderType.OrderType_AbsoluteLimit,
qty: 100,
secMarket: Trd_Common.TrdSecMarket.TrdSecMarket_HK
})
console.log(resp)
// Example 4: get account list
let accList = await ft.trdGetAccList()
console.log(accList)
// Example 5: subscription
// subscribe to DJI futures (Ticker & Realtime data)
await ft.qotSub({
isSubOrUnSub: true,
isRegOrUnRegPush: true,
subTypeList: [
Qot_Common.SubType.SubType_Ticker,
Qot_Common.SubType.SubType_RT
],
regPushRehabTypeList: [
Qot_Common.RehabType.RehabType_Forward
],
securityList: [targetSecurity]
})
// unsubscribe after 1min according to documentation
await new Promise(resolve => setTimeout(resolve, 60500))
// only unsubscribe to ticker
await ft.qotSub({
isSubOrUnSub: false,
isRegOrUnRegPush: false,
subTypeList: [
Qot_Common.SubType.SubType_Ticker
],
securityList: [targetSecurity]
})
// unsubscribe all
await ft.qotSub({
isSubOrUnSub: false,
isRegOrUnRegPush: false,
isUnsubAll: true // <----------------------------------- all
})
ft.close()
})
/// Push Listeners
// trdSubAccPush
ft.on(Qot_Common.SubType.SubType_Order, data => {
console.log(
'Security: ', data.code,
' Price: ', data.price,
' Qty: ', data.qty,
' Order Type: ', data.orderType
)
})
// qotSub (Ticker)
ft.on(Qot_Common.SubType.SubType_Ticker, targetSecurity, data => {
console.log('ticker: ', data.tickerList!.map(ticker => ticker.price))
})
// qotSub (RT)
ft.on(Qot_Common.SubType.SubType_RT, targetSecurity, data => {
console.log('rt: ', data.rtList!.map(rt => rt.price))
})
You can use "Subscibe" decorator instead of ft.on()
import { Subscribe } from 'futu-api';
class Example {
@Subscribe(Qot_Common.SubType.SubType_Ticker, {
code: 'YMmain',
market: Qot_Common.QotMarket.QotMarket_US_Security
})
subscription(data: Proto.Qot_UpdateTicker.IS2C) {
console.log('ticker: ', data.tickerList!.map(ticker => ticker.price))
}
}
message C2S
{
optional int32 market = 1; //Qot_Common.QotMarket,股票市場
optional int32 secType = 2; //Qot_Common.SecurityType,股票類型
repeated Qot_Common.Security securityList = 3; //股票,若該字段存在,忽略其他字段,只返回該字段股票的靜態信息
}
According to this declaration file, the output will be
interface IC2S {
/** C2S market */
market?: (number|null);
/** C2S secType */
secType?: (number|null);
/** C2S securityList */
securityList?: (Qot_Common.ISecurity[]|null);
}
/** correction */
interface IC2S {
/** C2S market */
market?: (Qot_Common.QotMarket|null);
/** C2S secType */
secType?: (Qot_Common.SecurityType|null);
/** C2S securityList */
securityList?: (Qot_Common.ISecurity[]|null);
}
# Require FutuOpenD software running
# Make sure websocket_port is set
npm test