From 9f1c1c9cd7adce446ffd882a0c2ab2d07e45bbdb Mon Sep 17 00:00:00 2001 From: pcriadoperez Date: Tue, 16 Apr 2024 15:20:07 +0700 Subject: [PATCH 1/8] feat(kucoinfutures): add watchPositions --- ts/src/pro/kucoinfutures.ts | 97 ++++++++++++++++++++++++++++++++----- 1 file changed, 85 insertions(+), 12 deletions(-) diff --git a/ts/src/pro/kucoinfutures.ts b/ts/src/pro/kucoinfutures.ts index 587027d7f0d6..b75876321ceb 100644 --- a/ts/src/pro/kucoinfutures.ts +++ b/ts/src/pro/kucoinfutures.ts @@ -21,8 +21,8 @@ export default class kucoinfutures extends kucoinfuturesRest { 'watchOrders': true, 'watchBalance': true, 'watchPosition': true, - 'watchPositions': false, - 'watchPositionForSymbols': false, + 'watchPositions': true, + 'watchPositionForSymbols': true, 'watchTradesForSymbols': true, 'watchOrderBookForSymbols': true, }, @@ -49,6 +49,10 @@ export default class kucoinfutures extends kucoinfuturesRest { 'fetchPositionSnapshot': true, // or false 'awaitPositionSnapshot': true, // whether to wait for the position snapshot before providing updates }, + 'watchPositions': { + 'fetchPositionsSnapshot': true, // or false + 'awaitPositionsSnapshot': true, // whether to wait for the position snapshot before providing updates + }, }, 'streaming': { // kucoin does not support built-in ws protocol-level ping-pong @@ -339,11 +343,11 @@ export default class kucoinfutures extends kucoinfuturesRest { const request = { 'privateChannel': true, }; - const messageHash = 'position:' + market['symbol']; + const messageHash = 'position::' + market['symbol']; const client = this.client (url); this.setPositionCache (client, symbol); - const fetchPositionSnapshot = this.handleOption ('watchPosition', 'fetchPositionSnapshot', true); - const awaitPositionSnapshot = this.safeBool ('watchPosition', 'awaitPositionSnapshot', true); + const fetchPositionSnapshot = this.handleOptionAndParams (params, 'watchPosition', 'fetchPositionSnapshot', true); + const awaitPositionSnapshot = this.handleOptionAndParams (params, 'watchPosition', 'awaitPositionSnapshot', true); const currentPosition = this.getCurrentPosition (symbol); if (fetchPositionSnapshot && awaitPositionSnapshot && currentPosition === undefined) { const snapshot = await client.future ('fetchPositionSnapshot:' + symbol); @@ -375,13 +379,79 @@ export default class kucoinfutures extends kucoinfuturesRest { async loadPositionSnapshot (client, messageHash, symbol) { const position = await this.fetchPosition (symbol); - this.positions = new ArrayCacheBySymbolById (); + if (this.positions === undefined) { + this.positions = new ArrayCacheBySymbolById (); + } const cache = this.positions; cache.append (position); // don't remove the future from the .futures cache const future = client.futures[messageHash]; future.resolve (cache); - client.resolve (position, 'position:' + symbol); + client.resolve (position, 'position::' + symbol); + } + + async watchPositions (symbols: Strings = undefined, since: Int = undefined, limit: Int = undefined, params = {}): Promise { + /** + * @method + * @name kucoinfutures#watchPositions + * @description watch open positions for all symbols or a set of symbols + * @see https://www.kucoin.com/docs/websocket/futures-trading/private-channels/all-position-change-events + * @param {string[]|undefined} symbols list of unified market symbols + * @param {object} params extra parameters specific to the exchange API endpoint + * @returns {object} a [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure} + */ + await this.loadMarkets (); + const url = await this.negotiate (true); + symbols = this.marketSymbols (symbols, undefined, true, true, false); + const topic = '/contract/positionAll'; + let messageHash = 'position'; + const request = { + 'privateChannel': true, + }; + if (!this.isEmpty (symbols)) { + messageHash = '::' + symbols.join (','); + } + const client = this.client (url); + this.setPositionsCache (client); + const fetchPositionsSnapshot = this.handleOptionAndParams (params, 'watchPositions', 'fetchPositionsSnapshot', true); + const awaitPositionsSnapshot = this.handleOptionAndParams (params, 'watchPositions', 'awaitPositionsSnapshot', true); + const hasReturnedPositionsSnapshot = this.safeBool (this.options, 'hasReturnedPositionsSnapshot', false); + if (fetchPositionsSnapshot && awaitPositionsSnapshot && hasReturnedPositionsSnapshot === false) { + const snapshot = await client.future ('fetchPositionsSnapshot'); + this.options['hasReturnedPositionsSnapshot'] = true; + return this.filterBySymbolsSinceLimit (snapshot, symbols, since, limit, true); + } + const newPosition = await this.subscribe (url, messageHash, topic, undefined, this.extend (request, params)); + if (this.newUpdates) { + return this.filterBySymbolsSinceLimit ([ newPosition ], symbols, since, limit, true); + } + return this.filterBySymbolsSinceLimit (this.positions, symbols, since, limit, true); + } + + setPositionsCache (client: Client) { + const fetchPositionsSnapshot = this.handleOption ('watchPositions', 'fetchPositionsSnapshot', false); + if (fetchPositionsSnapshot) { + const messageHash = 'fetchPositionsSnapshot'; + if (!(messageHash in client.futures)) { + client.future (messageHash); + this.spawn (this.loadPositionsSnapshot, client, messageHash); + } + } + } + + async loadPositionsSnapshot (client, messageHash) { + const positions = await this.fetchPositions (); + if (this.positions === undefined) { + this.positions = new ArrayCacheBySymbolById (); + } + const cache = this.positions; + for (let i = 0; i < positions.length; i++) { + cache.append (positions[i]); + } + // don't remove the future from the .futures cache + const future = client.futures[messageHash]; + future.resolve (cache); + client.resolve (this.positions, 'position'); } handlePosition (client: Client, message) { @@ -479,13 +549,14 @@ export default class kucoinfutures extends kucoinfuturesRest { // const topic = this.safeString (message, 'topic', ''); const parts = topic.split (':'); - const marketId = this.safeString (parts, 1); - const symbol = this.safeSymbol (marketId, undefined, ''); + const marketIdFromTopic = this.safeString (parts, 1); const cache = this.positions; - const currentPosition = this.getCurrentPosition (symbol); - const messageHash = 'position:' + symbol; const data = this.safeValue (message, 'data', {}); - const newPosition = this.parsePosition (data); + const marketId = this.safeString (data, 'symbol', marketIdFromTopic); + const symbol = this.safeSymbol (marketId, undefined, ''); + const market = this.safeMarket (marketId); + const currentPosition = this.getCurrentPosition (symbol); + const newPosition = this.parsePosition (data, market); const keys = Object.keys (newPosition); for (let i = 0; i < keys.length; i++) { const key = keys[i]; @@ -494,8 +565,10 @@ export default class kucoinfutures extends kucoinfuturesRest { } } const position = this.extend (currentPosition, newPosition); + const messageHash = 'position::' + symbol; cache.append (position); client.resolve (position, messageHash); + client.resolve (position, 'position'); } async watchTrades (symbol: string, since: Int = undefined, limit: Int = undefined, params = {}): Promise { From 7efd318358cca2b3b6ce000f7346083c57b1dd31 Mon Sep 17 00:00:00 2001 From: pcriadoperez Date: Tue, 16 Apr 2024 15:37:51 +0700 Subject: [PATCH 2/8] lint --- ts/src/pro/kucoinfutures.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/src/pro/kucoinfutures.ts b/ts/src/pro/kucoinfutures.ts index b75876321ceb..4cf2c7b94c21 100644 --- a/ts/src/pro/kucoinfutures.ts +++ b/ts/src/pro/kucoinfutures.ts @@ -416,7 +416,7 @@ export default class kucoinfutures extends kucoinfuturesRest { const fetchPositionsSnapshot = this.handleOptionAndParams (params, 'watchPositions', 'fetchPositionsSnapshot', true); const awaitPositionsSnapshot = this.handleOptionAndParams (params, 'watchPositions', 'awaitPositionsSnapshot', true); const hasReturnedPositionsSnapshot = this.safeBool (this.options, 'hasReturnedPositionsSnapshot', false); - if (fetchPositionsSnapshot && awaitPositionsSnapshot && hasReturnedPositionsSnapshot === false) { + if (fetchPositionsSnapshot && awaitPositionsSnapshot && !hasReturnedPositionsSnapshot) { const snapshot = await client.future ('fetchPositionsSnapshot'); this.options['hasReturnedPositionsSnapshot'] = true; return this.filterBySymbolsSinceLimit (snapshot, symbols, since, limit, true); From 53652ef8073a2529c56580d54f66e4857489fc1a Mon Sep 17 00:00:00 2001 From: pcriadoperez Date: Thu, 18 Apr 2024 00:25:35 +0700 Subject: [PATCH 3/8] update package.json --- package-lock.json | 11 +++++++---- package.json | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1735ed45cb30..8e2469c8789d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,9 @@ "dependencies": { "ws": "^8.8.1" }, + "bin": { + "ccxt": "examples/js/cli.js" + }, "devDependencies": { "@rollup/plugin-commonjs": "^21.0.3", "@rollup/plugin-json": "^4.1.0", @@ -23,7 +26,7 @@ "as-table": "1.0.37", "asciichart": "^1.5.25", "assert": "^2.0.0", - "ast-transpiler": "^0.0.44", + "ast-transpiler": "^0.0.46", "docsify": "^4.11.4", "eslint": "8.22.0", "eslint-config-airbnb-base": "15.0.0", @@ -1692,9 +1695,9 @@ } }, "node_modules/ast-transpiler": { - "version": "0.0.44", - "resolved": "https://registry.npmjs.org/ast-transpiler/-/ast-transpiler-0.0.44.tgz", - "integrity": "sha512-MWKD8UZxKMLpOa3YyL6apC1jEux9Tf/5qAaQX8C9X/gnG6A2/KeJSt2iO9ylK8HeFpStQ4k6nSk1S7fTHMyxIw==", + "version": "0.0.46", + "resolved": "https://registry.npmjs.org/ast-transpiler/-/ast-transpiler-0.0.46.tgz", + "integrity": "sha512-PUa3uV74eTEcYEM322ISjlTwt9tCUaC/vUuhWDuNfxklpPR/kGqwqhJOz1Z0H2843iD0hv/ka4u7ApmDaZJKlA==", "dev": true, "dependencies": { "colorette": "^2.0.19", diff --git a/package.json b/package.json index 7cadcf79c78e..2a34b7b25afb 100644 --- a/package.json +++ b/package.json @@ -151,7 +151,7 @@ "as-table": "1.0.37", "asciichart": "^1.5.25", "assert": "^2.0.0", - "ast-transpiler": "^0.0.44", + "ast-transpiler": "^0.0.46", "docsify": "^4.11.4", "eslint": "8.22.0", "eslint-config-airbnb-base": "15.0.0", From ce64734110ef8dc7913e1e650046ee61635a0b4f Mon Sep 17 00:00:00 2001 From: carlosmiei <43336371+carlosmiei@users.noreply.github.com> Date: Thu, 18 Apr 2024 11:07:21 +0100 Subject: [PATCH 4/8] protect crash --- ts/src/pro/kucoinfutures.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ts/src/pro/kucoinfutures.ts b/ts/src/pro/kucoinfutures.ts index 4cf2c7b94c21..bf1dc9fc9f78 100644 --- a/ts/src/pro/kucoinfutures.ts +++ b/ts/src/pro/kucoinfutures.ts @@ -555,7 +555,10 @@ export default class kucoinfutures extends kucoinfuturesRest { const marketId = this.safeString (data, 'symbol', marketIdFromTopic); const symbol = this.safeSymbol (marketId, undefined, ''); const market = this.safeMarket (marketId); - const currentPosition = this.getCurrentPosition (symbol); + let currentPosition = this.getCurrentPosition (symbol); + if (currentPosition === undefined) { + currentPosition = {}; + } const newPosition = this.parsePosition (data, market); const keys = Object.keys (newPosition); for (let i = 0; i < keys.length; i++) { From ee1092db828802cc94f89a603602ca5bc6ef755b Mon Sep 17 00:00:00 2001 From: pcriadoperez Date: Wed, 24 Apr 2024 02:55:16 +0700 Subject: [PATCH 5/8] fix cache --- php/pro/ArrayCacheBySymbolBySide.php | 12 +++++++++++- python/ccxt/async_support/base/ws/cache.py | 9 ++++++++- ts/src/base/ws/Cache.ts | 14 +++++++++++++- ts/src/pro/kucoinfutures.ts | 11 ++++++----- ts/src/pro/test/base/test.Cache.ts | 11 +++++++++++ 5 files changed, 49 insertions(+), 8 deletions(-) diff --git a/php/pro/ArrayCacheBySymbolBySide.php b/php/pro/ArrayCacheBySymbolBySide.php index 1b1cece55601..1f18ade517bc 100644 --- a/php/pro/ArrayCacheBySymbolBySide.php +++ b/php/pro/ArrayCacheBySymbolBySide.php @@ -5,17 +5,27 @@ class ArrayCacheBySymbolBySide extends ArrayCache { public $hashmap; private $index; + private $hedged; - public function __construct($max_size = null) { + public function __construct($max_size = null, $hedged = True) { parent::__construct($max_size); $this->nested_new_updates_by_symbol = true; $this->hashmap = array(); $this->index = array(); + $this->hedged = $hedged; } public function append($item) { if (array_key_exists($item['symbol'], $this->hashmap)) { $by_side = &$this->hashmap[$item['symbol']]; + if ($this->hedged) { + $side_to_reset = $by_side == 'long' ? 'short' : 'long'; + if (array_key_exists($side_to_reset, $by_side)) { + $index = array_search($side_to_reset, $this->index); + array_splice ($this->index, $index, 1); + array_splice ($this->deque, $index, 1); + } + } } else { $by_side = array(); $this->hashmap[$item['symbol']] = &$by_side; diff --git a/python/ccxt/async_support/base/ws/cache.py b/python/ccxt/async_support/base/ws/cache.py index 6625715c1f99..9bfbbc6933e0 100644 --- a/python/ccxt/async_support/base/ws/cache.py +++ b/python/ccxt/async_support/base/ws/cache.py @@ -171,14 +171,21 @@ def append(self, item): class ArrayCacheBySymbolBySide(ArrayCache): - def __init__(self, max_size=None): + def __init__(self, max_size=None, hedged=True): super(ArrayCacheBySymbolBySide, self).__init__(max_size) self._nested_new_updates_by_symbol = True + self._hedged = hedged self.hashmap = {} self._index = collections.deque([], max_size) def append(self, item): by_side = self.hashmap.setdefault(item['symbol'], {}) + if not self._hedged: + side_to_reset = 'long' if item['side'] == 'short' else 'short' + del by_side[side_to_reset] + index = self._index.index(side_to_reset) + del self._deque[index] + del self._index[index] if item['side'] in by_side: reference = by_side[item['side']] if reference != item: diff --git a/ts/src/base/ws/Cache.ts b/ts/src/base/ws/Cache.ts index 15791b428d46..a9c0ea1deabb 100644 --- a/ts/src/base/ws/Cache.ts +++ b/ts/src/base/ws/Cache.ts @@ -221,9 +221,10 @@ class ArrayCacheBySymbolById extends ArrayCache { class ArrayCacheBySymbolBySide extends ArrayCache { - constructor () { + constructor (hedged = true) { super () this.nestedNewUpdatesBySymbol = true + this.hedged = hedged Object.defineProperty (this, 'hashmap', { __proto__: null, // make it invisible value: {}, @@ -233,6 +234,17 @@ class ArrayCacheBySymbolBySide extends ArrayCache { append (item) { const bySide = this.hashmap[item.symbol] = this.hashmap[item.symbol] || {} + if (!this.hedged) { + // if one-way mode reset other side and remove from array + const sideToReset = item.side === 'long' ? 'short' : 'long' + if (sideToReset in bySide) { + delete bySide[sideToReset] + const index = this.findIndex ((x) => x.symbol === item.symbol && x.side === sideToReset) + if (index >= 0) { + this.splice (index, 1) + } + } + } if (item.side in bySide) { const reference = bySide[item.side] if (reference !== item) { diff --git a/ts/src/pro/kucoinfutures.ts b/ts/src/pro/kucoinfutures.ts index bf1dc9fc9f78..20fc3c87fe2a 100644 --- a/ts/src/pro/kucoinfutures.ts +++ b/ts/src/pro/kucoinfutures.ts @@ -2,7 +2,7 @@ import kucoinfuturesRest from '../kucoinfutures.js'; import { ExchangeError, ArgumentsRequired } from '../base/errors.js'; -import { ArrayCache, ArrayCacheBySymbolById } from '../base/ws/Cache.js'; +import { ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide } from '../base/ws/Cache.js'; import type { Int, Str, OrderBook, Order, Trade, Ticker, Balances, Position, Strings, Tickers } from '../base/types.js'; import Client from '../base/ws/Client.js'; @@ -360,8 +360,9 @@ export default class kucoinfutures extends kucoinfuturesRest { if (this.positions === undefined) { return undefined; } - const cache = this.positions.hashmap; - const symbolCache = this.safeValue (cache, symbol, {}); + const cache = this.positions; + const positionsHashMap = cache.hashmap; + const symbolCache = this.safeValue (positionsHashMap, symbol, {}); const values = Object.values (symbolCache); return this.safeValue (values, 0); } @@ -380,7 +381,7 @@ export default class kucoinfutures extends kucoinfuturesRest { async loadPositionSnapshot (client, messageHash, symbol) { const position = await this.fetchPosition (symbol); if (this.positions === undefined) { - this.positions = new ArrayCacheBySymbolById (); + this.positions = new ArrayCacheBySymbolBySide (false); } const cache = this.positions; cache.append (position); @@ -442,7 +443,7 @@ export default class kucoinfutures extends kucoinfuturesRest { async loadPositionsSnapshot (client, messageHash) { const positions = await this.fetchPositions (); if (this.positions === undefined) { - this.positions = new ArrayCacheBySymbolById (); + this.positions = new ArrayCacheBySymbolBySide (false); } const cache = this.positions; for (let i = 0; i < positions.length; i++) { diff --git a/ts/src/pro/test/base/test.Cache.ts b/ts/src/pro/test/base/test.Cache.ts index 9ab535314922..277f07ade9c7 100644 --- a/ts/src/pro/test/base/test.Cache.ts +++ b/ts/src/pro/test/base/test.Cache.ts @@ -405,3 +405,14 @@ assert (cacheSymbolSide3.getLimit (symbol, outsideLimit) === 1); // watch by sym assert (cacheSymbolSide3.getLimit (undefined, outsideLimit) === 2); // watch all positions cacheSymbolSide3.append ({ 'symbol': symbol2, 'side': 'long', 'contracts': 3 }); // update second position assert (cacheSymbolSide3.getLimit (undefined, outsideLimit) === 1); // watch all positions + +// ---------------------------------------------------------------------------- +// test ArrayCacheBySymbolBySide, watch all positions, same symbol when not positionMode is not hedged reset other side + +const oneWayCacheSymbolSide = new ArrayCacheBySymbolBySide (false); +symbol = 'BTC/USDT'; +outsideLimit = 5; +oneWayCacheSymbolSide.append ({ 'symbol': symbol, 'side': 'short', 'contracts': 1 }); // create first position +oneWayCacheSymbolSide.append ({ 'symbol': symbol, 'side': 'long', 'contracts': 2 }); // create oposite side position +const arrayLength = oneWayCacheSymbolSide.length; +assert (arrayLength === 1); From 4f13a82a35080ccc7f4cd2cba37b46efc4f6b965 Mon Sep 17 00:00:00 2001 From: pcriadoperez Date: Sat, 27 Apr 2024 23:03:29 +0200 Subject: [PATCH 6/8] add csharp --- cs/ccxt/ws/ArrayCache.cs | 15 +++++++++++++-- cs/tests/Generated/Base/Cache.cs | 19 +++++++++++++++++++ ts/src/base/ws/Cache.ts | 8 ++++++-- ts/src/pro/kucoinfutures.ts | 4 ++-- ts/src/pro/test/base/test.Cache.ts | 2 +- 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/cs/ccxt/ws/ArrayCache.cs b/cs/ccxt/ws/ArrayCache.cs index c42e77f99015..0ca61a9df665 100644 --- a/cs/ccxt/ws/ArrayCache.cs +++ b/cs/ccxt/ws/ArrayCache.cs @@ -297,9 +297,11 @@ public class ArrayCacheBySymbolBySide : ArrayCache { // tbd incomplete public Dictionary hashmap = new Dictionary(); - public ArrayCacheBySymbolBySide(int? maxSixe = null) : base(maxSixe) + private bool hedged = true; + public ArrayCacheBySymbolBySide(int? maxSixe = null, bool hedged = true) : base(maxSixe) { this.nestedNewUpdatesBySymbol = true; + this.hedged = hedged; } public void append(object item) @@ -316,6 +318,15 @@ private void _append(object item) var itemSide = Exchange.SafeString(item, "side"); var bySide = (this.hashmap.ContainsKey(itemSymbol)) ? this.hashmap[itemSide] as Dictionary : new Dictionary(); + if (!this.hedged) { + var sideToReset = itemSide == "long" ? "short" : "long"; + if (bySide.ContainsKey(sideToReset)) { + bySide.Remove(sideToReset); + var value = this.Find(x => Exchange.SafeString (x, "symbol") == itemSymbol && Exchange.SafeString (x, "side") == sideToReset); + var indexInt = this.IndexOf(value); + this.RemoveAt(indexInt); + } + } if (bySide.ContainsKey(itemSide)) { var reference = bySide[itemSide]; @@ -365,4 +376,4 @@ private void _append(object item) this.allNewUpdates = defaultAllNewUpdates + (afterLength - beforeLength); } } -// } \ No newline at end of file +// } diff --git a/cs/tests/Generated/Base/Cache.cs b/cs/tests/Generated/Base/Cache.cs index ed645fae1fa0..c6369ed1313c 100644 --- a/cs/tests/Generated/Base/Cache.cs +++ b/cs/tests/Generated/Base/Cache.cs @@ -614,5 +614,24 @@ public void CacheTests() { "contracts", 3 }, }); // update second position Assert(isEqual(cacheSymbolSide3.getLimit(null, outsideLimit), 1)); // watch all positions + + // ---------------------------------------------------------------------------- + + // test ArrayCacheBySymbolBySide, watch all positions, same symbol when not positionMode is not hedged reset other side + var oneWayCacheSymbolSide = new ArrayCacheBySymbolBySide(null, false); + symbol = "BTC/USDT"; + outsideLimit = 5; + oneWayCacheSymbolSide.append(new Dictionary() { + { "symbol", symbol }, + { "side", "short" }, + { "contracts", 1 }, + }); // create first position + oneWayCacheSymbolSide.append(new Dictionary() { + { "symbol", symbol }, + { "side", "long" }, + { "contracts", 2 }, + }); // create oposite side position + object arrayLength = getArrayLength(oneWayCacheSymbolSide); + Assert(isEqual(arrayLength, 1)); } } \ No newline at end of file diff --git a/ts/src/base/ws/Cache.ts b/ts/src/base/ws/Cache.ts index a9c0ea1deabb..c850655efe9d 100644 --- a/ts/src/base/ws/Cache.ts +++ b/ts/src/base/ws/Cache.ts @@ -221,8 +221,8 @@ class ArrayCacheBySymbolById extends ArrayCache { class ArrayCacheBySymbolBySide extends ArrayCache { - constructor (hedged = true) { - super () + constructor (maxSize = undefined, hedged = true) { + super (maxSize) this.nestedNewUpdatesBySymbol = true this.hedged = hedged Object.defineProperty (this, 'hashmap', { @@ -259,6 +259,10 @@ class ArrayCacheBySymbolBySide extends ArrayCache { } else { bySide[item.side] = item } + if (this.maxSize && (this.length === this.maxSize)) { + const deleteReference = this.shift () + delete this.hashmap[deleteReference.symbol][deleteReference.side] + } this.push (item) if (this.clearAllUpdates) { this.clearAllUpdates = false diff --git a/ts/src/pro/kucoinfutures.ts b/ts/src/pro/kucoinfutures.ts index 20fc3c87fe2a..e8103c318bb7 100644 --- a/ts/src/pro/kucoinfutures.ts +++ b/ts/src/pro/kucoinfutures.ts @@ -381,7 +381,7 @@ export default class kucoinfutures extends kucoinfuturesRest { async loadPositionSnapshot (client, messageHash, symbol) { const position = await this.fetchPosition (symbol); if (this.positions === undefined) { - this.positions = new ArrayCacheBySymbolBySide (false); + this.positions = new ArrayCacheBySymbolBySide (undefined, false); } const cache = this.positions; cache.append (position); @@ -443,7 +443,7 @@ export default class kucoinfutures extends kucoinfuturesRest { async loadPositionsSnapshot (client, messageHash) { const positions = await this.fetchPositions (); if (this.positions === undefined) { - this.positions = new ArrayCacheBySymbolBySide (false); + this.positions = new ArrayCacheBySymbolBySide (undefined, false); } const cache = this.positions; for (let i = 0; i < positions.length; i++) { diff --git a/ts/src/pro/test/base/test.Cache.ts b/ts/src/pro/test/base/test.Cache.ts index 277f07ade9c7..a73da600c8f6 100644 --- a/ts/src/pro/test/base/test.Cache.ts +++ b/ts/src/pro/test/base/test.Cache.ts @@ -409,7 +409,7 @@ assert (cacheSymbolSide3.getLimit (undefined, outsideLimit) === 1); // watch all // ---------------------------------------------------------------------------- // test ArrayCacheBySymbolBySide, watch all positions, same symbol when not positionMode is not hedged reset other side -const oneWayCacheSymbolSide = new ArrayCacheBySymbolBySide (false); +const oneWayCacheSymbolSide = new ArrayCacheBySymbolBySide (undefined, false); symbol = 'BTC/USDT'; outsideLimit = 5; oneWayCacheSymbolSide.append ({ 'symbol': symbol, 'side': 'short', 'contracts': 1 }); // create first position From 1e46ff64187422a2a60e1491f27677c42dda2d49 Mon Sep 17 00:00:00 2001 From: pcriadoperez Date: Sun, 28 Apr 2024 22:34:14 +0200 Subject: [PATCH 7/8] lint --- python/ccxt/async_support/base/ws/cache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ccxt/async_support/base/ws/cache.py b/python/ccxt/async_support/base/ws/cache.py index 9bfbbc6933e0..ba0b590fc012 100644 --- a/python/ccxt/async_support/base/ws/cache.py +++ b/python/ccxt/async_support/base/ws/cache.py @@ -180,7 +180,7 @@ def __init__(self, max_size=None, hedged=True): def append(self, item): by_side = self.hashmap.setdefault(item['symbol'], {}) - if not self._hedged: + if not self._hedged: side_to_reset = 'long' if item['side'] == 'short' else 'short' del by_side[side_to_reset] index = self._index.index(side_to_reset) From 6f001cd759f12840a25cdfa8e30634736f30b591 Mon Sep 17 00:00:00 2001 From: pcriadoperez Date: Mon, 29 Apr 2024 00:19:21 +0200 Subject: [PATCH 8/8] fix python cache --- python/ccxt/async_support/base/ws/cache.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/python/ccxt/async_support/base/ws/cache.py b/python/ccxt/async_support/base/ws/cache.py index ba0b590fc012..1bd6f930a8bb 100644 --- a/python/ccxt/async_support/base/ws/cache.py +++ b/python/ccxt/async_support/base/ws/cache.py @@ -182,10 +182,11 @@ def append(self, item): by_side = self.hashmap.setdefault(item['symbol'], {}) if not self._hedged: side_to_reset = 'long' if item['side'] == 'short' else 'short' - del by_side[side_to_reset] - index = self._index.index(side_to_reset) - del self._deque[index] - del self._index[index] + if side_to_reset in by_side: + del by_side[side_to_reset] + index = self._index.index(side_to_reset) + del self._deque[index] + del self._index[index] if item['side'] in by_side: reference = by_side[item['side']] if reference != item: