FutureConnector.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. import {
  2. DERIVATIVES_TRADING_USDS_FUTURES_REST_API_PROD_URL,
  3. DerivativesTradingUsdsFutures,
  4. DerivativesTradingUsdsFuturesRestAPI,
  5. } from '@binance/derivatives-trading-usds-futures'
  6. export class FutureConnector {
  7. client: DerivativesTradingUsdsFutures
  8. constructor(apiKey: string, apiSecret: string) {
  9. const configurationRestAPI = {
  10. apiKey: apiKey,
  11. apiSecret: apiSecret,
  12. basePath: DERIVATIVES_TRADING_USDS_FUTURES_REST_API_PROD_URL,
  13. }
  14. this.client = new DerivativesTradingUsdsFutures({ configurationRestAPI })
  15. }
  16. async getAssetsInfo() {
  17. try {
  18. const response = await this.client.restAPI.accountInformationV3()
  19. const data = await response.data()
  20. return data.assets.filter((asset: any) => Number(asset.walletBalance) > 0)
  21. } catch (error) {
  22. console.error('accountInformation() error:', error)
  23. return []
  24. }
  25. }
  26. async getPositonInfo() {
  27. try {
  28. const response = await this.client.restAPI.accountInformationV3()
  29. const data = await response.data()
  30. return data.positions.filter((position: any) => Number(position.positionAmt) > 0)
  31. } catch (error) {
  32. console.error('futuresPositionInformation() error:', error)
  33. return []
  34. }
  35. }
  36. async getPositionBalanceBySymbol(symbol: string) {
  37. try {
  38. const response = await this.client.restAPI.accountInformationV3()
  39. const data = await response.data()
  40. const position = data.positions.find((pos: any) => pos.symbol === symbol)
  41. if (position) {
  42. return position
  43. } else {
  44. return null
  45. }
  46. } catch (error) {
  47. console.error('getPositionBalanceBySymbol() error:', error)
  48. return null
  49. }
  50. }
  51. async openModifyPosition(
  52. symbol: string,
  53. side: DerivativesTradingUsdsFuturesRestAPI.ModifyOrderSideEnum,
  54. quantity: number,
  55. price: number,
  56. ) {
  57. try {
  58. const response = await this.client.restAPI.modifyOrder({
  59. symbol: symbol,
  60. side: side,
  61. quantity: quantity,
  62. price: price,
  63. })
  64. return await response.data()
  65. } catch (error) {
  66. console.error('openPosition() error:', error)
  67. return null
  68. }
  69. }
  70. async getCurrentAllOpenPosition() {
  71. try {
  72. const response = await this.client.restAPI.currentAllOpenOrders()
  73. const data = await response.data()
  74. console.log('当前所有开仓订单响应:', data)
  75. } catch (error) {
  76. console.error('currentAllOpenOrders() error:', error)
  77. }
  78. }
  79. async openPosition(
  80. symbol: string,
  81. side: DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum,
  82. quantity: number,
  83. price: number,
  84. options?: any,
  85. ) {
  86. try {
  87. const orderParams: any = {
  88. symbol: symbol,
  89. side: side,
  90. type: options?.type || 'LIMIT',
  91. timeInForce: options?.timeInForce || DerivativesTradingUsdsFuturesRestAPI.NewOrderTimeInForceEnum.GTC,
  92. quantity: quantity,
  93. price: price,
  94. }
  95. if (options?.positionSide) {
  96. orderParams.positionSide = options.positionSide
  97. }
  98. if (options?.reduceOnly) {
  99. orderParams.reduceOnly = options.reduceOnly
  100. }
  101. if (options?.closePosition) {
  102. orderParams.closePosition = options.closePosition
  103. }
  104. if (options?.activationPrice) {
  105. orderParams.activationPrice = options.activationPrice
  106. }
  107. if (options?.callbackRate) {
  108. orderParams.callbackRate = options.callbackRate
  109. }
  110. if (options?.workingType) {
  111. orderParams.workingType = options.workingType
  112. }
  113. if (options?.priceProtect) {
  114. orderParams.priceProtect = options.priceProtect
  115. }
  116. if (options?.newOrderRespType) {
  117. orderParams.newOrderRespType = options.newOrderRespType
  118. }
  119. if (options?.newClientOrderId) {
  120. orderParams.newClientOrderId = options.newClientOrderId
  121. }
  122. if (options?.stopPrice) {
  123. orderParams.stopPrice = options.stopPrice
  124. }
  125. if (options?.icebergQty) {
  126. orderParams.icebergQty = options.icebergQty
  127. }
  128. if (options?.orderTag) {
  129. orderParams.orderTag = options.orderTag
  130. }
  131. console.log('下单参数:', orderParams)
  132. const response = await this.client.restAPI.newOrder(orderParams)
  133. const result = await response.data()
  134. console.log('下单成功:', result)
  135. return result
  136. } catch (error) {
  137. console.error('openPosition() 错误:', error)
  138. return null
  139. }
  140. }
  141. async openLimitOrder(
  142. symbol: string,
  143. side: 'long' | 'short',
  144. quantity: number,
  145. price: number,
  146. timeInForce: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'GTD' = 'GTC',
  147. ) {
  148. return this.openPosition(
  149. symbol,
  150. side === 'long'
  151. ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
  152. : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
  153. quantity,
  154. price,
  155. {
  156. type: 'LIMIT',
  157. timeInForce,
  158. positionSide:
  159. side === 'long'
  160. ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
  161. : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
  162. },
  163. )
  164. }
  165. async openMarketOrder(symbol: string, side: 'long' | 'short', quantity: number) {
  166. return this.openPosition(
  167. symbol,
  168. side === 'long'
  169. ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
  170. : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
  171. quantity,
  172. 0,
  173. {
  174. type: 'MARKET',
  175. positionSide:
  176. side === 'long'
  177. ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
  178. : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
  179. },
  180. )
  181. }
  182. async openStopOrder(
  183. symbol: string,
  184. side: 'long' | 'short',
  185. quantity: number,
  186. stopPrice: number,
  187. type: 'STOP' | 'STOP_MARKET' = 'STOP_MARKET',
  188. price?: number,
  189. timeInForce: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'GTD' = 'GTC',
  190. ) {
  191. const orderParams: any = {
  192. type,
  193. stopPrice,
  194. reduceOnly: 'true',
  195. positionSide:
  196. side === 'long'
  197. ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
  198. : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
  199. }
  200. if (type === 'STOP') {
  201. orderParams.timeInForce = timeInForce
  202. }
  203. return this.openPosition(
  204. symbol,
  205. side === 'long'
  206. ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
  207. : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
  208. quantity,
  209. price || 0,
  210. orderParams,
  211. )
  212. }
  213. async openTakeProfitOrder(
  214. symbol: string,
  215. side: 'long' | 'short',
  216. quantity: number,
  217. stopPrice: number,
  218. type: 'TAKE_PROFIT' | 'TAKE_PROFIT_MARKET' = 'TAKE_PROFIT_MARKET',
  219. price?: number,
  220. timeInForce: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'GTD' = 'GTC',
  221. ) {
  222. const orderParams: any = {
  223. type,
  224. stopPrice,
  225. reduceOnly: 'true',
  226. positionSide:
  227. side === 'long'
  228. ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
  229. : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
  230. }
  231. if (type === 'TAKE_PROFIT') {
  232. orderParams.timeInForce = timeInForce
  233. }
  234. return this.openPosition(
  235. symbol,
  236. side === 'long'
  237. ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
  238. : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
  239. quantity,
  240. price || 0,
  241. orderParams,
  242. )
  243. }
  244. async openTrailingStopOrder(
  245. symbol: string,
  246. side: 'long' | 'short',
  247. quantity: number,
  248. activationPrice: number,
  249. callbackRate: number,
  250. ) {
  251. return this.openPosition(
  252. symbol,
  253. side === 'long'
  254. ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
  255. : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
  256. quantity,
  257. 0,
  258. {
  259. type: 'TRAILING_STOP_MARKET',
  260. activationPrice,
  261. callbackRate,
  262. reduceOnly: 'true',
  263. positionSide:
  264. side === 'long'
  265. ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
  266. : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
  267. },
  268. )
  269. }
  270. async openIcebergOrder(
  271. symbol: string,
  272. side: 'long' | 'short',
  273. quantity: number,
  274. price: number,
  275. icebergQty: number,
  276. timeInForce: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'GTD' = 'GTC',
  277. ) {
  278. return this.openPosition(
  279. symbol,
  280. side === 'long'
  281. ? DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY
  282. : DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL,
  283. quantity,
  284. price,
  285. {
  286. type: 'LIMIT',
  287. timeInForce,
  288. icebergQty,
  289. positionSide:
  290. side === 'long'
  291. ? DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG
  292. : DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
  293. },
  294. )
  295. }
  296. async closeLongPosition(symbol: string, quantity: number) {
  297. return this.openPosition(symbol, DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.SELL, quantity, 0, {
  298. type: 'MARKET',
  299. reduceOnly: 'true',
  300. positionSide: DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.LONG,
  301. })
  302. }
  303. async closeShortPosition(symbol: string, quantity: number) {
  304. return this.openPosition(symbol, DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY, quantity, 0, {
  305. type: 'MARKET',
  306. reduceOnly: 'true',
  307. positionSide: DerivativesTradingUsdsFuturesRestAPI.NewOrderPositionSideEnum.SHORT,
  308. })
  309. }
  310. async closeAllPositions() {
  311. const positions = await this.getAllPositions()
  312. const results: any[] = []
  313. for (const pos of positions as any[]) {
  314. const amt = Number((pos as any).positionAmt)
  315. if (amt > 0) {
  316. results.push(await this.closeLongPosition((pos as any).symbol, Math.abs(amt)))
  317. } else if (amt < 0) {
  318. results.push(await this.closeShortPosition((pos as any).symbol, Math.abs(amt)))
  319. }
  320. }
  321. return results
  322. }
  323. async cancelOrder(symbol: string, orderId?: number, origClientOrderId?: string) {
  324. return this.client.restAPI.cancelOrder({ symbol, orderId, origClientOrderId })
  325. }
  326. async cancelAllOrders(symbol: string) {
  327. return this.client.restAPI.cancelAllOpenOrders({ symbol })
  328. }
  329. async getOrderHistory(symbol: string, startTime?: number, endTime?: number, limit: number = 100) {
  330. const response = await this.client.restAPI.allOrders({ symbol, startTime, endTime, limit })
  331. return response.data()
  332. }
  333. async getTradeHistory(symbol: string, startTime?: number, endTime?: number, limit: number = 100) {
  334. const response = await this.client.restAPI.accountTradeList({ symbol, startTime, endTime, limit })
  335. return response.data()
  336. }
  337. async setLeverage(symbol: string, leverage: number) {
  338. return this.client.restAPI.changeInitialLeverage({ symbol, leverage })
  339. }
  340. async setMarginType(symbol: string, marginType: DerivativesTradingUsdsFuturesRestAPI.ChangeMarginTypeMarginTypeEnum) {
  341. return this.client.restAPI.changeMarginType({ symbol, marginType })
  342. }
  343. async getAllPositions() {
  344. const response = await this.client.restAPI.accountInformationV3()
  345. const data = await response.data()
  346. return data.positions || []
  347. }
  348. async getExchangeInfo() {
  349. try {
  350. const response = await this.client.restAPI.exchangeInformation()
  351. return response.data()
  352. } catch (error) {
  353. console.error('getExchangeInfo() error:', error)
  354. return null
  355. }
  356. }
  357. async getSymbols(): Promise<string[]> {
  358. try {
  359. const exchangeInfo = await this.getExchangeInfo()
  360. if (!exchangeInfo?.symbols) return []
  361. return exchangeInfo.symbols.filter((s: any) => s.status === 'TRADING').map((s: any) => s.symbol)
  362. } catch (error) {
  363. console.error('getSymbols() error:', error)
  364. return []
  365. }
  366. }
  367. async getDepth(symbol: string, limit = 100) {
  368. try {
  369. const response = await this.client.restAPI.orderBook({ symbol, limit })
  370. return response.data()
  371. } catch (error) {
  372. console.error('getDepth() error:', error)
  373. return { bids: [], asks: [], lastUpdateId: 0 }
  374. }
  375. }
  376. async getCurrentAllOpenOrders(symbol?: string) {
  377. try {
  378. const response = await this.client.restAPI.currentAllOpenOrders({ symbol })
  379. return response.data()
  380. } catch (error) {
  381. console.error('getCurrentAllOpenOrders() error:', error)
  382. return []
  383. }
  384. }
  385. }
  386. // 移除重复导出,统一以本文件类为准