@yuants/vendor-binance 0.11.4 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/api/public-api.js.map +1 -1
  2. package/dist/index.js +2 -0
  3. package/dist/index.js.map +1 -1
  4. package/dist/public-data/quote.js +16 -2
  5. package/dist/public-data/quote.js.map +1 -1
  6. package/dist/services/accounts/unified.js +73 -54
  7. package/dist/services/accounts/unified.js.map +1 -1
  8. package/dist/services/exchange.js +4 -20
  9. package/dist/services/exchange.js.map +1 -1
  10. package/dist/services/interest-rate-service.js +76 -0
  11. package/dist/services/interest-rate-service.js.map +1 -0
  12. package/dist/services/ohlc-service.js +81 -0
  13. package/dist/services/ohlc-service.js.map +1 -0
  14. package/lib/api/public-api.d.ts +0 -5
  15. package/lib/api/public-api.d.ts.map +1 -1
  16. package/lib/api/public-api.js.map +1 -1
  17. package/lib/index.d.ts +2 -0
  18. package/lib/index.d.ts.map +1 -1
  19. package/lib/index.js +2 -0
  20. package/lib/index.js.map +1 -1
  21. package/lib/public-data/quote.js +15 -1
  22. package/lib/public-data/quote.js.map +1 -1
  23. package/lib/services/accounts/unified.d.ts +1 -1
  24. package/lib/services/accounts/unified.d.ts.map +1 -1
  25. package/lib/services/accounts/unified.js +74 -55
  26. package/lib/services/accounts/unified.js.map +1 -1
  27. package/lib/services/exchange.js +3 -19
  28. package/lib/services/exchange.js.map +1 -1
  29. package/lib/services/interest-rate-service.d.ts +2 -0
  30. package/lib/services/interest-rate-service.d.ts.map +1 -0
  31. package/lib/services/interest-rate-service.js +78 -0
  32. package/lib/services/interest-rate-service.js.map +1 -0
  33. package/lib/services/ohlc-service.d.ts +2 -0
  34. package/lib/services/ohlc-service.d.ts.map +1 -0
  35. package/lib/services/ohlc-service.js +83 -0
  36. package/lib/services/ohlc-service.js.map +1 -0
  37. package/package.json +15 -15
  38. package/temp/package-deps.json +24 -23
  39. package/dist/services/accounts/spot.js +0 -61
  40. package/dist/services/accounts/spot.js.map +0 -1
  41. package/lib/services/accounts/spot.d.ts +0 -4
  42. package/lib/services/accounts/spot.d.ts.map +0 -1
  43. package/lib/services/accounts/spot.js +0 -65
  44. package/lib/services/accounts/spot.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"public-api.js","sourceRoot":"","sources":["../../src/api/public-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAgGzC;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAiC,EAAE,CACtE,aAAa,CAAsB,KAAK,EAAE,+CAA+C,CAAC,CAAC;AAE7F;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,MAKpC,EAAsC,EAAE,CACvC,aAAa,CAA4B,KAAK,EAAE,8CAA8C,EAAE,MAAM,CAAC,CAAC;AAE1G;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,MAA2B,EAAuC,EAAE,CACxG,aAAa,CAA6B,KAAK,EAAE,+CAA+C,EAAE,MAAM,CAAC,CAAC;AAE5G;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAA4B,EAAqC,EAAE,CACrG,aAAa,CACX,KAAK,EACL,oDAAoD,EACpD,MAAM,CACP,CAAC;AAEJ;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,MAA0B,EAAgC,EAAE,CAChG,aAAa,CAAsB,KAAK,EAAE,+CAA+C,EAAE,MAAM,CAAC,CAAC;AASrG;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAA4B,EAAmC,EAAE,CACjG,aAAa,CAAyB,KAAK,EAAE,kDAAkD,EAAE,MAAM,CAAC,CAAC;AAwC3G;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAA+B,EAAE,CAClE,aAAa,CAAoB,KAAK,EAAE,6CAA6C,CAAC,CAAC;AAEzF;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,MAIlC,EASC,EAAE,CACF,aAAa,CASX,KAAK,EAAE,6CAA6C,EAAE,MAAM,CAAC,CAAC","sourcesContent":["import { requestPublic } from './client';\n\nexport interface IFutureExchangeFilter extends Record<string, string | number | boolean | undefined> {\n filterType: string;\n}\n\nexport interface IFutureExchangeSymbol {\n symbol: string;\n pair: string;\n contractType: string;\n deliveryDate: number;\n onboardDate: number;\n status: string;\n maintMarginPercent: string;\n requiredMarginPercent: string;\n baseAsset: string;\n quoteAsset: string;\n marginAsset: string;\n pricePrecision: number;\n quantityPrecision: number;\n baseAssetPrecision: number;\n quotePrecision: number;\n underlyingType: string;\n underlyingSubType: string[];\n settlePlan: number;\n triggerProtect: string;\n liquidationFee: string;\n marketTakeBound: string;\n maxMoveOrderLimit: number;\n filters: IFutureExchangeFilter[];\n orderTypes: string[];\n timeInForce: string[];\n}\n\nexport interface IFutureExchangeInfo {\n timezone: string;\n serverTime: number;\n futuresType: string;\n rateLimits: {\n rateLimitType: string;\n interval: string;\n intervalNum: number;\n limit: number;\n }[];\n exchangeFilters: unknown[];\n assets: {\n asset: string;\n marginAvailable: boolean;\n autoAssetExchange: string;\n }[];\n symbols: IFutureExchangeSymbol[];\n}\n\nexport interface IFutureFundingRateEntry {\n symbol: string;\n fundingTime: number;\n fundingRate: string;\n markPrice: string;\n}\n\nexport interface IFuturePremiumIndexEntry {\n symbol: string;\n markPrice: string;\n indexPrice: string;\n estimatedSettlePrice: string;\n lastFundingRate: string;\n interestRate: string;\n nextFundingTime: number;\n time: number;\n}\n\nexport interface IFutureBookTickerEntry {\n symbol: string;\n bidPrice: string;\n bidQty: string;\n askPrice: string;\n askQty: string;\n time: number;\n}\n\nexport interface IFutureOpenInterest {\n openInterest: string;\n symbol: string;\n time: number;\n}\n\nexport interface IMarginPair {\n id: string;\n symbol: string;\n base: string;\n quote: string;\n isMarginTrade: boolean;\n isBuyAllowed: boolean;\n isSellAllowed: boolean;\n}\n\n/**\n * 获取交易规则和交易对\n *\n * https://binance-docs.github.io/apidocs/futures/cn/#0f3f2d5ee7\n */\nexport const getFutureExchangeInfo = (): Promise<IFutureExchangeInfo> =>\n requestPublic<IFutureExchangeInfo>('GET', 'https://fapi.binance.com/fapi/v1/exchangeInfo');\n\n/**\n * 查询资金费率历史\n *\n * https://developers.binance.com/docs/zh-CN/derivatives/usds-margined-futures/market-data/rest-api/Get-Funding-Rate-History\n */\nexport const getFutureFundingRate = (params: {\n symbol?: string;\n startTime?: number;\n endTime?: number;\n limit?: number;\n}): Promise<IFutureFundingRateEntry[]> =>\n requestPublic<IFutureFundingRateEntry[]>('GET', 'https://fapi.binance.com/fapi/v1/fundingRate', params);\n\n/**\n * 最新标记价格和资金费率\n *\n * 采集各大交易所数据加权平均\n *\n * 权重: 带symbol为1;不带symbol为10\n *\n * https://developers.binance.com/docs/zh-CN/derivatives/usds-margined-futures/market-data/rest-api/Mark-Price\n */\nexport const getFuturePremiumIndex = (params: { symbol?: string }): Promise<IFuturePremiumIndexEntry[]> =>\n requestPublic<IFuturePremiumIndexEntry[]>('GET', 'https://fapi.binance.com/fapi/v1/premiumIndex', params);\n\n/**\n * 当前最优挂单\n *\n * 返回当前最优的挂单(最高买单,最低卖单)\n *\n * 权重: 单交易对2,无交易对5\n *\n * https://developers.binance.com/docs/zh-CN/derivatives/usds-margined-futures/market-data/rest-api/Symbol-Order-Book-Ticker\n */\nexport const getFutureBookTicker = (params?: { symbol?: string }): Promise<IFutureBookTickerEntry[]> =>\n requestPublic<IFutureBookTickerEntry[]>(\n 'GET',\n 'https://fapi.binance.com/fapi/v1/ticker/bookTicker',\n params,\n );\n\n/**\n * 获取未平仓合约数\n *\n * 权重: 1\n *\n * 更新速率: 3s\n *\n * https://developers.binance.com/docs/zh-CN/derivatives/usds-margined-futures/market-data/rest-api/Open-Interest\n */\nexport const getFutureOpenInterest = (params: { symbol: string }): Promise<IFutureOpenInterest> =>\n requestPublic<IFutureOpenInterest>('GET', 'https://fapi.binance.com/fapi/v1/openInterest', params);\nexport interface ISpotBookTickerEntry {\n symbol: string;\n bidPrice: string;\n bidQty: string;\n askPrice: string;\n askQty: string;\n}\n\n/**\n * 当前最优挂单 (Spot)\n *\n * https://binance-docs.github.io/apidocs/spot/cn/#5393cd0851\n */\nexport const getSpotBookTicker = (params?: { symbol?: string }): Promise<ISpotBookTickerEntry[]> =>\n requestPublic<ISpotBookTickerEntry[]>('GET', 'https://api.binance.com/api/v3/ticker/bookTicker', params);\n\nexport interface ISpotExchangeFilter extends Record<string, string | number | boolean | undefined> {\n filterType: string;\n}\n\nexport interface ISpotExchangeSymbol {\n symbol: string;\n status: string;\n baseAsset: string;\n baseAssetPrecision: number;\n quoteAsset: string;\n quotePrecision: number;\n baseCommissionPrecision: number;\n quoteCommissionPrecision: number;\n orderTypes: string[];\n icebergAllowed: boolean;\n ocoAllowed: boolean;\n quoteOrderQtyMarketAllowed: boolean;\n allowTrailingStop: boolean;\n cancelReplaceAllowed: boolean;\n isSpotTradingAllowed: boolean;\n isMarginTradingAllowed: boolean;\n filters: ISpotExchangeFilter[];\n permissions: string[];\n}\n\nexport interface ISpotExchangeInfo {\n timezone: string;\n serverTime: number;\n rateLimits: {\n rateLimitType: string;\n interval: string;\n intervalNum: number;\n limit: number;\n }[];\n exchangeFilters: unknown[];\n symbols: ISpotExchangeSymbol[];\n}\n\n/**\n * 获取现货交易规则和交易对\n *\n * https://developers.binance.com/docs/zh-CN/binance-spot-api-docs/rest-api/general-endpoints#%E4%BA%A4%E6%98%93%E8%A7%84%E8%8C%83%E4%BF%A1%E6%81%AF\n */\nexport const getSpotExchangeInfo = (): Promise<ISpotExchangeInfo> =>\n requestPublic<ISpotExchangeInfo>('GET', 'https://api.binance.com/api/v3/exchangeInfo');\n\n/**\n * 获取当前现货报价\n *\n *https://developers.binance.com/docs/zh-CN/binance-spot-api-docs/rest-api/market-data-endpoints#%E6%9C%80%E6%96%B0%E4%BB%B7%E6%A0%BC%E6%8E%A5%E5%8F%A3\n */\nexport const getSpotTickerPrice = (params?: {\n symbol?: string;\n symbols?: string;\n symbolStatus?: 'TRADING' | 'HALT' | 'BREAK';\n}): Promise<\n | {\n symbol: string;\n price: string;\n }\n | {\n symbol: string;\n price: string;\n }[]\n> =>\n requestPublic<\n | {\n symbol: string;\n price: string;\n }\n | {\n symbol: string;\n price: string;\n }[]\n >('GET', 'https://api.binance.com/api/v3/ticker/price', params);\n"]}
