UNPKG

@itick/browser-sdk

Version:

Official iTick API SDK for browser. Real-time & historical data for global Stocks, Forex, Crypto, Indices, Futures, Funds, Precious Metals. REST (OHLCV/K-line) + low-latency WebSocket. Promise-based, TypeScript-ready. For quant trading & fintech

1,171 lines (1,163 loc) 85.1 kB
'use strict'; /** * Kline Period Enum (Standard Text Identifiers + Numeric Codes) * Centrally maintained for global reuse */ const KlinePeriod = { ONE_MIN: '1m', FIVE_MIN: '5m', FIFTEEN_MIN: '15m', THIRTY_MIN: '30m', ONE_HOUR: '1h', TWO_HOUR: '2h', FOUR_HOUR: '4h', ONE_DAY: '1d', ONE_WEEK: '1w', ONE_MONTH: '1M', }; // Numeric code mapping const KlineTypeCode = { [KlinePeriod.ONE_MIN]: 1, [KlinePeriod.FIVE_MIN]: 2, [KlinePeriod.FIFTEEN_MIN]: 3, [KlinePeriod.THIRTY_MIN]: 4, [KlinePeriod.ONE_HOUR]: 5, [KlinePeriod.TWO_HOUR]: 6, [KlinePeriod.FOUR_HOUR]: 7, [KlinePeriod.ONE_DAY]: 8, [KlinePeriod.ONE_WEEK]: 9, [KlinePeriod.ONE_MONTH]: 10, }; /** * Market Data Subscription Types * Supports both kline@1m and kline@1 formats */ const SubscribeType = { // Basic market data QUOTE: 'quote', DEPTH: 'depth', TICK: 'tick', // Kline subscription KLINE_1M: `kline@${KlinePeriod.ONE_MIN}`, KLINE_5M: `kline@${KlinePeriod.FIVE_MIN}`, KLINE_15M: `kline@${KlinePeriod.FIFTEEN_MIN}`, KLINE_30M: `kline@${KlinePeriod.THIRTY_MIN}`, KLINE_1H: `kline@${KlinePeriod.ONE_HOUR}`, KLINE_2H: `kline@${KlinePeriod.TWO_HOUR}`, KLINE_4H: `kline@${KlinePeriod.FOUR_HOUR}`, KLINE_1D: `kline@${KlinePeriod.ONE_DAY}`, KLINE_1W: `kline@${KlinePeriod.ONE_WEEK}`, KLINE_1MTH: `kline@${KlinePeriod.ONE_MONTH}`, }; // Numeric code mapping const SubscribeTypeCode = { [SubscribeType.KLINE_1M]: `kline@${KlineTypeCode[KlinePeriod.ONE_MIN]}`, [SubscribeType.KLINE_5M]: `kline@${KlineTypeCode[KlinePeriod.FIVE_MIN]}`, [SubscribeType.KLINE_15M]: `kline@${KlineTypeCode[KlinePeriod.FIFTEEN_MIN]}`, [SubscribeType.KLINE_30M]: `kline@${KlineTypeCode[KlinePeriod.THIRTY_MIN]}`, [SubscribeType.KLINE_1H]: `kline@${KlineTypeCode[KlinePeriod.ONE_HOUR]}`, [SubscribeType.KLINE_2H]: `kline@${KlineTypeCode[KlinePeriod.TWO_HOUR]}`, [SubscribeType.KLINE_4H]: `kline@${KlineTypeCode[KlinePeriod.FOUR_HOUR]}`, [SubscribeType.KLINE_1D]: `kline@${KlineTypeCode[KlinePeriod.ONE_DAY]}`, [SubscribeType.KLINE_1W]: `kline@${KlineTypeCode[KlinePeriod.ONE_WEEK]}`, [SubscribeType.KLINE_1MTH]: `kline@${KlineTypeCode[KlinePeriod.ONE_MONTH]}`, }; const STRICT_SYMBOL_REGEX = /^[A-Za-z0-9]+\$[A-Za-z0-9]+$/; function buildApiUrl(baseURL, path) { return `${baseURL.replace(/\/$/, '')}${path}`; } function buildWebSocketUrl(wssURL, path) { return `${wssURL.replace(/\/$/, '')}${path}`; } /** * Convert K-line period string to number */ function convertKlinePeriod(period) { if (period === KlinePeriod.ONE_MIN) return 1; if (period === KlinePeriod.FIVE_MIN) return 2; if (period === KlinePeriod.FIFTEEN_MIN) return 3; if (period === KlinePeriod.THIRTY_MIN) return 4; if (period === KlinePeriod.ONE_HOUR) return 5; if (period === KlinePeriod.TWO_HOUR) return 6; if (period === KlinePeriod.FOUR_HOUR) return 7; if (period === KlinePeriod.ONE_DAY) return 8; if (period === KlinePeriod.ONE_WEEK) return 9; if (period === KlinePeriod.ONE_MONTH) return 10; return period; } /** * Convert websocket subscription type */ function convertSubscribeType(type) { if (type === SubscribeType.KLINE_1M) return 'kline@1'; if (type === SubscribeType.KLINE_5M) return 'kline@2'; if (type === SubscribeType.KLINE_15M) return 'kline@3'; if (type === SubscribeType.KLINE_30M) return 'kline@4'; if (type === SubscribeType.KLINE_1H) return 'kline@5'; if (type === SubscribeType.KLINE_2H) return 'kline@6'; if (type === SubscribeType.KLINE_4H) return 'kline@7'; if (type === SubscribeType.KLINE_1D) return 'kline@8'; if (type === SubscribeType.KLINE_1W) return 'kline@9'; if (type === SubscribeType.KLINE_1MTH) return 'kline@10'; return type; } /** * Convert subscription type list */ function parseeSubscribeType(type) { let rawList; if (Array.isArray(type)) rawList = type.map(String); else rawList = type.split(','); const validTypes = Object.values(SubscribeType); const processedList = []; const apiToEnumMap = {}; for (const enumValue of validTypes) { // Ensure enumValue is a valid SubscribeType if (typeof enumValue === 'string' || typeof enumValue === 'number') { const apiFormat = convertSubscribeType(enumValue); apiToEnumMap[apiFormat] = enumValue; } } for (const item of rawList) { const trimmed = item.trim(); if (!trimmed) continue; let targetEnum; const isValid = validTypes.some(v => v === trimmed); if (isValid) targetEnum = trimmed; else targetEnum = apiToEnumMap[trimmed]; if (!targetEnum) throw new Error(`Invalid subscribe type: "${trimmed}". Valid types are: ${validTypes.join(', ')}`); processedList.push(convertSubscribeType(trimmed)); } return [...new Set(processedList)].join(','); } /** * Subscription product parameter formatting function * @param input Subscription parameters */ function parseSymbols(input) { const list = Array.isArray(input) ? input : input.split(','); return [...new Set(list .map(item => item.trim()) .filter(Boolean) .map(item => { if (!STRICT_SYMBOL_REGEX.test(item)) throw new Error(`Invalid symbol format: "${item}". Expected format is "SYMBOL$REGION", e.g. "AAPL$US".`); return item.toUpperCase(); }))].join(','); } /** * Build query string */ function buildQueryString(params) { return Object.entries(params) .filter(([_, value]) => value != null) .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) .join('&'); } /** * HTTP request implementation for Browser environment (using fetch API) */ async function makeHttpRequest(url, options = {}) { const { method = 'GET', headers = {}, body, params = {}, } = options; // Build complete URL let finalUrl = url; // For GET requests, append params to URL if (method === 'GET' && Object.keys(params).length > 0) { const queryString = buildQueryString(params); // Handle existing query parameters in the base URL const separator = finalUrl.includes('?') ? '&' : '?'; finalUrl = `${finalUrl}${separator}${queryString}`; } // Prepare fetch options const fetchOptions = { method, headers: { 'Content-Type': 'application/json', ...headers, }, }; // Attach body for non-GET methods if (body && method !== 'GET') { fetchOptions.body = body; } try { const response = await fetch(finalUrl, fetchOptions); // Extract headers as a plain object const responseHeaders = {}; response.headers.forEach((value, key) => { responseHeaders[key] = value; }); // Parse JSON response let data; const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { try { data = await response.json(); } catch (e) { // Fallback to text if JSON parsing fails but content-type suggests JSON data = await response.text(); } } else { // For non-JSON responses, get text data = await response.text(); } return { status: response.status, data, headers: responseHeaders, }; } catch (error) { // Network errors or other fetch failures throw new Error(`Request failed: ${error instanceof Error ? error.message : String(error)}`); } } /** * Create WebSocket instance (Browser environment) */ async function createWebSocket(url, token) { return new WebSocket(`${url}?token=${token}`); } class SocketClient { constructor(token, options) { // WebSocket connection related properties this.socket = null; this.isRunning = false; this.reconnectAttempts = 0; this.pingInterval = null; this.reconnectTimeout = null; // Callback functions this.messageHandlers = []; this.errorHandlers = []; this.openHandlers = []; this.closeHandlers = []; // Subscription information storage this.lastSubscription = null; this.wssURL = options.wssURL ?? 'wss://api.itick.org'; this.wsPath = options.wsPath; this.token = token; this.RECONNECT_INTERVAL = options.reconnectInterval ?? 5000; this.MAX_RECONNECT_ATTEMPTS = options.maxReconnectTimes ?? 0; this.PING_INTERVAL = options.pingInterval ?? 30000; this.lastSubscription = options.subscribeData ?? null; this._connectWebSocket(); } /** * WebSocket Message Handler */ onSocketMessage(handler) { this.messageHandlers.push(handler); } /** * WebSocket Error Handler */ onSocketError(handler) { this.errorHandlers.push(handler); } /** * WebSocket Connection Open Handler */ onSocketOpen(handler) { this.openHandlers.push(handler); } /** * WebSocket Connection Close Handler */ onSocketClose(handler) { this.closeHandlers.push(handler); } /** * Internal WebSocket Connection Method */ async _connectWebSocket() { const url = buildWebSocketUrl(this.wssURL, this.wsPath || ''); try { this.isRunning = true; this.socket = await createWebSocket(url, this.token); this.socket.onopen = () => { this.reconnectAttempts = 0; this._startPing(); this.openHandlers.forEach(handler => handler()); // Subscribe to data after successful connection this._resubscribeLast(); }; this.socket.onmessage = (event) => { const messageStr = typeof event.data === 'string' ? event.data : event.data.toString(); this.messageHandlers.forEach(handler => handler(JSON.parse(messageStr))); }; this.socket.onclose = (event) => { this._stopPing(); this.closeHandlers.forEach(handler => handler(event)); if (this.isRunning) { this._scheduleReconnect(); } }; this.socket.onerror = (event) => { this.errorHandlers.forEach(handler => handler(event)); }; } catch (error) { this.errorHandlers.forEach(handler => handler(error)); if (this.isRunning) { this._scheduleReconnect(); } } } /** * Start heartbeat ping */ _startPing() { this._stopPing(); this.pingInterval = setInterval(() => { if (this.socket && this.socket.readyState === WebSocket.OPEN) { this.socket.send(JSON.stringify({ ac: "ping", params: Date.now() })); } }, this.PING_INTERVAL); } /** * Stop heartbeat ping */ _stopPing() { if (this.pingInterval) { clearInterval(this.pingInterval); this.pingInterval = null; } } /** * Schedule reconnection */ _scheduleReconnect() { // When MAX_RECONNECT_ATTEMPTS is 0, it means unlimited reconnection if (this.MAX_RECONNECT_ATTEMPTS > 0 && this.reconnectAttempts >= this.MAX_RECONNECT_ATTEMPTS) { this.errorHandlers.forEach(handler => handler(new Error('Maximum reconnect attempts reached'))); return; } this.reconnectAttempts++; this.reconnectTimeout = setTimeout(() => { if (this.isRunning) { this._connectWebSocket().catch((error) => { }); } }, this.RECONNECT_INTERVAL); } /** * WebSocket Subscription Method * @description * message object must contain ac, types and params fields * - ac: operation type, must be "subscribe" or "unsubscribe" * - types: subscription types, can be comma-separated string or string array, supports "quote", "depth", "tick", "kline@1m" etc. kline@1m can also be written as kline@1, SDK will automatically convert to correct format * - params: subscription parameters, can be comma-separated string or string array, format is "code$region" (e.g., "AAPL$US") SDK will automatically handle formatting * - String array format is recommended for clearer code and fewer errors * @example * Example 1: Subscribe to AAPL and TSA real-time quotes/order book/trades/1-minute K-line data * ```json * { * "ac": "subscribe", * "types": "quote,depth,tick,kline@1", * "params": "AAPL$US,TSA$US" * } * ``` * Example 2: Subscribe to AAPL and TSA real-time quotes/order book/trades/1-minute K-line data * ```json * { * "ac": "subscribe", * "types": ["quote","depth","tick","kline@1m"], * "params": ["AAPL$US","TSA$US"] * } * ``` * * Both methods can correctly subscribe, SDK will automatically handle type conversion and parameter formatting * */ subscribeSocket(data) { if (!this.socket || this.socket.readyState !== WebSocket.OPEN) { throw new Error('WebSocket not connected'); } try { let { ac, types, codes } = data; const type = parseeSubscribeType(types); const symbol = parseSymbols(codes); this.socket.send(JSON.stringify({ ac, types: type, params: symbol })); } catch (err) { console.error(err); } } /** * Restore subscription after reconnection */ _resubscribeLast() { if (!this.lastSubscription) return; try { let { types, codes } = this.lastSubscription; const type = parseeSubscribeType(types); const symbol = parseSymbols(codes); this.socket?.send(JSON.stringify({ ac: 'subscribe', types: type, params: symbol })); } catch (err) { console.error(err); } } /** * Close WebSocket */ closeWebSocket() { this.isRunning = false; this._stopPing(); if (this.reconnectTimeout) { clearTimeout(this.reconnectTimeout); } if (this.socket) { this.socket.close(); } // Clear last subscription information when closing this.lastSubscription = null; } /** * Check if WebSocket is connected */ checkSocketConnected() { if (!this.socket) return false; return this.socket.readyState === WebSocket.OPEN; } disconnectSocket() { this.closeWebSocket(); } } /** * Core Client Class * Provides basic functionality for WebSocket connections and HTTP requests */ class Client { constructor(token, options = {}) { this.token = token; this.baseURL = options.baseURL ?? 'https://api.itick.org'; this.wssURL = options.wssURL ?? 'wss://api.itick.org'; } /** * Send GET request */ async _get(path, params = {}) { try { const url = buildApiUrl(this.baseURL, path); const response = await makeHttpRequest(url, { method: 'GET', headers: { 'accept': 'application/json', 'token': this.token }, params, }); if (response.status >= 400) { throw new Error(`HTTP Error: ${response.status}`); } return response.data; } catch (error) { throw error; } } _createSocket(path, options) { return new SocketClient(this.token, { wssURL: this.wssURL, wsPath: path, ...options }); } } /** * Stock Module * Provides data access interfaces for stocks */ /** * Stock SDK Client * Specialized for stock data access */ class StockClient extends Client { constructor(token, options) { super(token, options); } /** * Get Stock Information * @description Query basic stock information based on market code and symbol code * @param params - Query parameters object * @param params.region - Market code (e.g., US, HK etc.), see {@link https://docs.itick.org/rest-api/stocks/stock-info Official Documentation} for complete supported list * @param params.code - Stock code (e.g., AAPL, MSFT etc.) * @param params.exchange - Optional Exchange code (e.g., NYSE, NASDAQ etc.) * @returns Promise wrapped standard API response, data is stock information data {@link StockInfo} * @example * ```typescript * // Get Apple Inc. stock information * getInfo({ region: 'US', code: 'AAPL' }).then(response => { * console.log('Stock information:', response.data); * }).catch(err => { * console.error('Failed to get stock information:', err); * }); * ``` */ async getInfo(params) { const { region, code, exchange } = params; return this._get('/stock/info', { type: 'stock', region, code, exchange }); } /** * Get Stock IPO Information * @description Query stock initial public offering information based on market code and symbol code * @param params - Query parameters object * @param params.region - Market code (e.g., US, HK etc.), see {@link https://docs.itick.org/rest-api/stocks/stock-ipo Official Documentation} for complete supported list * @param params.code - Stock code (e.g., AAPL, MSFT etc.) * @returns Promise wrapped standard API response, data is stock IPO information data {@link StockIPO} * @example * ```typescript * // Get Apple Inc. IPO information * getIPO({ region: 'US', code: 'AAPL' }).then(response => { * console.log('IPO information:', response.data); * }).catch(err => { * console.error('Failed to get IPO information:', err); * }); * ``` */ async getIPO(params) { const { region, code } = params; return this._get('/stock/ipo', { region, code }); } /** * Get Stock Adjustment Factor Information * @description Query stock ex-rights and ex-dividend information based on market code and symbol code * @param params - Query parameters object * @param params.region - Market code (e.g., US, HK etc.), see {@link https://docs.itick.org/rest-api/stocks/stock-split Official Documentation} for complete supported list * @param params.code - Stock code (e.g., AAPL, MSFT etc.) * @returns Promise wrapped standard API response, data is stock adjustment factor information data {@link StockSplit} * @example * ```typescript * // Get Apple Inc. adjustment information * getSplit({ region: 'US', code: 'AAPL' }).then(response => { * console.log('Adjustment information:', response.data); * }).catch(err => { * console.error('Failed to get adjustment information:', err); * }); * ``` */ async getSplit(params) { const { region, code } = params; return this._get('/stock/split', { region, code }); } /** * Get Stock Real-Time Trade Snapshot * @description Query latest trade real-time market data for stock based on market code and symbol code * @param params - Query parameters object * @param params.region - Market code (e.g., US, HK etc.), see {@link https://docs.itick.org/rest-api/stocks/stock-tick Official Documentation} for complete supported list * @param params.code - Stock code (e.g., AAPL, MSFT etc.) * @returns Promise wrapped standard API response, data is real-time market data {@link TickData} * @example * ```typescript * // Get real-time trade market data for Apple Inc. stock * getTick({ region: 'US', code: 'AAPL' }).then(response => { * console.log('Real-time market:', response.data); * }).catch(err => { * console.error('Failed to get market data:', err); * }); * ``` */ async getTick(params) { const { region, code } = params; return this._get('/stock/tick', { region, code }); } /** * Get Stock Latest Quote * @description Query latest quote real-time market data for stock based on market code and symbol code * @param params - Query parameters object * @param params.region - Market code (e.g., US, HK etc.), see {@link https://docs.itick.org/rest-api/stocks/stock-quote Official Documentation} for complete supported list * @param params.code - Stock code (e.g., AAPL, MSFT etc.) * @returns Promise wrapped API response, data is latest quote data {@link QuoteData} * @example * ```typescript * // Get latest quote for Apple Inc. stock * getQuote({ region: 'US', code: 'AAPL' }).then(response => { * console.log('Latest quote:', response.data); * }).catch(err => { * console.error('Failed to get quote:', err); * }); * ``` */ async getQuote(params) { const { region, code } = params; return this._get('/stock/quote', { region, code }); } /** * Get Stock Latest Order Book * @description Query latest order book data for stock based on market code and symbol code * @param params - Query parameters object * @param params.region - Market code (e.g., US, HK etc.), see {@link https://docs.itick.org/rest-api/stocks/stock-depth Official Documentation} for complete supported list * @param params.code - Stock code (e.g., AAPL, MSFT etc.) * @returns Promise wrapped API response, data is latest order book data {@link DepthData} * @example * ```typescript * // Get latest order book for Apple Inc. stock * getDepth({ region: 'US', code: 'AAPL' }).then(response => { * console.log('Latest order book:', response.data); * }).catch(err => { * console.error('Failed to get order book:', err); * }); * ``` */ async getDepth(params) { const { region, code } = params; return this._get('/stock/depth', { region, code }); } /** * Get Stock K-Line Data * @description Query stock K-line data based on market code, symbol code, K-line period, end time and number of records to return * @param options - Query parameters object {@link GetKlineOptions} * @param options.region - Market code (e.g., US, HK etc.), see {@link https://docs.itick.org/rest-api/stocks/stock-kline Official Documentation} for complete supported list * @param options.code - Stock code (e.g., AAPL, MSFT etc.) * @returns Promise wrapped API response, data is K-line data array {@link KlineData} * @example * ```typescript * // Get 5-minute K-line data for Apple Inc. stock * getKline({ region: 'US', code: 'AAPL', interval: '5m', limit: 100 }).then(response => { * console.log('K-line data:', response.data); * }).catch(err => { * console.error('Failed to get K-line data:', err); * }); * ``` */ async getKline(options) { const { region, code, kType, interval, limit, et } = options; const params = { region, code, kType: convertKlinePeriod(interval ?? kType), limit }; if (et) params.et = et; return this._get('/stock/kline', params); } /** * Get Multiple Stocks Latest Trades * @description Query latest trade real-time market data for multiple stocks based on market code and symbol code list * @param params - Query parameters object * @param params.region - Market code (e.g., US, HK etc.), see {@link https://docs.itick.org/rest-api/stocks/stock-ticks Official Documentation} for complete supported list * @param params.codes - Symbol code list (e.g., AAPL, MSFT etc.) * @returns Promise wrapped API response, data is multiple stocks latest trade data object {@link TickDataMap} * @example * ```typescript * // Get latest trade market data for Apple Inc. and Microsoft Corp. * getTicks({ region: 'US', codes: ['AAPL', 'MSFT'] }).then(response => { * console.log('Latest trades:', response.data); * }).catch(err => { * console.error('Failed to get trade market data:', err); * }); * ``` */ async getTicks(params) { const { region, codes } = params; return this._get('/stock/ticks', { region, codes: Array.isArray(codes) ? codes.join(',') : codes }); } /** * Get Multiple Stocks Latest Quotes * @description Query latest quote real-time market data for multiple stocks based on market code and symbol code list * @param params - Query parameters object * @param params.region - Market code (e.g., US, HK etc.), see {@link https://docs.itick.org/rest-api/stocks/stock-quotes Official Documentation} for complete supported list * @param params.codes - Symbol code list (e.g., AAPL, MSFT etc.) * @returns Promise wrapped API response, data is multiple stocks latest quote data object {@link QuoteDataMap} * @example * ```typescript * // Get latest quotes for Apple Inc. and Microsoft Corp. * getQuotes({ region: 'US', codes: ['AAPL', 'MSFT'] }).then(response => { * console.log('Latest quotes:', response.data); * }).catch(err => { * console.error('Failed to get quotes:', err); * }); * ``` */ async getQuotes(params) { const { region, codes } = params; return this._get('/stock/quotes', { region, codes: Array.isArray(codes) ? codes.join(',') : codes }); } /** * Get Multiple Stocks Latest Order Books * @description Query latest order book real-time market data for multiple stocks based on market code and symbol code list * @param params - Query parameters object * @param params.region - Market code (e.g., US, HK etc.), see {@link https://docs.itick.org/rest-api/stocks/stock-depths Official Documentation} for complete supported list * @param params.codes - Symbol code list (e.g., AAPL, MSFT etc.) * @returns Promise wrapped API response, data is multiple stocks latest order book data object {@link DepthDataMap} * @example * ```typescript * // Get latest order books for Apple Inc. and Microsoft Corp. * getDepths({ region: 'US', codes: ['AAPL', 'MSFT'] }).then(response => { * console.log('Latest order books:', response.data); * }).catch(err => { * console.error('Failed to get order books:', err); * }); * ``` */ async getDepths(params) { const { region, codes } = params; return this._get('/stock/depths', { region, codes: Array.isArray(codes) ? codes.join(',') : codes }); } /** * Get Multiple Stocks K-Line Data * @description Query K-line data for multiple stocks based on market code, symbol code list, K-line period, end time and number of records to return * @param options - Query parameters object {@link GetKlinesOptions} * @param options.region - Market code (e.g., US, HK etc.), see {@link https://docs.itick.org/rest-api/stocks/stock-klines Official Documentation} for complete supported list * @param options.codes - Symbol code list (e.g., AAPL, MSFT etc.) * @returns Promise wrapped API response, data is multiple stocks K-line data object {@link KlineDataMap} * @example * ```typescript * // Get 5-minute K-line data for Apple Inc. and Microsoft Corp. * getKlines({ region: 'US', codes: ['AAPL', 'MSFT'], kType: '5m', limit: 100 }).then(response => { * console.log('K-line data:', response.data); * }).catch(err => { * console.error('Failed to get K-line data:', err); * }); * ``` */ async getKlines(options) { const { region, codes, kType, interval, limit, et } = options; const params = { region, codes: Array.isArray(codes) ? codes.join(',') : codes, kType: convertKlinePeriod(interval ?? kType), limit }; if (et) params.et = et; return this._get('/stock/klines', params); } /** * Create WebSocket Connection * @description Creates a WebSocket connection and returns a SocketClient object for managing connection and subscribing to real-time data. Subscription data can be specified through options parameter. * Automatically handles connection retry and heartbeat mechanism to ensure connection stability and reliability. * @param options - Optional options object for creating WebSocket connection {@link CreateSocketOptions} * @returns SocketClient object for managing WebSocket connection * @example * ```typescript * // Create a WebSocket connection and subscribe to latest tick and quote market data for Apple and Microsoft * const client = new StockClient(token); * const socket = client.createSocket({ * subscribeData: { * codes: ['AAPL$US', 'MSFT$US'], * types: ['tick','quote'] * } * }); * socket.onSocketMessage(data => { * console.log('Received WebSocket message:', data); * }); * ``` * @see Official Documentation https://docs.itick.org/websocket/stocks */ createSocket(options) { return this._createSocket('/stock', options); } } /** * Cryptocurrency Module * Provides data access interfaces for cryptocurrencies */ /** * Cryptocurrency SDK Client * Specialized for cryptocurrency data access */ class CryptoClient extends Client { constructor(token, options) { super(token, options); } /** * Get Cryptocurrency Real-Time Trade Snapshot * @description Query latest trade real-time market data for cryptocurrency based on market code and symbol code * @param params - Query parameters object * @param params.region - Market code (e.g., BA, BT, PB etc.), see {@link https://docs.itick.org/rest-api/crypto/crypto-tick Official Documentation} for complete supported list * @param params.code - Symbol code (e.g., BTCUSDT, ETHUSDT etc.) * @returns Promise wrapped standard API response, data is real-time market data {@link TickData} * @example * ```typescript * // Get real-time trade market data for BTCUSDT cryptocurrency pair * getTick({ region: 'BA', code: 'BTCUSDT' }).then(response => { * console.log('Real-time market:', response.data); * }).catch(err => { * console.error('Failed to get market data:', err); * }); * ``` */ async getTick(params) { const { region, code } = params; return this._get('/crypto/tick', { region, code }); } /** * Get Cryptocurrency Latest Quote * @description Query latest quote real-time market data for cryptocurrency based on market code and symbol code * @param params - Query parameters object * @param params.region - Market code (e.g., BA, BT, PB etc.), see {@link https://docs.itick.org/rest-api/crypto/crypto-quote Official Documentation} for complete supported list * @param params.code - Symbol code (e.g., BTCUSDT, ETHUSDT etc.) * @returns Promise wrapped API response, data is latest quote data {@link QuoteData} * @example * ```typescript * // Get latest quote for BTCUSDT cryptocurrency pair * getQuote({ region: 'BA', code: 'BTCUSDT' }).then(response => { * console.log('Latest quote:', response.data); * }).catch(err => { * console.error('Failed to get quote:', err); * }); * ``` */ async getQuote(params) { const { region, code } = params; return this._get('/crypto/quote', { region, code }); } /** * Get Cryptocurrency Latest Order Book * @description Query latest order book data for cryptocurrency based on market code and symbol code * @param params - Query parameters object * @param params.region - Market code (e.g., BA, BT, PB etc.), see {@link https://docs.itick.org/rest-api/crypto/crypto-depth Official Documentation} for complete supported list * @param params.code - Symbol code (e.g., BTCUSDT, ETHUSDT etc.) * @returns Promise wrapped API response, data is latest order book data {@link DepthData} * @example * ```typescript * // Get latest order book for BTCUSDT cryptocurrency pair * getDepth({ region: 'BA', code: 'BTCUSDT' }).then(response => { * console.log('Latest order book:', response.data); * }).catch(err => { * console.error('Failed to get order book:', err); * }); * ``` */ async getDepth(params) { const { region, code } = params; return this._get('/crypto/depth', { region, code }); } /** * Get Cryptocurrency K-Line Data * @description Query cryptocurrency K-line data based on market code, symbol code, K-line period, end time and number of records to return * @param options - Query parameters object see {@link GetKlineOptions} * @param options.region - Market code (e.g., BA, BT, PB etc.), see {@link https://docs.itick.org/rest-api/crypto/crypto-kline Official Documentation} for complete supported list * @param params.code - Symbol code (e.g., BTCUSDT, ETHUSDT etc.) * @returns Promise wrapped API response, data is K-line data array {@link KlineData} * @example * ```typescript * // Get 5-minute K-line data for BTCUSDT cryptocurrency pair * getKline({ region: 'BA', code: 'BTCUSDT', interval: '5m', limit: 100 }).then(response => { * console.log('K-line data:', response.data); * }).catch(err => { * console.error('Failed to get K-line data:', err); * }); * ``` */ async getKline(options) { const { region, code, kType, interval, limit, et } = options; const params = { region, code, kType: convertKlinePeriod(interval ?? kType), limit }; if (et) params.et = et; return this._get('/crypto/kline', params); } /** * Get Multiple Cryptocurrencies Latest Trades * @description Query latest trade real-time market data for multiple cryptocurrencies based on market code and symbol code list * @param params - Query parameters object * @param params.region - Market code (e.g., BA, BT, PB etc.), see {@link https://docs.itick.org/rest-api/crypto/crypto-ticks Official Documentation} for complete supported list * @param params.codes - Symbol code list (e.g., BTCUSDT, ETHUSDT etc.) * @returns Promise wrapped API response, data is multiple cryptocurrencies latest trade data object {@link TickDataMap} * @example * ```typescript * // Get latest trade market data for BTCUSDT and ETHUSDT cryptocurrency pairs * getTicks({ region: 'BA', codes: ['BTCUSDT', 'ETHUSDT'] }).then(response => { * console.log('Latest trades:', response.data); * }).catch(err => { * console.error('Failed to get trade market data:', err); * }); * ``` */ async getTicks(params) { const { region, codes } = params; return this._get('/crypto/ticks', { region, codes: Array.isArray(codes) ? codes.join(',') : codes }); } /** * Get Multiple Cryptocurrencies Latest Quotes * @description Query latest quote real-time market data for multiple cryptocurrencies based on market code and symbol code list * @param params - Query parameters object * @param params.region - Market code (e.g., BA, BT, PB etc.), see {@link https://docs.itick.org/rest-api/crypto/crypto-quotes Official Documentation} for complete supported list * @param params.codes - Symbol code list (e.g., BTCUSDT, ETHUSDT etc.) * @returns Promise wrapped API response, data is multiple cryptocurrencies latest quote data object {@link QuoteDataMap} * @example * ```typescript * // Get latest quotes for BTCUSDT and ETHUSDT cryptocurrency pairs * getQuotes({ region: 'BA', codes: ['BTCUSDT', 'ETHUSDT'] }).then(response => { * console.log('Latest quotes:', response.data); * }).catch(err => { * console.error('Failed to get quotes:', err); * }); * ``` */ async getQuotes(params) { const { region, codes } = params; return this._get('/crypto/quotes', { region, codes: Array.isArray(codes) ? codes.join(',') : codes }); } /** * Get Multiple Cryptocurrencies Latest Order Books * @description Query latest order book real-time market data for multiple cryptocurrencies based on market code and symbol code list * @param params - Query parameters object * @param params.region - Market code (e.g., BA, BT, PB etc.), see {@link https://docs.itick.org/rest-api/crypto/crypto-depths Official Documentation} for complete supported list * @param params.codes - Symbol code list (e.g., BTCUSDT, ETHUSDT etc.) * @returns Promise wrapped API response, data is multiple cryptocurrencies latest order book data object {@link DepthDataMap} * @example * ```typescript * // Get latest order books for BTCUSDT and ETHUSDT cryptocurrency pairs * getDepths({ region: 'BA', codes: ['BTCUSDT', 'ETHUSDT'] }).then(response => { * console.log('Latest order books:', response.data); * }).catch(err => { * console.error('Failed to get order books:', err); * }); * ``` */ async getDepths(params) { const { region, codes } = params; return this._get('/crypto/depths', { region, codes: Array.isArray(codes) ? codes.join(',') : codes }); } /** * Get Multiple Cryptocurrencies K-Line Data * @description Query K-line data for multiple cryptocurrencies based on market code, symbol code list, K-line period, end time and number of records to return * @param options - Query parameters object {@link GetKlinesOptions} * @param options.region - Market code (e.g., BA, BT, PB etc.), see {@link https://docs.itick.org/rest-api/crypto/crypto-klines Official Documentation} for complete supported list * @param params.codes - Symbol code list (e.g., BTCUSDT, ETHUSDT etc.) * @returns Promise wrapped API response, data is multiple cryptocurrencies K-line data object {@link KlineDataMap} * @example * ```typescript * // Get 5-minute K-line data for BTCUSDT and ETHUSDT cryptocurrency pairs * getKlines({ region: 'BA', codes: ['BTCUSDT', 'ETHUSDT'], interval: '5m', limit: 100 }).then(response => { * console.log('K-line data:', response.data); * }).catch(err => { * console.error('Failed to get K-line data:', err); * }); * ``` */ async getKlines(options) { const { region, codes, kType, interval, limit, et } = options; const params = { region, codes: Array.isArray(codes) ? codes.join(',') : codes, kType: convertKlinePeriod(interval ?? kType), limit }; if (et) params.et = et; return this._get('/crypto/klines', params); } /** * Create WebSocket Connection * @description Creates a WebSocket connection and returns a SocketClient object for managing connection and subscribing to real-time data. Subscription data can be specified through options parameter. * Automatically handles connection retry and heartbeat mechanism to ensure connection stability and reliability. * @param options - Optional options object for creating WebSocket connection {@link CreateSocketOptions} * @returns SocketClient object for managing WebSocket connection * @example * ```typescript * // Create a WebSocket connection and subscribe to real-time trades, quotes, order books, 1-minute K-line data for BTCUSDT and ETHUSDT, with maximum reconnection attempts of 5 * const client = new CryptoClient(token); * const socket = client.createSocket({ * maxReconnectTimes: 5, * subscribeData: { * codes: ['BTCUSDT$BA', 'ETHUSDT$BA'], * types: ['tick','quote','depth','kline@1m'], * } * }); * socket.onSocketMessage(data => { * console.log('Received WebSocket message:', data); * }); * ``` * @see Official Documentation https://docs.itick.org/websocket/crypto */ createSocket(options) { return this._createSocket('/crypto', options); } } /** * Forex Module * Provides data access interfaces for forex */ /** * Forex SDK Client * Specialized for forex data access */ class ForexClient extends Client { constructor(token, options) { super(token, options); } /** * Get Forex Real-Time Trade Snapshot * @description Query latest trade real-time market data for forex based on market code and symbol code * @param params - Query parameters object * @param params.region - Market code (e.g., GB etc.), see {@link https://docs.itick.org/rest-api/forex/forex-tick Official Documentation} for complete supported list * @param params.code - Symbol code (e.g., EURUSD, GBPUSD etc.) * @returns Promise wrapped standard API response, data is real-time market data {@link TickData} * @example * ```typescript * // Get real-time trade market data for EURUSD forex pair * getTick({ region: 'GB', code: 'EURUSD' }).then(response => { * console.log('Real-time market:', response.data); * }).catch(err => { * console.error('Failed to get market data:', err); * }); * ``` */ async getTick(params) { const { region, code } = params; return this._get('/forex/tick', { region, code }); } /** * Get Forex Latest Quote * @description Query latest quote real-time market data for forex based on market code and symbol code * @param params - Query parameters object * @param params.region - Market code (e.g., GB etc.), see {@link https://docs.itick.org/rest-api/forex/forex-quote Official Documentation} for complete supported list * @param params.code - Symbol code (e.g., EURUSD, GBPUSD etc.) * @returns Promise wrapped API response, data is latest quote data {@link QuoteData} * @example * ```typescript * // Get latest quote for EURUSD forex pair * getQuote({ region: 'GB', code: 'EURUSD' }).then(response => { * console.log('Latest quote:', response.data); * }).catch(err => { * console.error('Failed to get quote:', err); * }); * ``` */ async getQuote(params) { const { region, code } = params; return this._get('/forex/quote', { region, code }); } /** * Get Forex Latest Order Book * @description Query latest order book data for forex based on market code and symbol code * @param params - Query parameters object * @param params.region - Market code (e.g., GB etc.), see {@link https://docs.itick.org/rest-api/forex/forex-depth Official Documentation} for complete supported list * @param params.code - Symbol code (e.g., EURUSD, GBPUSD etc.) * @returns Promise wrapped API response, data is latest order book data {@link DepthData} * @example * ```typescript * // Get latest order book for EURUSD forex pair * getDepth({ region: 'GB', code: 'EURUSD' }).then(response => { * console.log('Latest order book:', response.data); * }).catch(err => { * console.error('Failed to get order book:', err); * }); * ``` */ async getDepth(params) { const { region, code } = params; return this._get('/forex/depth', { region, code }); } /** * Get Forex K-Line Data * @description Query forex K-line data based on market code, symbol code, K-line period, end time and number of records to return * @param options - Query parameters object see {@link GetKlineOptions} * @param options.region - Market code (e.g., GB etc.), see {@link https://docs.itick.org/rest-api/forex/forex-kline Official Documentation} for complete supported list * @param params.code - Symbol code (e.g., EURUSD, GBPUSD etc.) * @returns Promise wrapped API response, data is K-line data array {@link KlineData} * @example * ```typescript * // Get 5-minute K-line data for EURUSD forex pair * getKline({ region: 'GB', code: 'EURUSD', interval: '5m', limit: 100 }).then(response => { * console.log('K-line data:', response.data); * }).catch(err => { * console.error('Failed to get K-line data:', err); * }); * ``` */ async getKline(options) { const { region, code, kType, interval, limit, et } = options; const params = { region, code, kType: convertKlinePeriod(interval ?? kType), limit }; if (et) params.et = et; return this._get('/forex/kline', params); } /** * Get Multiple Forex Latest Trades * @description Query latest trade real-time market data for multiple forex pairs based on market code and symbol code list * @param params - Query parameters object * @param params.region - Market code (e.g., GB etc.), see {@link https://docs.itick.org/rest-api/forex/forex-ticks Official Documentation} for complete supported list * @param params.codes - Symbol code list (e.g., EURUSD, GBPUSD etc.) * @returns Promise wrapped API response, data is multiple forex latest trade data object {@link TickDataMap} * @example * ```typescript * // Get latest trade market data for EURUSD and GBPUSD forex pairs * getTicks({ region: 'GB', codes: ['EURUSD', 'GBPUSD'] }).then(response => { * console.log('Latest trades:', response.data); * }).catch(err => { * console.error('Failed to get trade market data:', err); * }); * ``` */ async getTicks(params) { const { region, codes } = params; return this._get('/forex/ticks', { region, codes: Array.isArray(codes) ? codes.join(',') : codes }); } /** * Get Multiple Forex Latest Quotes * @description Query latest quote real-time market data for multiple forex pairs based on market code and symbol code list * @param params - Query parameters object * @param params.region - Market code (e.g., GB etc.), see {@link https://docs.itick.org/rest-api/forex/forex-quotes Official Documentation} for complete supported list * @param params.codes - Symbol code list (e.g., EURUSD, GBPUSD etc.) * @returns Promise wrapped API response, data is multiple forex latest quote data object {@link QuoteDataMap} * @example * ```typescript * // Get latest quotes for EURUSD and GBPUSD forex pairs * getQuotes({ region: 'GB', codes: ['EURUSD', 'GBPUSD'] }).then(response => { * console.log('Latest quotes:', response.data); * }).catch(err => { * console.error('Failed to get quotes:', err); * }); * ``` */ async getQuotes(params) { const { region, codes } = params; return this._get('/forex/quotes', { region, codes: Array.isArray(codes) ? codes.join(',') : codes }); } /** * Get Multiple Forex Latest Order Books * @description Query latest order book real-time market data for multiple forex pairs based on market code and symbol code list * @param params - Query parameters object * @param params.region - Market code (e.g., GB etc.), see {@link https://docs.itick.org/rest-api/forex/forex-depths Official Documentation} for complete supported list * @param params.codes - Symbol code list (e.g., EURUSD, GBPUSD etc.) * @returns Promise wrapped API response, data is multiple forex latest order book data object {@link DepthDataMap} * @example * ```typescript * // Get latest order books for EURUSD and GBPUSD forex pairs * getDepths({ region: 'GB', codes: ['EURUSD', 'GBPUSD'] }).then(response => { * console.log('Latest order books:', response.data); * }).catch(err => { * console.error('Failed to get order books:', err); * }); * ``` */ async getDepths(params) { const { region, codes } = params; return this._get('/forex/depths', { region, codes: Array.isArray(codes) ? codes.join(',') : codes }); } /** * Get Multiple Forex K-Line Data * @description Query K-line data for multiple forex pairs based on market code, symbol code list, K-line period, end time and number of records to return * @param options - Query parameters object see {@link GetKlinesOptions} * @param options.region - Market code (e.g., GB etc.), see {@link https://docs.itick.org/rest-api/forex/forex-klines Official Documentation} for complete supported list * @param params.codes - Symbol code list (e.g., EURUSD, GBPUSD etc.) * @returns Promise wrapped API response, data is multiple forex K-line data object {@link KlineDataMap} * @example * ```typescript * // Get 5-minute K-line data for EURUSD and GBPUSD forex pairs * getKlines({ region: 'GB', codes: ['EURUSD', 'GBPUSD'], interval: '5m', limit: 100 }).then(response => { * console.log('K-line data:', response.data); * }).catch(err => { * console.error('Failed to get K-line data:', err); * }); * ``` */ async getKlines(options) { const { region, codes, kType, interval, limit, et } = options; const params = { region, codes: Array.isArray(codes) ? codes.join(',') : codes, kType: convertKlinePeriod(interval ??