1
+ {"version":3,"file":"public-api.js","sourceRoot":"","sources":["../../src/api/public-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAgGzC;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAiC,EAAE,CACtE,aAAa,CAAsB,KAAK,EAAE,+CAA+C,CAAC,CAAC;AAE7F;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,MAKpC,EAAsC,EAAE,CACvC,aAAa,CAA4B,KAAK,EAAE,8CAA8C,EAAE,MAAM,CAAC,CAAC;AAE1G;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,MAA2B,EAAuC,EAAE,CACxG,aAAa,CAA6B,KAAK,EAAE,+CAA+C,EAAE,MAAM,CAAC,CAAC;AAE5G;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAA4B,EAAqC,EAAE,CACrG,aAAa,CACX,KAAK,EACL,oDAAoD,EACpD,MAAM,CACP,CAAC;AAEJ;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,MAA0B,EAAgC,EAAE,CAChG,aAAa,CAAsB,KAAK,EAAE,+CAA+C,EAAE,MAAM,CAAC,CAAC;AASrG;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAA4B,EAAmC,EAAE,CACjG,aAAa,CAAyB,KAAK,EAAE,kDAAkD,EAAE,MAAM,CAAC,CAAC;AAwC3G;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAA+B,EAAE,CAClE,aAAa,CAAoB,KAAK,EAAE,6CAA6C,CAAC,CAAC;AAEzF;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,MAElC,EAKC,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,6CAA6C,EAAE,MAAM,CAAC,CAAC","sourcesContent":["import { requestPublic } from './client';\n\nexport interface IFutureExchangeFilter extends Record<string, string | number | boolean | undefined> {\n filterType: string;\n}\n\nexport interface IFutureExchangeSymbol {\n symbol: string;\n pair: string;\n contractType: string;\n deliveryDate: number;\n onboardDate: number;\n status: string;\n maintMarginPercent: string;\n requiredMarginPercent: string;\n baseAsset: string;\n quoteAsset: string;\n marginAsset: string;\n pricePrecision: number;\n quantityPrecision: number;\n baseAssetPrecision: number;\n quotePrecision: number;\n underlyingType: string;\n underlyingSubType: string[];\n settlePlan: number;\n triggerProtect: string;\n liquidationFee: string;\n marketTakeBound: string;\n maxMoveOrderLimit: number;\n filters: IFutureExchangeFilter[];\n orderTypes: string[];\n timeInForce: string[];\n}\n\nexport interface IFutureExchangeInfo {\n timezone: string;\n serverTime: number;\n futuresType: string;\n rateLimits: {\n rateLimitType: string;\n interval: string;\n intervalNum: number;\n limit: number;\n }[];\n exchangeFilters: unknown[];\n assets: {\n asset: string;\n marginAvailable: boolean;\n autoAssetExchange: string;\n }[];\n symbols: IFutureExchangeSymbol[];\n}\n\nexport interface IFutureFundingRateEntry {\n symbol: string;\n fundingTime: number;\n fundingRate: string;\n markPrice: string;\n}\n\nexport interface IFuturePremiumIndexEntry {\n symbol: string;\n markPrice: string;\n indexPrice: string;\n estimatedSettlePrice: string;\n lastFundingRate: string;\n interestRate: string;\n nextFundingTime: number;\n time: number;\n}\n\nexport interface IFutureBookTickerEntry {\n symbol: string;\n bidPrice: string;\n bidQty: string;\n askPrice: string;\n askQty: string;\n time: number;\n}\n\nexport interface IFutureOpenInterest {\n openInterest: string;\n symbol: string;\n time: number;\n}\n\nexport interface IMarginPair {\n id: string;\n symbol: string;\n base: string;\n quote: string;\n isMarginTrade: boolean;\n isBuyAllowed: boolean;\n isSellAllowed: boolean;\n}\n\n/**\n * 获取交易规则和交易对\n *\n * https://binance-docs.github.io/apidocs/futures/cn/#0f3f2d5ee7\n */\nexport const getFutureExchangeInfo = (): Promise<IFutureExchangeInfo> =>\n requestPublic<IFutureExchangeInfo>('GET', 'https://fapi.binance.com/fapi/v1/exchangeInfo');\n\n/**\n * 查询资金费率历史\n *\n * https://developers.binance.com/docs/zh-CN/derivatives/usds-margined-futures/market-data/rest-api/Get-Funding-Rate-History\n */\nexport const getFutureFundingRate = (params: {\n symbol?: string;\n startTime?: number;\n endTime?: number;\n limit?: number;\n}): Promise<IFutureFundingRateEntry[]> =>\n requestPublic<IFutureFundingRateEntry[]>('GET', 'https://fapi.binance.com/fapi/v1/fundingRate', params);\n\n/**\n * 最新标记价格和资金费率\n *\n * 采集各大交易所数据加权平均\n *\n * 权重: 带symbol为1;不带symbol为10\n *\n * https://developers.binance.com/docs/zh-CN/derivatives/usds-margined-futures/market-data/rest-api/Mark-Price\n */\nexport const getFuturePremiumIndex = (params: { symbol?: string }): Promise<IFuturePremiumIndexEntry[]> =>\n requestPublic<IFuturePremiumIndexEntry[]>('GET', 'https://fapi.binance.com/fapi/v1/premiumIndex', params);\n\n/**\n * 当前最优挂单\n *\n * 返回当前最优的挂单(最高买单,最低卖单)\n *\n * 权重: 单交易对2,无交易对5\n *\n * https://developers.binance.com/docs/zh-CN/derivatives/usds-margined-futures/market-data/rest-api/Symbol-Order-Book-Ticker\n */\nexport const getFutureBookTicker = (params?: { symbol?: string }): Promise<IFutureBookTickerEntry[]> =>\n requestPublic<IFutureBookTickerEntry[]>(\n 'GET',\n 'https://fapi.binance.com/fapi/v1/ticker/bookTicker',\n params,\n );\n\n/**\n * 获取未平仓合约数\n *\n * 权重: 1\n *\n * 更新速率: 3s\n *\n * https://developers.binance.com/docs/zh-CN/derivatives/usds-margined-futures/market-data/rest-api/Open-Interest\n */\nexport const getFutureOpenInterest = (params: { symbol: string }): Promise<IFutureOpenInterest> =>\n requestPublic<IFutureOpenInterest>('GET', 'https://fapi.binance.com/fapi/v1/openInterest', params);\nexport interface ISpotBookTickerEntry {\n symbol: string;\n bidPrice: string;\n bidQty: string;\n askPrice: string;\n askQty: string;\n}\n\n/**\n * 当前最优挂单 (Spot)\n *\n * https://binance-docs.github.io/apidocs/spot/cn/#5393cd0851\n */\nexport const getSpotBookTicker = (params?: { symbol?: string }): Promise<ISpotBookTickerEntry[]> =>\n requestPublic<ISpotBookTickerEntry[]>('GET', 'https://api.binance.com/api/v3/ticker/bookTicker', params);\n\nexport interface ISpotExchangeFilter extends Record<string, string | number | boolean | undefined> {\n filterType: string;\n}\n\nexport interface ISpotExchangeSymbol {\n symbol: string;\n status: string;\n baseAsset: string;\n baseAssetPrecision: number;\n quoteAsset: string;\n quotePrecision: number;\n baseCommissionPrecision: number;\n quoteCommissionPrecision: number;\n orderTypes: string[];\n icebergAllowed: boolean;\n ocoAllowed: boolean;\n quoteOrderQtyMarketAllowed: boolean;\n allowTrailingStop: boolean;\n cancelReplaceAllowed: boolean;\n isSpotTradingAllowed: boolean;\n isMarginTradingAllowed: boolean;\n filters: ISpotExchangeFilter[];\n permissions: string[];\n}\n\nexport interface ISpotExchangeInfo {\n timezone: string;\n serverTime: number;\n rateLimits: {\n rateLimitType: string;\n interval: string;\n intervalNum: number;\n limit: number;\n }[];\n exchangeFilters: unknown[];\n symbols: ISpotExchangeSymbol[];\n}\n\n/**\n * 获取现货交易规则和交易对\n *\n * https://developers.binance.com/docs/zh-CN/binance-spot-api-docs/rest-api/general-endpoints#%E4%BA%A4%E6%98%93%E8%A7%84%E8%8C%83%E4%BF%A1%E6%81%AF\n */\nexport const getSpotExchangeInfo = (): Promise<ISpotExchangeInfo> =>\n requestPublic<ISpotExchangeInfo>('GET', 'https://api.binance.com/api/v3/exchangeInfo');\n\n/**\n * 获取当前现货报价\n *\n *https://developers.binance.com/docs/zh-CN/binance-spot-api-docs/rest-api/market-data-endpoints#%E6%9C%80%E6%96%B0%E4%BB%B7%E6%A0%BC%E6%8E%A5%E5%8F%A3\n */\nexport const getSpotTickerPrice = (params?: {\n symbolStatus?: 'TRADING' | 'HALT' | 'BREAK';\n}): Promise<\n {\n symbol: string;\n price: string;\n }[]\n> => requestPublic('GET', 'https://api.binance.com/api/v3/ticker/price', params);\n"]}
package/dist/index.js CHANGED
@@ -4,4 +4,6 @@ import './public-data/product';
4
4
  import './public-data/quote';
5
5
  import './services/exchange';
6
6
  import './services/quotes';
7
+ import './services/ohlc-service';
8
+ import './services/interest-rate-service';
7
9
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,6BAA6B,CAAC;AACrC,OAAO,oBAAoB,CAAC;AAC5B,OAAO,uBAAuB,CAAC;AAC/B,OAAO,qBAAqB,CAAC;AAC7B,OAAO,qBAAqB,CAAC;AAC7B,OAAO,mBAAmB,CAAC","sourcesContent":["import './public-data/interest_rate';\nimport './public-data/ohlc';\nimport './public-data/product';\nimport './public-data/quote';\nimport './services/exchange';\nimport './services/quotes';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,6BAA6B,CAAC;AACrC,OAAO,oBAAoB,CAAC;AAC5B,OAAO,uBAAuB,CAAC;AAC/B,OAAO,qBAAqB,CAAC;AAC7B,OAAO,qBAAqB,CAAC;AAC7B,OAAO,mBAAmB,CAAC;AAC3B,OAAO,yBAAyB,CAAC;AACjC,OAAO,kCAAkC,CAAC","sourcesContent":["import './public-data/interest_rate';\nimport './public-data/ohlc';\nimport './public-data/product';\nimport './public-data/quote';\nimport './services/exchange';\nimport './services/quotes';\nimport './services/ohlc-service';\nimport './services/interest-rate-service';\n"]}
@@ -5,7 +5,7 @@ import { writeToSQL } from '@yuants/sql';
5
5
  import { decodePath, encodePath, formatTime } from '@yuants/utils';
6
6
  import { catchError, combineLatest, concatMap, defer, exhaustMap, filter, from, groupBy, map, merge, mergeMap, of, repeat, retry, scan, share, shareReplay, tap, timer, } from 'rxjs';
7
7
  import { getMarginAllPairs, getMarginNextHourlyInterestRate } from '../api/private-api';
8
- import { getFutureBookTicker, getFutureExchangeInfo, getFutureOpenInterest, getFuturePremiumIndex, getSpotBookTicker, getSpotExchangeInfo, } from '../api/public-api';
8
+ import { getFutureBookTicker, getFutureExchangeInfo, getFutureOpenInterest, getFuturePremiumIndex, getSpotBookTicker, getSpotExchangeInfo, getSpotTickerPrice, } from '../api/public-api';
9
9
  const terminal = Terminal.fromNodeEnv();
10
10
  const DEFAULT_OPEN_INTEREST_REQUEST_INTERVAL_MS = 500;
11
11
  const DEFAULT_MARGIN_RATE_REQUEST_INTERVAL_MS = 500;
@@ -62,6 +62,20 @@ const futureRequestInterval$ = defer(() => getFutureExchangeInfo()).pipe(map((in
62
62
  }));
63
63
  const futurePremiumIndex$ = defer(() => getFuturePremiumIndex({})).pipe(repeat({ delay: 1000 }), retry({ delay: 30000 }), shareReplay({ bufferSize: 1, refCount: true }));
64
64
  const futureBookTicker$ = defer(() => getFutureBookTicker({})).pipe(repeat({ delay: 1000 }), retry({ delay: 30000 }), shareReplay({ bufferSize: 1, refCount: true }));
65
+ const quoteFromSpotTicker$ = defer(() => getSpotTickerPrice({})).pipe(mergeMap((entries) => from(entries || [])), mergeMap((entry) => [
66
+ {
67
+ datasource_id: 'BINANCE',
68
+ product_id: encodePath('BINANCE', 'SPOT', entry.symbol),
69
+ last_price: entry.price,
70
+ updated_at: formatTime(Date.now()),
71
+ },
72
+ {
73
+ datasource_id: 'BINANCE',
74
+ product_id: encodePath('BINANCE', 'MARGIN', entry.symbol),
75
+ last_price: entry.price,
76
+ updated_at: formatTime(Date.now()),
77
+ },
78
+ ]), repeat({ delay: 1000 }), retry({ delay: 1000 }));
65
79
  const quoteFromPremiumIndex$ = futurePremiumIndex$.pipe(mergeMap((entries) => from(entries || [])), map((entry) => {
66
80
  var _a;
67
81
  return ({
@@ -139,7 +153,7 @@ const quoteFromMarginRates$ = combineLatest([marginPairs$, spotRequestInterval$]
139
153
  interest_rate_short: baseRate,
140
154
  updated_at: formatTime(Date.now()),
141
155
  })))))))), repeat({ delay: 60000 }));
142
- const quote$ = merge(quoteFromPremiumIndex$, quoteFromBookTicker$, quoteFromOpenInterest$, quoteFromSpotBookTicker$, quoteFromMarginRates$).pipe(groupBy((quote) => quote.product_id), mergeMap((group$) => group$.pipe(scan((acc, cur) => Object.assign(acc, cur, {
156
+ const quote$ = merge(quoteFromPremiumIndex$, quoteFromBookTicker$, quoteFromOpenInterest$, quoteFromSpotBookTicker$, quoteFromMarginRates$, quoteFromSpotTicker$).pipe(groupBy((quote) => quote.product_id), mergeMap((group$) => group$.pipe(scan((acc, cur) => Object.assign(acc, cur, {
143
157
  datasource_id: 'BINANCE',
144
158
  product_id: group$.key,
145
159
  }), {}))), share(), shareReplay({ bufferSize: 1, refCount: true }));
@@ -1 +1 @@
1
- {"version":3,"file":"quote.js","sourceRoot":"","sources":["../../src/public-data/quote.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAU,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EACL,UAAU,EACV,aAAa,EACb,SAAS,EACT,KAAK,EACL,UAAU,EACV,MAAM,EACN,IAAI,EACJ,OAAO,EACP,GAAG,EACH,KAAK,EACL,QAAQ,EACR,EAAE,EACF,MAAM,EACN,KAAK,EACL,IAAI,EACJ,KAAK,EACL,WAAW,EACX,GAAG,EACH,KAAK,GACN,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,iBAAiB,EAAE,+BAA+B,EAAe,MAAM,oBAAoB,CAAC;AACrG,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AACxC,MAAM,yCAAyC,GAAG,GAAG,CAAC;AACtD,MAAM,uCAAuC,GAAG,GAAG,CAAC;AACpD,MAAM,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,MAAO,CAAC;AAS1G,MAAM,YAAY,GAAG,CAAC,QAAiB,EAAE,WAAoB,EAAE,EAAE;IAC/D,QAAQ,QAAQ,EAAE;QAChB,KAAK,QAAQ;YACX,OAAO,CAAC,WAAW,aAAX,WAAW,cAAX,WAAW,GAAI,CAAC,CAAC,GAAG,IAAK,CAAC;QACpC,KAAK,QAAQ;YACX,OAAO,CAAC,WAAW,aAAX,WAAW,cAAX,WAAW,GAAI,CAAC,CAAC,GAAG,KAAM,CAAC;QACrC,KAAK,MAAM;YACT,OAAO,CAAC,WAAW,aAAX,WAAW,cAAX,WAAW,GAAI,CAAC,CAAC,GAAG,OAAS,CAAC;QACxC,KAAK,KAAK;YACR,OAAO,CAAC,WAAW,aAAX,WAAW,cAAX,WAAW,GAAI,CAAC,CAAC,GAAG,QAAU,CAAC;QACzC;YACE,OAAO,SAAS,CAAC;KACpB;AACH,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAAC,UAAoC,EAAE,UAAkB,EAAE,EAAE;IACxF,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,UAAU,aAAV,UAAU,cAAV,UAAU,GAAI,EAAE,EAAE;QACnC,IAAI,IAAI,CAAC,aAAa,KAAK,gBAAgB,IAAI,IAAI,CAAC,aAAa,KAAK,cAAc;YAAE,SAAS;QAC/F,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC/D,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,IAAI,QAAQ,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC;YAAE,SAAS;QAC9D,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC;KAC7C;IACD,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACjC,IAAI,CAAC,SAAS,CAAC,MAAM;QAAE,OAAO,UAAU,CAAC;IACzC,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,WAAW,CACnC,KAAK,EAAE,MAAc,EAAE,EAAE;;IACvB,IAAI;QACF,MAAM,IAAI,GAAG,MAAM,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACrD,OAAO,MAAM,CAAC,MAAA,IAAI,CAAC,YAAY,mCAAI,CAAC,CAAC,CAAC;KACvC;IAAC,OAAO,GAAG,EAAE;QACZ,OAAO,CAAC,IAAI,CAAC,8BAA8B,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;QAC1D,OAAO,SAAS,CAAC;KAClB;AACH,CAAC,EACD;IACE,MAAM,EAAE,iBAAiB;CAC1B,CACF,CAAC;AAEF,MAAM,sBAAsB,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CACtE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,UAAU,EAAE,yCAAyC,CAAC,CAAC,EAC/F,UAAU,CAAC,CAAC,GAAG,EAAE,EAAE;IACjB,OAAO,CAAC,IAAI,CAAC,gEAAgE,EAAE,GAAG,CAAC,CAAC;IACpF,OAAO,EAAE,CAAC,yCAAyC,CAAC,CAAC;AACvD,CAAC,CAAC,EACF,KAAK,CAAC,EAAE,KAAK,EAAE,KAAM,EAAE,CAAC,EACxB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAC9C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;IACR,OAAO,CAAC,IAAI,CAAC,2CAA2C,CAAC,KAAK,CAAC,CAAC;AAClE,CAAC,CAAC,CACH,CAAC;AAEF,MAAM,mBAAmB,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CACrE,MAAM,CAAC,EAAE,KAAK,EAAE,IAAK,EAAE,CAAC,EACxB,KAAK,CAAC,EAAE,KAAK,EAAE,KAAM,EAAE,CAAC,EACxB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAC/C,CAAC;AAEF,MAAM,iBAAiB,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CACjE,MAAM,CAAC,EAAE,KAAK,EAAE,IAAK,EAAE,CAAC,EACxB,KAAK,CAAC,EAAE,KAAK,EAAE,KAAM,EAAE,CAAC,EACxB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAC/C,CAAC;AAEF,MAAM,sBAAsB,GAAG,mBAAmB,CAAC,IAAI,CACrD,QAAQ,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,EAC1C,GAAG,CACD,CAAC,KAAK,EAAmB,EAAE;;IAAC,OAAA,CAAC;QAC3B,aAAa,EAAE,SAAS;QACxB,UAAU,EAAE,UAAU,CAAC,SAAS,EAAE,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC;QAC9D,UAAU,EAAE,KAAK,CAAC,SAAS;QAC3B,qEAAqE;QACrE,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE;QACvD,mBAAmB,EAAE,KAAK,CAAC,eAAe;QAC1C,6BAA6B,EAAE,UAAU,CAAC,KAAK,CAAC,eAAe,CAAC;QAChE,UAAU,EAAE,UAAU,CAAC,MAAA,KAAK,CAAC,IAAI,mCAAI,IAAI,CAAC,GAAG,EAAE,CAAC;KACjD,CAAC,CAAA;CAAA,CACH,CACF,CAAC;AAEF,MAAM,oBAAoB,GAAG,iBAAiB,CAAC,IAAI,CACjD,QAAQ,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,EAC1C,GAAG,CACD,CAAC,KAAK,EAAmB,EAAE;;IAAC,OAAA,CAAC;QAC3B,aAAa,EAAE,SAAS;QACxB,UAAU,EAAE,UAAU,CAAC,SAAS,EAAE,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC;QAC9D,SAAS,EAAE,KAAK,CAAC,QAAQ;QACzB,SAAS,EAAE,KAAK,CAAC,QAAQ;QACzB,UAAU,EAAE,UAAU,CAAC,MAAA,KAAK,CAAC,IAAI,mCAAI,IAAI,CAAC,GAAG,EAAE,CAAC;KACjD,CAAC,CAAA;CAAA,CACH,CACF,CAAC;AAEF,MAAM,sBAAsB,GAAG,aAAa,CAAC,CAAC,iBAAiB,EAAE,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAC5F,UAAU,CAAC,CAAC,CAAC,OAAO,EAAE,eAAe,CAAC,EAAE,EAAE,CACxC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,CACtB,SAAS,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CACzB,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC/C,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAC3D,GAAG,CACD,CAAC,YAAY,EAAmB,EAAE,CAAC,CAAC;IAClC,aAAa,EAAE,SAAS;IACxB,UAAU,EAAE,UAAU,CAAC,SAAS,EAAE,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC;IAC9D,aAAa,EAAE,GAAG,YAAY,aAAZ,YAAY,cAAZ,YAAY,GAAI,CAAC,EAAE;CACtC,CAAC,CACH,CACF,CACF,CACF,CACF,CACF,CAAC;AAEF,MAAM,wBAAwB,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CACtE,QAAQ,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,EAC1C,GAAG,CACD,CAAC,KAAK,EAAmB,EAAE,CAAC,CAAC;IAC3B,aAAa,EAAE,SAAS;IACxB,UAAU,EAAE,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;IACvD,SAAS,EAAE,KAAK,CAAC,QAAQ;IACzB,SAAS,EAAE,KAAK,CAAC,QAAQ;IACzB,UAAU,EAAE,KAAK,CAAC,MAAM;IACxB,UAAU,EAAE,KAAK,CAAC,MAAM;IACxB,UAAU,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;CACnC,CAAC,CACH,EACD,MAAM,CAAC,EAAE,KAAK,EAAE,IAAK,EAAE,CAAC,EACxB,KAAK,CAAC,EAAE,KAAK,EAAE,KAAM,EAAE,CAAC,EACxB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAC/C,CAAC;AAEF,MAAM,uBAAuB,GAAG,WAAW,CACzC,KAAK,EAAE,KAAa,EAAE,EAAE;;IACtB,IAAI;QACF,MAAM,IAAI,GAAG,MAAM,+BAA+B,CAAC;YACjD,MAAM,EAAE,KAAK;YACb,UAAU,EAAE,KAAK;SAClB,CAAC,CAAC;QACH,OAAO,MAAA,IAAI,CAAC,CAAC,CAAC,0CAAE,sBAAsB,CAAC;KACxC;IAAC,OAAO,GAAG,EAAE;QACZ,OAAO,SAAS,CAAC;KAClB;AACH,CAAC,EACD;IACE,MAAM,EAAE,KAAM;CACf,CACF,CAAC;AAEF,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CACxD,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;IACZ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;QACzB,OAAO,CAAC,IAAI,CAAC,8CAA8C,EAAE,KAAK,CAAC,CAAC;QACpE,OAAO,EAAE,CAAC;KACX;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC,EACF,UAAU,CAAC,CAAC,GAAG,EAAE,EAAE;IACjB,OAAO,CAAC,IAAI,CAAC,0BAA0B,EAAE,GAAG,CAAC,CAAC;IAC9C,OAAO,EAAE,CAAC,EAAmB,CAAC,CAAC;AACjC,CAAC,CAAC,EACF,MAAM,CAAC,EAAE,KAAK,EAAE,OAAQ,EAAE,CAAC,EAAE,2BAA2B;AACxD,KAAK,CAAC,EAAE,KAAK,EAAE,KAAM,EAAE,CAAC,EACxB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAC/C,CAAC;AAEF,MAAM,oBAAoB,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,mBAAmB,EAAE,CAAC,CAAC,IAAI,CAClE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,UAAU,EAAE,uCAAuC,CAAC,CAAC,EAC7F,UAAU,CAAC,CAAC,GAAG,EAAE,EAAE;IACjB,OAAO,CAAC,IAAI,CAAC,8DAA8D,EAAE,GAAG,CAAC,CAAC;IAClF,OAAO,EAAE,CAAC,uCAAuC,CAAC,CAAC;AACrD,CAAC,CAAC,EACF,KAAK,CAAC,EAAE,KAAK,EAAE,KAAM,EAAE,CAAC,EACxB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAC9C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;IACR,OAAO,CAAC,IAAI,CAAC,yCAAyC,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC,CAAC,CACH,CAAC;AAEF,MAAM,qBAAqB,GAAG,aAAa,CAAC,CAAC,YAAY,EAAE,oBAAoB,CAAC,CAAC,CAAC,IAAI,CACpF,QAAQ,CAAC,CAAC,CAAC,KAAK,EAAE,eAAe,CAAC,EAAE,EAAE,CACpC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CACd,SAAS,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACxB,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC/C,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAC9D,QAAQ,CAAC,CAAC,QAAQ,EAAE,EAAE,CACpB,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,CACzB,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAC/D,GAAG,CACD,CAAC,SAAS,EAAmB,EAAE,CAAC,CAAC;IAC/B,aAAa,EAAE,SAAS;IACxB,UAAU,EAAE,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;IACtD,yDAAyD;IACzD,kBAAkB,EAAE,SAAS;IAC7B,mBAAmB,EAAE,QAAQ;IAC7B,UAAU,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;CACnC,CAAC,CACH,CACF,CACF,CACF,CACF,CACF,CACF,EACD,MAAM,CAAC,EAAE,KAAK,EAAE,KAAM,EAAE,CAAC,CAC1B,CAAC;AAEF,MAAM,MAAM,GAAG,KAAK,CAClB,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,CACtB,CAAC,IAAI,CACJ,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,EACpC,QAAQ,CAAC,CAAC,MAAM,EAAE,EAAE,CAClB,MAAM,CAAC,IAAI,CACT,IAAI,CACF,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CACX,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE;IACtB,aAAa,EAAE,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC,GAAG;CACvB,CAAC,EACJ,EAAqB,CACtB,CACF,CACF,EACD,KAAK,EAAE,EACP,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAC/C,CAAC;AAEF,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,KAAK,MAAM,EAAE;IAC7C,MAAM;SACH,IAAI,CACH,oBAAoB,CAAC,QAAQ,CAAC,WAAW,CAAC,EAC1C,UAAU,CAAC;QACT,QAAQ;QACR,SAAS,EAAE,OAAO;QAClB,aAAa,EAAE,IAAK;QACpB,YAAY,EAAE,CAAC,eAAe,EAAE,YAAY,CAAC;KAC9C,CAAC,CACH;SACA,SAAS,EAAE,CAAC;IAEf,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,CAAC,UAAU,EAAE,EAAE;QAChF,MAAM,CAAC,YAAY,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;QACzD,IAAI,CAAC,YAAY,IAAI,CAAC,SAAS,EAAE;YAC/B,MAAM,IAAI,KAAK,CAAC,uBAAuB,UAAU,EAAE,CAAC,CAAC;SACtD;QACD,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;CACJ","sourcesContent":["import { createCache } from '@yuants/cache';\nimport { IQuote, setMetricsQuoteState } from '@yuants/data-quote';\nimport { Terminal } from '@yuants/protocol';\nimport { writeToSQL } from '@yuants/sql';\nimport { decodePath, encodePath, formatTime } from '@yuants/utils';\nimport {\n catchError,\n combineLatest,\n concatMap,\n defer,\n exhaustMap,\n filter,\n from,\n groupBy,\n map,\n merge,\n mergeMap,\n of,\n repeat,\n retry,\n scan,\n share,\n shareReplay,\n tap,\n timer,\n} from 'rxjs';\nimport { getMarginAllPairs, getMarginNextHourlyInterestRate, IMarginPair } from '../api/private-api';\nimport {\n getFutureBookTicker,\n getFutureExchangeInfo,\n getFutureOpenInterest,\n getFuturePremiumIndex,\n getSpotBookTicker,\n getSpotExchangeInfo,\n} from '../api/public-api';\n\nconst terminal = Terminal.fromNodeEnv();\nconst DEFAULT_OPEN_INTEREST_REQUEST_INTERVAL_MS = 500;\nconst DEFAULT_MARGIN_RATE_REQUEST_INTERVAL_MS = 500;\nconst OPEN_INTEREST_TTL = process.env.OPEN_INTEREST_TTL ? Number(process.env.OPEN_INTEREST_TTL) : 300_000;\n\ninterface IRateLimit {\n rateLimitType?: string;\n interval?: string;\n intervalNum?: number;\n limit?: number;\n}\n\nconst toIntervalMs = (interval?: string, intervalNum?: number) => {\n switch (interval) {\n case 'SECOND':\n return (intervalNum ?? 1) * 1_000;\n case 'MINUTE':\n return (intervalNum ?? 1) * 60_000;\n case 'HOUR':\n return (intervalNum ?? 1) * 3_600_000;\n case 'DAY':\n return (intervalNum ?? 1) * 86_400_000;\n default:\n return undefined;\n }\n};\n\nconst getRequestIntervalMs = (rateLimits: IRateLimit[] | undefined, fallbackMs: number) => {\n const intervals: number[] = [];\n for (const item of rateLimits ?? []) {\n if (item.rateLimitType !== 'REQUEST_WEIGHT' && item.rateLimitType !== 'RAW_REQUESTS') continue;\n const duration = toIntervalMs(item.interval, item.intervalNum);\n console.info('!!!!!', item, duration);\n const limit = item.limit;\n if (duration == null || limit == null || limit <= 0) continue;\n intervals.push(Math.ceil(duration / limit));\n }\n console.info('!!!!!', intervals);\n if (!intervals.length) return fallbackMs;\n return Math.max(fallbackMs, Math.max(...intervals));\n};\n\nconst openInterestCache = createCache<number>(\n async (symbol: string) => {\n try {\n const data = await getFutureOpenInterest({ symbol });\n return Number(data.openInterest ?? 0);\n } catch (err) {\n console.warn('getFutureOpenInterest failed', symbol, err);\n return undefined;\n }\n },\n {\n expire: OPEN_INTEREST_TTL,\n },\n);\n\nconst futureRequestInterval$ = defer(() => getFutureExchangeInfo()).pipe(\n map((info) => getRequestIntervalMs(info.rateLimits, DEFAULT_OPEN_INTEREST_REQUEST_INTERVAL_MS)),\n catchError((err) => {\n console.warn('getFutureExchangeInfo failed when calculating request interval', err);\n return of(DEFAULT_OPEN_INTEREST_REQUEST_INTERVAL_MS);\n }),\n retry({ delay: 60_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n tap((v) => {\n console.info(`!!!!Determined future request interval: ${v} ms`);\n }),\n);\n\nconst futurePremiumIndex$ = defer(() => getFuturePremiumIndex({})).pipe(\n repeat({ delay: 1_000 }),\n retry({ delay: 30_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nconst futureBookTicker$ = defer(() => getFutureBookTicker({})).pipe(\n repeat({ delay: 1_000 }),\n retry({ delay: 30_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nconst quoteFromPremiumIndex$ = futurePremiumIndex$.pipe(\n mergeMap((entries) => from(entries || [])),\n map(\n (entry): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', entry.symbol),\n last_price: entry.markPrice,\n // Use the latest funding rate so that long pays when fundingRate > 0\n interest_rate_long: `${-Number(entry.lastFundingRate)}`,\n interest_rate_short: entry.lastFundingRate,\n interest_rate_next_settled_at: formatTime(entry.nextFundingTime),\n updated_at: formatTime(entry.time ?? Date.now()),\n }),\n ),\n);\n\nconst quoteFromBookTicker$ = futureBookTicker$.pipe(\n mergeMap((entries) => from(entries || [])),\n map(\n (entry): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', entry.symbol),\n bid_price: entry.bidPrice,\n ask_price: entry.askPrice,\n updated_at: formatTime(entry.time ?? Date.now()),\n }),\n ),\n);\n\nconst quoteFromOpenInterest$ = combineLatest([futureBookTicker$, futureRequestInterval$]).pipe(\n exhaustMap(([entries, requestInterval]) =>\n from(entries || []).pipe(\n concatMap((entry, index) =>\n (index > 0 ? timer(requestInterval) : of(0)).pipe(\n mergeMap(() => from(openInterestCache.query(entry.symbol))),\n map(\n (openInterest): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', entry.symbol),\n open_interest: `${openInterest ?? 0}`,\n }),\n ),\n ),\n ),\n ),\n ),\n);\n\nconst quoteFromSpotBookTicker$ = defer(() => getSpotBookTicker({})).pipe(\n mergeMap((entries) => from(entries || [])),\n map(\n (entry): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'SPOT', entry.symbol),\n bid_price: entry.bidPrice,\n ask_price: entry.askPrice,\n bid_volume: entry.bidQty,\n ask_volume: entry.askQty,\n updated_at: formatTime(Date.now()),\n }),\n ),\n repeat({ delay: 1_000 }),\n retry({ delay: 30_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nconst marginInterestRateCache = createCache<string>(\n async (asset: string) => {\n try {\n const data = await getMarginNextHourlyInterestRate({\n assets: asset,\n isIsolated: false,\n });\n return data[0]?.nextHourlyInterestRate;\n } catch (err) {\n return undefined;\n }\n },\n {\n expire: 60_000,\n },\n);\n\nconst marginPairs$ = defer(() => getMarginAllPairs()).pipe(\n map((pairs) => {\n if (!Array.isArray(pairs)) {\n console.warn('getMarginAllPairs returned non-array payload', pairs);\n return [];\n }\n return pairs;\n }),\n catchError((err) => {\n console.warn('getMarginAllPairs failed', err);\n return of([] as IMarginPair[]);\n }),\n repeat({ delay: 3600_000 }), // Refresh pair list hourly\n retry({ delay: 60_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nconst spotRequestInterval$ = defer(() => getSpotExchangeInfo()).pipe(\n map((info) => getRequestIntervalMs(info.rateLimits, DEFAULT_MARGIN_RATE_REQUEST_INTERVAL_MS)),\n catchError((err) => {\n console.warn('getSpotExchangeInfo failed when calculating request interval', err);\n return of(DEFAULT_MARGIN_RATE_REQUEST_INTERVAL_MS);\n }),\n retry({ delay: 60_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n tap((v) => {\n console.info(`!!!!Determined spot request interval: ${v} ms`);\n }),\n);\n\nconst quoteFromMarginRates$ = combineLatest([marginPairs$, spotRequestInterval$]).pipe(\n mergeMap(([pairs, requestInterval]) =>\n from(pairs).pipe(\n concatMap((pair, index) =>\n (index > 0 ? timer(requestInterval) : of(0)).pipe(\n mergeMap(() => from(marginInterestRateCache.query(pair.base))),\n mergeMap((baseRate) =>\n timer(requestInterval).pipe(\n mergeMap(() => from(marginInterestRateCache.query(pair.quote))),\n map(\n (quoteRate): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'SPOT', pair.symbol),\n // User instruction: Long = Quote Rate, Short = Base Rate\n interest_rate_long: quoteRate,\n interest_rate_short: baseRate,\n updated_at: formatTime(Date.now()),\n }),\n ),\n ),\n ),\n ),\n ),\n ),\n ),\n repeat({ delay: 60_000 }),\n);\n\nconst quote$ = merge(\n quoteFromPremiumIndex$,\n quoteFromBookTicker$,\n quoteFromOpenInterest$,\n quoteFromSpotBookTicker$,\n quoteFromMarginRates$,\n).pipe(\n groupBy((quote) => quote.product_id),\n mergeMap((group$) =>\n group$.pipe(\n scan(\n (acc, cur) =>\n Object.assign(acc, cur, {\n datasource_id: 'BINANCE',\n product_id: group$.key,\n }),\n {} as Partial<IQuote>,\n ),\n ),\n ),\n share(),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nif (process.env.WRITE_QUOTE_TO_SQL === 'true') {\n quote$\n .pipe(\n setMetricsQuoteState(terminal.terminal_id),\n writeToSQL({\n terminal,\n tableName: 'quote',\n writeInterval: 1_000,\n conflictKeys: ['datasource_id', 'product_id'],\n }),\n )\n .subscribe();\n\n terminal.channel.publishChannel('quote', { pattern: '^BINANCE/' }, (channel_id) => {\n const [datasourceId, productId] = decodePath(channel_id);\n if (!datasourceId || !productId) {\n throw new Error(`Invalid channel_id: ${channel_id}`);\n }\n return quote$.pipe(filter((quote) => quote.product_id === productId));\n });\n}\n"]}
1
+ {"version":3,"file":"quote.js","sourceRoot":"","sources":["../../src/public-data/quote.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCache } from '@yuants/cache';\nimport { IQuote, setMetricsQuoteState } from '@yuants/data-quote';\nimport { Terminal } from '@yuants/protocol';\nimport { writeToSQL } from '@yuants/sql';\nimport { decodePath, encodePath, formatTime } from '@yuants/utils';\nimport {\n catchError,\n combineLatest,\n concatMap,\n defer,\n exhaustMap,\n filter,\n from,\n groupBy,\n map,\n merge,\n mergeMap,\n of,\n repeat,\n retry,\n scan,\n share,\n shareReplay,\n tap,\n timer,\n} from 'rxjs';\nimport { getMarginAllPairs, getMarginNextHourlyInterestRate, IMarginPair } from '../api/private-api';\nimport {\n getFutureBookTicker,\n getFutureExchangeInfo,\n getFutureOpenInterest,\n getFuturePremiumIndex,\n getSpotBookTicker,\n getSpotExchangeInfo,\n getSpotTickerPrice,\n} from '../api/public-api';\n\nconst terminal = Terminal.fromNodeEnv();\nconst DEFAULT_OPEN_INTEREST_REQUEST_INTERVAL_MS = 500;\nconst DEFAULT_MARGIN_RATE_REQUEST_INTERVAL_MS = 500;\nconst OPEN_INTEREST_TTL = process.env.OPEN_INTEREST_TTL ? Number(process.env.OPEN_INTEREST_TTL) : 300_000;\n\ninterface IRateLimit {\n rateLimitType?: string;\n interval?: string;\n intervalNum?: number;\n limit?: number;\n}\n\nconst toIntervalMs = (interval?: string, intervalNum?: number) => {\n switch (interval) {\n case 'SECOND':\n return (intervalNum ?? 1) * 1_000;\n case 'MINUTE':\n return (intervalNum ?? 1) * 60_000;\n case 'HOUR':\n return (intervalNum ?? 1) * 3_600_000;\n case 'DAY':\n return (intervalNum ?? 1) * 86_400_000;\n default:\n return undefined;\n }\n};\n\nconst getRequestIntervalMs = (rateLimits: IRateLimit[] | undefined, fallbackMs: number) => {\n const intervals: number[] = [];\n for (const item of rateLimits ?? []) {\n if (item.rateLimitType !== 'REQUEST_WEIGHT' && item.rateLimitType !== 'RAW_REQUESTS') continue;\n const duration = toIntervalMs(item.interval, item.intervalNum);\n console.info('!!!!!', item, duration);\n const limit = item.limit;\n if (duration == null || limit == null || limit <= 0) continue;\n intervals.push(Math.ceil(duration / limit));\n }\n console.info('!!!!!', intervals);\n if (!intervals.length) return fallbackMs;\n return Math.max(fallbackMs, Math.max(...intervals));\n};\n\nconst openInterestCache = createCache<number>(\n async (symbol: string) => {\n try {\n const data = await getFutureOpenInterest({ symbol });\n return Number(data.openInterest ?? 0);\n } catch (err) {\n console.warn('getFutureOpenInterest failed', symbol, err);\n return undefined;\n }\n },\n {\n expire: OPEN_INTEREST_TTL,\n },\n);\n\nconst futureRequestInterval$ = defer(() => getFutureExchangeInfo()).pipe(\n map((info) => getRequestIntervalMs(info.rateLimits, DEFAULT_OPEN_INTEREST_REQUEST_INTERVAL_MS)),\n catchError((err) => {\n console.warn('getFutureExchangeInfo failed when calculating request interval', err);\n return of(DEFAULT_OPEN_INTEREST_REQUEST_INTERVAL_MS);\n }),\n retry({ delay: 60_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n tap((v) => {\n console.info(`!!!!Determined future request interval: ${v} ms`);\n }),\n);\n\nconst futurePremiumIndex$ = defer(() => getFuturePremiumIndex({})).pipe(\n repeat({ delay: 1_000 }),\n retry({ delay: 30_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nconst futureBookTicker$ = defer(() => getFutureBookTicker({})).pipe(\n repeat({ delay: 1_000 }),\n retry({ delay: 30_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nconst quoteFromSpotTicker$ = defer(() => getSpotTickerPrice({})).pipe(\n mergeMap((entries) => from(entries || [])),\n mergeMap((entry): Partial<IQuote>[] => [\n {\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'SPOT', entry.symbol),\n last_price: entry.price,\n updated_at: formatTime(Date.now()),\n },\n {\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'MARGIN', entry.symbol),\n last_price: entry.price,\n updated_at: formatTime(Date.now()),\n },\n ]),\n repeat({ delay: 1_000 }),\n retry({ delay: 1_000 }),\n);\n\nconst quoteFromPremiumIndex$ = futurePremiumIndex$.pipe(\n mergeMap((entries) => from(entries || [])),\n map(\n (entry): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', entry.symbol),\n last_price: entry.markPrice,\n // Use the latest funding rate so that long pays when fundingRate > 0\n interest_rate_long: `${-Number(entry.lastFundingRate)}`,\n interest_rate_short: entry.lastFundingRate,\n interest_rate_next_settled_at: formatTime(entry.nextFundingTime),\n updated_at: formatTime(entry.time ?? Date.now()),\n }),\n ),\n);\n\nconst quoteFromBookTicker$ = futureBookTicker$.pipe(\n mergeMap((entries) => from(entries || [])),\n map(\n (entry): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', entry.symbol),\n bid_price: entry.bidPrice,\n ask_price: entry.askPrice,\n updated_at: formatTime(entry.time ?? Date.now()),\n }),\n ),\n);\n\nconst quoteFromOpenInterest$ = combineLatest([futureBookTicker$, futureRequestInterval$]).pipe(\n exhaustMap(([entries, requestInterval]) =>\n from(entries || []).pipe(\n concatMap((entry, index) =>\n (index > 0 ? timer(requestInterval) : of(0)).pipe(\n mergeMap(() => from(openInterestCache.query(entry.symbol))),\n map(\n (openInterest): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', entry.symbol),\n open_interest: `${openInterest ?? 0}`,\n }),\n ),\n ),\n ),\n ),\n ),\n);\n\nconst quoteFromSpotBookTicker$ = defer(() => getSpotBookTicker({})).pipe(\n mergeMap((entries) => from(entries || [])),\n map(\n (entry): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'SPOT', entry.symbol),\n bid_price: entry.bidPrice,\n ask_price: entry.askPrice,\n bid_volume: entry.bidQty,\n ask_volume: entry.askQty,\n updated_at: formatTime(Date.now()),\n }),\n ),\n repeat({ delay: 1_000 }),\n retry({ delay: 30_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nconst marginInterestRateCache = createCache<string>(\n async (asset: string) => {\n try {\n const data = await getMarginNextHourlyInterestRate({\n assets: asset,\n isIsolated: false,\n });\n return data[0]?.nextHourlyInterestRate;\n } catch (err) {\n return undefined;\n }\n },\n {\n expire: 60_000,\n },\n);\n\nconst marginPairs$ = defer(() => getMarginAllPairs()).pipe(\n map((pairs) => {\n if (!Array.isArray(pairs)) {\n console.warn('getMarginAllPairs returned non-array payload', pairs);\n return [];\n }\n return pairs;\n }),\n catchError((err) => {\n console.warn('getMarginAllPairs failed', err);\n return of([] as IMarginPair[]);\n }),\n repeat({ delay: 3600_000 }), // Refresh pair list hourly\n retry({ delay: 60_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nconst spotRequestInterval$ = defer(() => getSpotExchangeInfo()).pipe(\n map((info) => getRequestIntervalMs(info.rateLimits, DEFAULT_MARGIN_RATE_REQUEST_INTERVAL_MS)),\n catchError((err) => {\n console.warn('getSpotExchangeInfo failed when calculating request interval', err);\n return of(DEFAULT_MARGIN_RATE_REQUEST_INTERVAL_MS);\n }),\n retry({ delay: 60_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n tap((v) => {\n console.info(`!!!!Determined spot request interval: ${v} ms`);\n }),\n);\n\nconst quoteFromMarginRates$ = combineLatest([marginPairs$, spotRequestInterval$]).pipe(\n mergeMap(([pairs, requestInterval]) =>\n from(pairs).pipe(\n concatMap((pair, index) =>\n (index > 0 ? timer(requestInterval) : of(0)).pipe(\n mergeMap(() => from(marginInterestRateCache.query(pair.base))),\n mergeMap((baseRate) =>\n timer(requestInterval).pipe(\n mergeMap(() => from(marginInterestRateCache.query(pair.quote))),\n map(\n (quoteRate): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'SPOT', pair.symbol),\n // User instruction: Long = Quote Rate, Short = Base Rate\n interest_rate_long: quoteRate,\n interest_rate_short: baseRate,\n updated_at: formatTime(Date.now()),\n }),\n ),\n ),\n ),\n ),\n ),\n ),\n ),\n repeat({ delay: 60_000 }),\n);\n\nconst quote$ = merge(\n quoteFromPremiumIndex$,\n quoteFromBookTicker$,\n quoteFromOpenInterest$,\n quoteFromSpotBookTicker$,\n quoteFromMarginRates$,\n quoteFromSpotTicker$,\n).pipe(\n groupBy((quote) => quote.product_id),\n mergeMap((group$) =>\n group$.pipe(\n scan(\n (acc, cur) =>\n Object.assign(acc, cur, {\n datasource_id: 'BINANCE',\n product_id: group$.key,\n }),\n {} as Partial<IQuote>,\n ),\n ),\n ),\n share(),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nif (process.env.WRITE_QUOTE_TO_SQL === 'true') {\n quote$\n .pipe(\n setMetricsQuoteState(terminal.terminal_id),\n writeToSQL({\n terminal,\n tableName: 'quote',\n writeInterval: 1_000,\n conflictKeys: ['datasource_id', 'product_id'],\n }),\n )\n .subscribe();\n\n terminal.channel.publishChannel('quote', { pattern: '^BINANCE/' }, (channel_id) => {\n const [datasourceId, productId] = decodePath(channel_id);\n if (!datasourceId || !productId) {\n throw new Error(`Invalid channel_id: ${channel_id}`);\n }\n return quote$.pipe(filter((quote) => quote.product_id === productId));\n });\n}\n"]}
@@ -1,12 +1,25 @@
1
+ import { createCache } from '@yuants/cache';
1
2
  import { makeSpotPosition } from '@yuants/data-account';
3
+ import { Terminal } from '@yuants/protocol';
4
+ import { escapeSQL, requestSQL } from '@yuants/sql';
2
5
  import { encodePath } from '@yuants/utils';
3
6
  import { isApiError } from '../../api/client';
4
- import { getUnifiedAccountBalance, getUnifiedUmAccount } from '../../api/private-api';
5
- import { getSpotTickerPrice } from '../../api/public-api';
6
- export const getUnifiedAccountInfo = async (credential) => {
7
- const [balanceRes, umAccountRes] = await Promise.all([
7
+ import { getFundingAsset, getSpotAccountInfo, getUnifiedAccountBalance, getUnifiedUmAccount, } from '../../api/private-api';
8
+ const terminal = Terminal.fromNodeEnv();
9
+ const quoteCache = createCache(async (product_id) => {
10
+ const sql = `select * from quote where product_id = ${escapeSQL(product_id)}`;
11
+ const [quote] = await requestSQL(terminal, sql);
12
+ return quote;
13
+ }, { expire: 10000 });
14
+ export const getPositions = async (credential) => {
15
+ var _a, _b;
16
+ const [balanceRes, umAccountRes, res, fundingAsset] = await Promise.all([
8
17
  getUnifiedAccountBalance(credential),
9
18
  getUnifiedUmAccount(credential),
19
+ getSpotAccountInfo(credential, { omitZeroBalances: true }),
20
+ getFundingAsset(credential, {
21
+ timestamp: Date.now(),
22
+ }),
10
23
  ]);
11
24
  if (isApiError(balanceRes)) {
12
25
  throw new Error(balanceRes.msg);
@@ -14,50 +27,58 @@ export const getUnifiedAccountInfo = async (credential) => {
14
27
  if (isApiError(umAccountRes)) {
15
28
  throw new Error(umAccountRes.msg);
16
29
  }
17
- const positions = umAccountRes.positions
18
- .filter((position) => +position.positionAmt !== 0)
19
- .map((position) => ({
20
- position_id: `${position.symbol}/${position.positionSide}`,
21
- datasource_id: 'BINANCE',
22
- product_id: encodePath('BINANCE', 'USDT-FUTURE', position.symbol),
23
- direction: position.positionSide === 'LONG'
24
- ? 'LONG'
25
- : position.positionSide === 'SHORT'
26
- ? 'SHORT'
27
- : position.positionSide === 'BOTH'
28
- ? 'BOTH'
29
- : 'UNKNOWN',
30
- volume: Math.abs(+position.positionAmt),
31
- free_volume: Math.abs(+position.positionAmt),
32
- position_price: +position.entryPrice,
33
- // ISSUE: positionAmt 有正负,这里计算有个 trick,不需要区分仓位方向
34
- closable_price: +position.entryPrice + +position.unrealizedProfit / +position.positionAmt,
35
- floating_profit: +position.unrealizedProfit,
36
- valuation: +position.positionAmt *
37
- (+position.entryPrice +
38
- (+position.positionAmt === 0 ? 0 : +position.unrealizedProfit / +position.positionAmt)),
39
- }));
40
- const prices = await getSpotTickerPrice({
41
- symbols: JSON.stringify([
42
- ...new Set([
43
- ...balanceRes
44
- .map((balance) => {
45
- const match = balance.asset.match(/^LD(\w+)$/);
46
- let symbol = balance.asset;
47
- if (match) {
48
- symbol = match[1];
49
- }
50
- if (symbol === 'USDT')
51
- return '';
52
- return `${symbol}USDT`;
53
- })
54
- .filter(Boolean),
55
- ]),
56
- ]),
57
- });
58
- const balancePositions = balanceRes.map((position) => {
59
- var _a, _b;
60
- return makeSpotPosition({
30
+ if (isApiError(res)) {
31
+ throw new Error(res.msg);
32
+ }
33
+ if (isApiError(fundingAsset)) {
34
+ throw new Error(fundingAsset.msg);
35
+ }
36
+ const positions = [];
37
+ for (const balance of [...res.balances, ...fundingAsset]) {
38
+ const volume = +balance.free + +balance.locked;
39
+ if (!volume)
40
+ continue;
41
+ positions.push(makeSpotPosition({
42
+ position_id: `spot/${balance.asset}`,
43
+ datasource_id: 'BINANCE',
44
+ product_id: encodePath('BINANCE', 'SPOT', `${balance.asset}`),
45
+ volume,
46
+ free_volume: +balance.free,
47
+ closable_price: balance.asset === 'USDT'
48
+ ? 1
49
+ : +(((_a = (await quoteCache.query(encodePath('BINANCE', 'SPOT', `${balance.asset}USDT`)))) === null || _a === void 0 ? void 0 : _a.last_price) ||
50
+ 0),
51
+ }));
52
+ }
53
+ for (const position of umAccountRes.positions) {
54
+ if (+position.positionAmt === 0)
55
+ continue;
56
+ positions.push({
57
+ position_id: `${position.symbol}/${position.positionSide}`,
58
+ datasource_id: 'BINANCE',
59
+ product_id: encodePath('BINANCE', 'USDT-FUTURE', position.symbol),
60
+ direction: position.positionSide === 'LONG'
61
+ ? 'LONG'
62
+ : position.positionSide === 'SHORT'
63
+ ? 'SHORT'
64
+ : position.positionSide === 'BOTH'
65
+ ? 'BOTH'
66
+ : 'UNKNOWN',
67
+ volume: Math.abs(+position.positionAmt),
68
+ free_volume: Math.abs(+position.positionAmt),
69
+ position_price: +position.entryPrice,
70
+ // ISSUE: positionAmt 有正负,这里计算有个 trick,不需要区分仓位方向
71
+ closable_price: +position.entryPrice + +position.unrealizedProfit / +position.positionAmt,
72
+ floating_profit: +position.unrealizedProfit,
73
+ valuation: +position.positionAmt *
74
+ (+position.entryPrice +
75
+ (+position.positionAmt === 0 ? 0 : +position.unrealizedProfit / +position.positionAmt)),
76
+ });
77
+ }
78
+ for (const position of balanceRes) {
79
+ if (+position.totalWalletBalance === 0)
80
+ continue;
81
+ positions.push(makeSpotPosition({
61
82
  position_id: `UNIFIED-SPOT/${position.asset}`,
62
83
  datasource_id: 'BINANCE',
63
84
  product_id: encodePath('BINANCE', 'UNIFIED-SPOT', position.asset),
@@ -65,11 +86,9 @@ export const getUnifiedAccountInfo = async (credential) => {
65
86
  free_volume: +position.crossMarginFree,
66
87
  closable_price: position.asset === 'USDT'
67
88
  ? 1
68
- : Array.isArray(prices)
69
- ? +((_b = (_a = prices.find((item) => item.symbol === `${position.asset}USDT`)) === null || _a === void 0 ? void 0 : _a.price) !== null && _b !== void 0 ? _b : 0)
70
- : 0,
71
- });
72
- });
73
- return [...balancePositions, ...positions];
89
+ : +(((_b = (await quoteCache.query(encodePath('BINANCE', 'SPOT', `${position.asset}USDT`)))) === null || _b === void 0 ? void 0 : _b.last_price) || 0),
90
+ }));
91
+ }
92
+ return positions;
74
93
  };
75
94
  //# sourceMappingURL=unified.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"unified.js","sourceRoot":"","sources":["../../../src/services/accounts/unified.ts"],"names":[],"mappings":"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","sourcesContent":["import { IPosition, makeSpotPosition } from '@yuants/data-account';\nimport { encodePath } from '@yuants/utils';\nimport { isApiError } from '../../api/client';\nimport { getUnifiedAccountBalance, getUnifiedUmAccount, ICredential } from '../../api/private-api';\nimport { getSpotTickerPrice } from '../../api/public-api';\n\nexport const getUnifiedAccountInfo = async (credential: ICredential): Promise<IPosition[]> => {\n const [balanceRes, umAccountRes] = await Promise.all([\n getUnifiedAccountBalance(credential),\n getUnifiedUmAccount(credential),\n ]);\n if (isApiError(balanceRes)) {\n throw new Error(balanceRes.msg);\n }\n if (isApiError(umAccountRes)) {\n throw new Error(umAccountRes.msg);\n }\n\n const positions: IPosition[] = umAccountRes.positions\n .filter((position) => +position.positionAmt !== 0)\n .map((position) => ({\n position_id: `${position.symbol}/${position.positionSide}`,\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', position.symbol),\n direction:\n position.positionSide === 'LONG'\n ? 'LONG'\n : position.positionSide === 'SHORT'\n ? 'SHORT'\n : position.positionSide === 'BOTH'\n ? 'BOTH'\n : 'UNKNOWN',\n volume: Math.abs(+position.positionAmt),\n free_volume: Math.abs(+position.positionAmt),\n position_price: +position.entryPrice,\n // ISSUE: positionAmt 有正负,这里计算有个 trick,不需要区分仓位方向\n closable_price: +position.entryPrice + +position.unrealizedProfit / +position.positionAmt,\n floating_profit: +position.unrealizedProfit,\n valuation:\n +position.positionAmt *\n (+position.entryPrice +\n (+position.positionAmt === 0 ? 0 : +position.unrealizedProfit / +position.positionAmt)),\n }));\n\n const prices = await getSpotTickerPrice({\n symbols: JSON.stringify([\n ...new Set([\n ...balanceRes\n .map((balance) => {\n const match = balance.asset.match(/^LD(\\w+)$/);\n let symbol = balance.asset;\n if (match) {\n symbol = match[1];\n }\n if (symbol === 'USDT') return '';\n return `${symbol}USDT`;\n })\n .filter(Boolean),\n ]),\n ]),\n });\n const balancePositions: IPosition[] = balanceRes.map((position) =>\n makeSpotPosition({\n position_id: `UNIFIED-SPOT/${position.asset}`,\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'UNIFIED-SPOT', position.asset),\n volume: +position.totalWalletBalance,\n free_volume: +position.crossMarginFree,\n closable_price:\n position.asset === 'USDT'\n ? 1\n : Array.isArray(prices)\n ? +(prices.find((item) => item.symbol === `${position.asset}USDT`)?.price ?? 0)\n : 0,\n }),\n );\n return [...balancePositions, ...positions];\n};\n"]}
1
+ {"version":3,"file":"unified.js","sourceRoot":"","sources":["../../../src/services/accounts/unified.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAa,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAEnE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,wBAAwB,EACxB,mBAAmB,GAEpB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,UAAU,GAAG,WAAW,CAC5B,KAAK,EAAE,UAAU,EAAE,EAAE;IACnB,MAAM,GAAG,GAAG,0CAA0C,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;IAC9E,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,UAAU,CAAW,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC1D,OAAO,KAAK,CAAC;AACf,CAAC,EACD,EAAE,MAAM,EAAE,KAAM,EAAE,CACnB,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAAE,UAAuB,EAAwB,EAAE;;IAClF,MAAM,CAAC,UAAU,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACtE,wBAAwB,CAAC,UAAU,CAAC;QACpC,mBAAmB,CAAC,UAAU,CAAC;QAC/B,kBAAkB,CAAC,UAAU,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC;QAC1D,eAAe,CAAC,UAAU,EAAE;YAC1B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;KACH,CAAC,CAAC;IACH,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE;QAC1B,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;KACjC;IACD,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE;QAC5B,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;KACnC;IACD,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE;QACnB,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;KAC1B;IACD,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE;QAC5B,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;KACnC;IAED,MAAM,SAAS,GAAgB,EAAE,CAAC;IAElC,KAAK,MAAM,OAAO,IAAI,CAAC,GAAG,GAAG,CAAC,QAAQ,EAAE,GAAG,YAAY,CAAC,EAAE;QACxD,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;QAC/C,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,SAAS,CAAC,IAAI,CACZ,gBAAgB,CAAC;YACf,WAAW,EAAE,QAAQ,OAAO,CAAC,KAAK,EAAE;YACpC,aAAa,EAAE,SAAS;YACxB,UAAU,EAAE,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;YAC7D,MAAM;YACN,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI;YAC1B,cAAc,EACZ,OAAO,CAAC,KAAK,KAAK,MAAM;gBACtB,CAAC,CAAC,CAAC;gBACH,CAAC,CAAC,CAAC,CACC,CAAA,MAAA,CAAC,MAAM,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,0CAAE,UAAU;oBAC3F,CAAC,CACF;SACR,CAAC,CACH,CAAC;KACH;IAED,KAAK,MAAM,QAAQ,IAAI,YAAY,CAAC,SAAS,EAAE;QAC7C,IAAI,CAAC,QAAQ,CAAC,WAAW,KAAK,CAAC;YAAE,SAAS;QAC1C,SAAS,CAAC,IAAI,CAAC;YACb,WAAW,EAAE,GAAG,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,YAAY,EAAE;YAC1D,aAAa,EAAE,SAAS;YACxB,UAAU,EAAE,UAAU,CAAC,SAAS,EAAE,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC;YACjE,SAAS,EACP,QAAQ,CAAC,YAAY,KAAK,MAAM;gBAC9B,CAAC,CAAC,MAAM;gBACR,CAAC,CAAC,QAAQ,CAAC,YAAY,KAAK,OAAO;oBACnC,CAAC,CAAC,OAAO;oBACT,CAAC,CAAC,QAAQ,CAAC,YAAY,KAAK,MAAM;wBAClC,CAAC,CAAC,MAAM;wBACR,CAAC,CAAC,SAAS;YACf,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC;YACvC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC;YAC5C,cAAc,EAAE,CAAC,QAAQ,CAAC,UAAU;YACpC,gDAAgD;YAChD,cAAc,EAAE,CAAC,QAAQ,CAAC,UAAU,GAAG,CAAC,QAAQ,CAAC,gBAAgB,GAAG,CAAC,QAAQ,CAAC,WAAW;YACzF,eAAe,EAAE,CAAC,QAAQ,CAAC,gBAAgB;YAC3C,SAAS,EACP,CAAC,QAAQ,CAAC,WAAW;gBACrB,CAAC,CAAC,QAAQ,CAAC,UAAU;oBACnB,CAAC,CAAC,QAAQ,CAAC,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;SAC5F,CAAC,CAAC;KACJ;IAED,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE;QACjC,IAAI,CAAC,QAAQ,CAAC,kBAAkB,KAAK,CAAC;YAAE,SAAS;QACjD,SAAS,CAAC,IAAI,CACZ,gBAAgB,CAAC;YACf,WAAW,EAAE,gBAAgB,QAAQ,CAAC,KAAK,EAAE;YAC7C,aAAa,EAAE,SAAS;YACxB,UAAU,EAAE,UAAU,CAAC,SAAS,EAAE,cAAc,EAAE,QAAQ,CAAC,KAAK,CAAC;YACjE,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB;YACpC,WAAW,EAAE,CAAC,QAAQ,CAAC,eAAe;YACtC,cAAc,EACZ,QAAQ,CAAC,KAAK,KAAK,MAAM;gBACvB,CAAC,CAAC,CAAC;gBACH,CAAC,CAAC,CAAC,CACC,CAAA,MAAA,CAAC,MAAM,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,0CAC5E,UAAU,KAAI,CAAC,CACpB;SACR,CAAC,CACH,CAAC;KACH;IAED,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC","sourcesContent":["import { createCache } from '@yuants/cache';\nimport { IPosition, makeSpotPosition } from '@yuants/data-account';\nimport { IQuote } from '@yuants/data-quote';\nimport { Terminal } from '@yuants/protocol';\nimport { escapeSQL, requestSQL } from '@yuants/sql';\nimport { encodePath } from '@yuants/utils';\nimport { isApiError } from '../../api/client';\nimport {\n getFundingAsset,\n getSpotAccountInfo,\n getUnifiedAccountBalance,\n getUnifiedUmAccount,\n ICredential,\n} from '../../api/private-api';\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst quoteCache = createCache<IQuote>(\n async (product_id) => {\n const sql = `select * from quote where product_id = ${escapeSQL(product_id)}`;\n const [quote] = await requestSQL<IQuote[]>(terminal, sql);\n return quote;\n },\n { expire: 10_000 },\n);\n\nexport const getPositions = async (credential: ICredential): Promise<IPosition[]> => {\n const [balanceRes, umAccountRes, res, fundingAsset] = await Promise.all([\n getUnifiedAccountBalance(credential),\n getUnifiedUmAccount(credential),\n getSpotAccountInfo(credential, { omitZeroBalances: true }),\n getFundingAsset(credential, {\n timestamp: Date.now(),\n }),\n ]);\n if (isApiError(balanceRes)) {\n throw new Error(balanceRes.msg);\n }\n if (isApiError(umAccountRes)) {\n throw new Error(umAccountRes.msg);\n }\n if (isApiError(res)) {\n throw new Error(res.msg);\n }\n if (isApiError(fundingAsset)) {\n throw new Error(fundingAsset.msg);\n }\n\n const positions: IPosition[] = [];\n\n for (const balance of [...res.balances, ...fundingAsset]) {\n const volume = +balance.free + +balance.locked;\n if (!volume) continue;\n positions.push(\n makeSpotPosition({\n position_id: `spot/${balance.asset}`,\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'SPOT', `${balance.asset}`),\n volume,\n free_volume: +balance.free,\n closable_price:\n balance.asset === 'USDT'\n ? 1\n : +(\n (await quoteCache.query(encodePath('BINANCE', 'SPOT', `${balance.asset}USDT`)))?.last_price ||\n 0\n ),\n }),\n );\n }\n\n for (const position of umAccountRes.positions) {\n if (+position.positionAmt === 0) continue;\n positions.push({\n position_id: `${position.symbol}/${position.positionSide}`,\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', position.symbol),\n direction:\n position.positionSide === 'LONG'\n ? 'LONG'\n : position.positionSide === 'SHORT'\n ? 'SHORT'\n : position.positionSide === 'BOTH'\n ? 'BOTH'\n : 'UNKNOWN',\n volume: Math.abs(+position.positionAmt),\n free_volume: Math.abs(+position.positionAmt),\n position_price: +position.entryPrice,\n // ISSUE: positionAmt 有正负,这里计算有个 trick,不需要区分仓位方向\n closable_price: +position.entryPrice + +position.unrealizedProfit / +position.positionAmt,\n floating_profit: +position.unrealizedProfit,\n valuation:\n +position.positionAmt *\n (+position.entryPrice +\n (+position.positionAmt === 0 ? 0 : +position.unrealizedProfit / +position.positionAmt)),\n });\n }\n\n for (const position of balanceRes) {\n if (+position.totalWalletBalance === 0) continue;\n positions.push(\n makeSpotPosition({\n position_id: `UNIFIED-SPOT/${position.asset}`,\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'UNIFIED-SPOT', position.asset),\n volume: +position.totalWalletBalance,\n free_volume: +position.crossMarginFree,\n closable_price:\n position.asset === 'USDT'\n ? 1\n : +(\n (await quoteCache.query(encodePath('BINANCE', 'SPOT', `${position.asset}USDT`)))\n ?.last_price || 0\n ),\n }),\n );\n }\n\n return positions;\n};\n"]}
@@ -1,10 +1,8 @@
1
1
  import { provideExchangeServices } from '@yuants/exchange';
2
2
  import { Terminal } from '@yuants/protocol';
3
- import { decodePath } from '@yuants/utils';
4
3
  import { listProducts } from '../public-data/product';
5
4
  import { getCredentialId } from './accounts/profile';
6
- import { getSpotAccountInfoSnapshot } from './accounts/spot';
7
- import { getUnifiedAccountInfo } from './accounts/unified';
5
+ import { getPositions } from './accounts/unified';
8
6
  import { cancelOrder } from './orders/cancelOrder';
9
7
  import { getOrdersByProductId, listSpotOrders, listUnifiedUmOrders } from './orders/listOrders';
10
8
  import { modifyOrder } from './orders/modifyOrder';
@@ -22,13 +20,7 @@ provideExchangeServices(terminal, {
22
20
  },
23
21
  getCredentialId,
24
22
  listProducts,
25
- getPositions: async function (credential) {
26
- const [uFuturePositions, spotPositions] = await Promise.all([
27
- getUnifiedAccountInfo(credential),
28
- getSpotAccountInfoSnapshot(credential),
29
- ]);
30
- return [...uFuturePositions, ...spotPositions];
31
- },
23
+ getPositions: getPositions,
32
24
  getOrders: async function (credential) {
33
25
  const [umOrders, spotOrders] = await Promise.all([
34
26
  listUnifiedUmOrders(credential),
@@ -37,16 +29,8 @@ provideExchangeServices(terminal, {
37
29
  return [...umOrders, ...spotOrders];
38
30
  },
39
31
  getPositionsByProductId: async function (credential, product_id) {
40
- const [_, instType] = decodePath(product_id); // BINANCE/USDT-FUTURE/ADAUSDT
41
- if (instType === 'SPOT') {
42
- const positions = await getSpotAccountInfoSnapshot(credential);
43
- return positions.filter((position) => position.product_id === product_id);
44
- }
45
- if (instType === 'USDT-FUTURE') {
46
- const positions = await getUnifiedAccountInfo(credential);
47
- return positions.filter((position) => position.product_id === product_id);
48
- }
49
- throw new Error(`Unsupported instType: ${instType}`);
32
+ const positions = await getPositions(credential);
33
+ return positions.filter((position) => position.product_id === product_id);
50
34
  },
51
35
  getOrdersByProductId,
52
36
  submitOrder,
@@ -1 +1 @@
1
- {"version":3,"file":"exchange.js","sourceRoot":"","sources":["../../src/services/exchange.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAChG,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,uBAAuB,CAAc,QAAQ,EAAE;IAC7C,IAAI,EAAE,SAAS;IACf,gBAAgB,EAAE;QAChB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC;QACtC,UAAU,EAAE;YACV,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC9B,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;SAC/B;KACF;IACD,eAAe;IACf,YAAY;IACZ,YAAY,EAAE,KAAK,WAAW,UAAuB;QACnD,MAAM,CAAC,gBAAgB,EAAE,aAAa,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC1D,qBAAqB,CAAC,UAAU,CAAC;YACjC,0BAA0B,CAAC,UAAU,CAAC;SACvC,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,gBAAgB,EAAE,GAAG,aAAa,CAAC,CAAC;IACjD,CAAC;IACD,SAAS,EAAE,KAAK,WAAW,UAAuB;QAChD,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC/C,mBAAmB,CAAC,UAAU,CAAC;YAC/B,cAAc,CAAC,UAAU,CAAC;SAC3B,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,QAAQ,EAAE,GAAG,UAAU,CAAC,CAAC;IACtC,CAAC;IACD,uBAAuB,EAAE,KAAK,WAC5B,UAAuB,EACvB,UAAkB;QAElB,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,8BAA8B;QAC5E,IAAI,QAAQ,KAAK,MAAM,EAAE;YACvB,MAAM,SAAS,GAAG,MAAM,0BAA0B,CAAC,UAAU,CAAC,CAAC;YAC/D,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;SAC3E;QACD,IAAI,QAAQ,KAAK,aAAa,EAAE;YAC9B,MAAM,SAAS,GAAG,MAAM,qBAAqB,CAAC,UAAU,CAAC,CAAC;YAC1D,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;SAC3E;QACD,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,oBAAoB;IACpB,WAAW;IACX,WAAW;IACX,WAAW;CACZ,CAAC,CAAC","sourcesContent":["import { IPosition } from '@yuants/data-account';\nimport { IOrder } from '@yuants/data-order';\nimport { provideExchangeServices } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { decodePath } from '@yuants/utils';\nimport { ICredential } from '../api/client';\nimport { listProducts } from '../public-data/product';\nimport { getCredentialId } from './accounts/profile';\nimport { getSpotAccountInfoSnapshot } from './accounts/spot';\nimport { getUnifiedAccountInfo } from './accounts/unified';\nimport { cancelOrder } from './orders/cancelOrder';\nimport { getOrdersByProductId, listSpotOrders, listUnifiedUmOrders } from './orders/listOrders';\nimport { modifyOrder } from './orders/modifyOrder';\nimport { submitOrder } from './orders/submitOrder';\n\nconst terminal = Terminal.fromNodeEnv();\n\nprovideExchangeServices<ICredential>(terminal, {\n name: 'BINANCE',\n credentialSchema: {\n type: 'object',\n required: ['access_key', 'secret_key'],\n properties: {\n access_key: { type: 'string' },\n secret_key: { type: 'string' },\n },\n },\n getCredentialId,\n listProducts,\n getPositions: async function (credential: ICredential): Promise<IPosition[]> {\n const [uFuturePositions, spotPositions] = await Promise.all([\n getUnifiedAccountInfo(credential),\n getSpotAccountInfoSnapshot(credential),\n ]);\n return [...uFuturePositions, ...spotPositions];\n },\n getOrders: async function (credential: ICredential): Promise<IOrder[]> {\n const [umOrders, spotOrders] = await Promise.all([\n listUnifiedUmOrders(credential),\n listSpotOrders(credential),\n ]);\n return [...umOrders, ...spotOrders];\n },\n getPositionsByProductId: async function (\n credential: ICredential,\n product_id: string,\n ): Promise<IPosition[]> {\n const [_, instType] = decodePath(product_id); // BINANCE/USDT-FUTURE/ADAUSDT\n if (instType === 'SPOT') {\n const positions = await getSpotAccountInfoSnapshot(credential);\n return positions.filter((position) => position.product_id === product_id);\n }\n if (instType === 'USDT-FUTURE') {\n const positions = await getUnifiedAccountInfo(credential);\n return positions.filter((position) => position.product_id === product_id);\n }\n throw new Error(`Unsupported instType: ${instType}`);\n },\n getOrdersByProductId,\n submitOrder,\n modifyOrder,\n cancelOrder,\n});\n"]}
1
+ {"version":3,"file":"exchange.js","sourceRoot":"","sources":["../../src/services/exchange.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAChG,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,uBAAuB,CAAc,QAAQ,EAAE;IAC7C,IAAI,EAAE,SAAS;IACf,gBAAgB,EAAE;QAChB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC;QACtC,UAAU,EAAE;YACV,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC9B,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;SAC/B;KACF;IACD,eAAe;IACf,YAAY;IACZ,YAAY,EAAE,YAAY;IAC1B,SAAS,EAAE,KAAK,WAAW,UAAuB;QAChD,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC/C,mBAAmB,CAAC,UAAU,CAAC;YAC/B,cAAc,CAAC,UAAU,CAAC;SAC3B,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,QAAQ,EAAE,GAAG,UAAU,CAAC,CAAC;IACtC,CAAC;IACD,uBAAuB,EAAE,KAAK,WAC5B,UAAuB,EACvB,UAAkB;QAElB,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,CAAC;QACjD,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;IAC5E,CAAC;IACD,oBAAoB;IACpB,WAAW;IACX,WAAW;IACX,WAAW;CACZ,CAAC,CAAC","sourcesContent":["import { IPosition } from '@yuants/data-account';\nimport { IOrder } from '@yuants/data-order';\nimport { provideExchangeServices } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { ICredential } from '../api/client';\nimport { listProducts } from '../public-data/product';\nimport { getCredentialId } from './accounts/profile';\nimport { getPositions } from './accounts/unified';\nimport { cancelOrder } from './orders/cancelOrder';\nimport { getOrdersByProductId, listSpotOrders, listUnifiedUmOrders } from './orders/listOrders';\nimport { modifyOrder } from './orders/modifyOrder';\nimport { submitOrder } from './orders/submitOrder';\n\nconst terminal = Terminal.fromNodeEnv();\n\nprovideExchangeServices<ICredential>(terminal, {\n name: 'BINANCE',\n credentialSchema: {\n type: 'object',\n required: ['access_key', 'secret_key'],\n properties: {\n access_key: { type: 'string' },\n secret_key: { type: 'string' },\n },\n },\n getCredentialId,\n listProducts,\n getPositions: getPositions,\n getOrders: async function (credential: ICredential): Promise<IOrder[]> {\n const [umOrders, spotOrders] = await Promise.all([\n listUnifiedUmOrders(credential),\n listSpotOrders(credential),\n ]);\n return [...umOrders, ...spotOrders];\n },\n getPositionsByProductId: async function (\n credential: ICredential,\n product_id: string,\n ): Promise<IPosition[]> {\n const positions = await getPositions(credential);\n return positions.filter((position) => position.product_id === product_id);\n },\n getOrdersByProductId,\n submitOrder,\n modifyOrder,\n cancelOrder,\n});\n"]}
@@ -0,0 +1,76 @@
1
+ import { provideInterestRateService } from '@yuants/exchange';
2
+ import { Terminal } from '@yuants/protocol';
3
+ import { decodePath, formatTime } from '@yuants/utils';
4
+ import { getMarginInterestRateHistory } from '../api/private-api';
5
+ import { getFutureFundingRate } from '../api/public-api';
6
+ const terminal = Terminal.fromNodeEnv();
7
+ const INGEST_SERVICE_OPTIONS = {
8
+ concurrent: 1,
9
+ max_pending_requests: 20,
10
+ ingress_token_capacity: 2,
11
+ ingress_token_refill_interval: 1000,
12
+ egress_token_capacity: 1,
13
+ egress_token_refill_interval: 1000,
14
+ };
15
+ const WINDOW_MS = 365 * 24 * 3600000;
16
+ const fetchUsdtFutureFundingRateForward = async (req) => {
17
+ const [, instType, symbol] = decodePath(req.product_id);
18
+ if (instType !== 'USDT-FUTURE' || !symbol)
19
+ throw new Error(`Unsupported product_id: ${req.product_id}`);
20
+ const startTime = req.time;
21
+ const res = await getFutureFundingRate({
22
+ symbol,
23
+ startTime,
24
+ endTime: startTime + WINDOW_MS,
25
+ limit: 1000,
26
+ });
27
+ return (res !== null && res !== void 0 ? res : [])
28
+ .map((v) => {
29
+ const ms = Number(v.fundingTime);
30
+ const rate = Number(v.fundingRate);
31
+ return {
32
+ series_id: req.series_id,
33
+ product_id: req.product_id,
34
+ datasource_id: 'BINANCE',
35
+ created_at: formatTime(ms),
36
+ long_rate: `${-rate}`,
37
+ short_rate: `${rate}`,
38
+ settlement_price: '',
39
+ };
40
+ })
41
+ .filter((x) => Date.parse(x.created_at) >= startTime);
42
+ };
43
+ const fetchMarginBorrowRateForward = async (req) => {
44
+ const [, instType, asset] = decodePath(req.product_id);
45
+ if (instType !== 'MARGIN' || !asset)
46
+ throw new Error(`Unsupported product_id: ${req.product_id}`);
47
+ const startTime = req.time;
48
+ const res = await getMarginInterestRateHistory({
49
+ asset,
50
+ startTime,
51
+ endTime: startTime + WINDOW_MS,
52
+ limit: 100,
53
+ });
54
+ return (res !== null && res !== void 0 ? res : [])
55
+ .map((v) => {
56
+ return {
57
+ series_id: req.series_id,
58
+ product_id: req.product_id,
59
+ datasource_id: 'BINANCE',
60
+ created_at: formatTime(v.timestamp),
61
+ long_rate: v.dailyInterestRate,
62
+ short_rate: '0',
63
+ settlement_price: '',
64
+ };
65
+ })
66
+ .filter((x) => Date.parse(x.created_at) >= startTime);
67
+ };
68
+ provideInterestRateService(terminal, {
69
+ product_id_prefix: 'BINANCE/USDT-FUTURE/',
70
+ direction: 'forward',
71
+ }, fetchUsdtFutureFundingRateForward, INGEST_SERVICE_OPTIONS);
72
+ provideInterestRateService(terminal, {
73
+ product_id_prefix: 'BINANCE/MARGIN/',
74
+ direction: 'forward',
75
+ }, fetchMarginBorrowRateForward, INGEST_SERVICE_OPTIONS);
76
+ //# sourceMappingURL=interest-rate-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interest-rate-service.js","sourceRoot":"","sources":["../../src/services/interest-rate-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { IInterestRate } from '@yuants/data-interest-rate';\nimport { provideInterestRateService } from '@yuants/exchange';\nimport { IServiceOptions, Terminal } from '@yuants/protocol';\nimport { decodePath, formatTime } from '@yuants/utils';\nimport { getMarginInterestRateHistory } from '../api/private-api';\nimport { getFutureFundingRate } from '../api/public-api';\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst INGEST_SERVICE_OPTIONS: IServiceOptions = {\n concurrent: 1,\n max_pending_requests: 20,\n ingress_token_capacity: 2,\n ingress_token_refill_interval: 1000,\n egress_token_capacity: 1,\n egress_token_refill_interval: 1000,\n};\n\nconst WINDOW_MS = 365 * 24 * 3600_000;\n\nconst fetchUsdtFutureFundingRateForward = async (req: {\n product_id: string;\n time: number;\n series_id: string;\n}): Promise<IInterestRate[]> => {\n const [, instType, symbol] = decodePath(req.product_id);\n if (instType !== 'USDT-FUTURE' || !symbol) throw new Error(`Unsupported product_id: ${req.product_id}`);\n\n const startTime = req.time;\n const res = await getFutureFundingRate({\n symbol,\n startTime,\n endTime: startTime + WINDOW_MS,\n limit: 1000,\n });\n\n return (res ?? [])\n .map((v): IInterestRate => {\n const ms = Number(v.fundingTime);\n const rate = Number(v.fundingRate);\n return {\n series_id: req.series_id,\n product_id: req.product_id,\n datasource_id: 'BINANCE',\n created_at: formatTime(ms),\n long_rate: `${-rate}`,\n short_rate: `${rate}`,\n settlement_price: '',\n };\n })\n .filter((x) => Date.parse(x.created_at) >= startTime);\n};\n\nconst fetchMarginBorrowRateForward = async (req: {\n product_id: string;\n time: number;\n series_id: string;\n}): Promise<IInterestRate[]> => {\n const [, instType, asset] = decodePath(req.product_id);\n if (instType !== 'MARGIN' || !asset) throw new Error(`Unsupported product_id: ${req.product_id}`);\n\n const startTime = req.time;\n const res = await getMarginInterestRateHistory({\n asset,\n startTime,\n endTime: startTime + WINDOW_MS,\n limit: 100,\n });\n\n return (res ?? [])\n .map((v): IInterestRate => {\n return {\n series_id: req.series_id,\n product_id: req.product_id,\n datasource_id: 'BINANCE',\n created_at: formatTime(v.timestamp),\n long_rate: v.dailyInterestRate,\n short_rate: '0',\n settlement_price: '',\n };\n })\n .filter((x) => Date.parse(x.created_at) >= startTime);\n};\n\nprovideInterestRateService(\n terminal,\n {\n product_id_prefix: 'BINANCE/USDT-FUTURE/',\n direction: 'forward',\n },\n fetchUsdtFutureFundingRateForward,\n INGEST_SERVICE_OPTIONS,\n);\n\nprovideInterestRateService(\n terminal,\n {\n product_id_prefix: 'BINANCE/MARGIN/',\n direction: 'forward',\n },\n fetchMarginBorrowRateForward,\n INGEST_SERVICE_OPTIONS,\n);\n"]}