UNPKG

sfccxt

Version:

A JavaScript / Python / PHP cryptocurrency trading library with support for 130+ exchanges

356 lines (278 loc) 10.8 kB
'use strict'; const assert = require ('assert'); const { ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById } = require ('../../base/Cache'); function equals (a, b) { if (a.length !== b.length) { return false; } for (const prop in a) { if (Array.isArray (a[prop]) || typeof a[prop] === 'object') { if (!equals (a[prop], b[prop])) { return false; } } else if (a[prop] !== b[prop]) { return false; } } return true; } // ---------------------------------------------------------------------------- let cache = new ArrayCache (3); cache.append ({ 'symbol': 'BTC/USDT', 'data': 1 }); cache.append ({ 'symbol': 'BTC/USDT', 'data': 2 }); cache.append ({ 'symbol': 'BTC/USDT', 'data': 3 }); cache.append ({ 'symbol': 'BTC/USDT', 'data': 4 }); assert (equals (cache, [ { 'symbol': 'BTC/USDT', 'data': 2 }, { 'symbol': 'BTC/USDT', 'data': 3 }, { 'symbol': 'BTC/USDT', 'data': 4 }, ])); cache.append ({ 'symbol': 'BTC/USDT', 'data': 5 }); cache.append ({ 'symbol': 'BTC/USDT', 'data': 6 }); cache.append ({ 'symbol': 'BTC/USDT', 'data': 7 }); cache.append ({ 'symbol': 'BTC/USDT', 'data': 8 }); assert (equals (cache, [ { 'symbol': 'BTC/USDT', 'data': 6 }, { 'symbol': 'BTC/USDT', 'data': 7 }, { 'symbol': 'BTC/USDT', 'data': 8 }, ])); cache.clear (); cache.append ({ 'symbol': 'BTC/USDT', 'data': 1 }); assert (equals (cache, [ { 'symbol': 'BTC/USDT', 'data': 1 }, ])); // ---------------------------------------------------------------------------- cache = new ArrayCache (1); cache.append ({ 'symbol': 'BTC/USDT', 'data': 1 }); cache.append ({ 'symbol': 'BTC/USDT', 'data': 2 }); assert (equals (cache, [ { 'symbol': 'BTC/USDT', 'data': 2 }, ])); // ---------------------------------------------------------------------------- cache = new ArrayCacheByTimestamp (); const ohlcv1 = [100, 1, 2, 3]; const ohlcv2 = [200, 5, 6, 7]; cache.append (ohlcv1); cache.append (ohlcv2); assert (equals (cache, [ohlcv1, ohlcv2])); const modify2 = [200, 10, 11, 12]; cache.append (modify2); assert (equals (cache, [ohlcv1, modify2])); // ---------------------------------------------------------------------------- cache = new ArrayCacheBySymbolById (); const object1 = { 'symbol': 'BTC/USDT', 'id': 'abcdef', 'i': 1 }; const object2 = { 'symbol': 'ETH/USDT', 'id': 'qwerty', 'i': 2 }; const object3 = { 'symbol': 'BTC/USDT', 'id': 'abcdef', 'i': 3 }; cache.append (object1); cache.append (object2); cache.append (object3); // should update index 0 assert (equals (cache, [ object2, object3 ])); cache = new ArrayCacheBySymbolById (5); for (let i = 1; i < 11; i++) { cache.append ({ 'symbol': 'BTC/USDT', 'id': i.toString (), 'i': i, }); } assert (equals (cache, [ { 'symbol': 'BTC/USDT', 'id': '6', 'i': 6 }, { 'symbol': 'BTC/USDT', 'id': '7', 'i': 7 }, { 'symbol': 'BTC/USDT', 'id': '8', 'i': 8 }, { 'symbol': 'BTC/USDT', 'id': '9', 'i': 9 }, { 'symbol': 'BTC/USDT', 'id': '10', 'i': 10 }, ])); for (let i = 1; i < 11; i++) { cache.append ({ 'symbol': 'BTC/USDT', 'id': i.toString (), 'i': i + 10, }); } assert (equals (cache, [ { 'symbol': 'BTC/USDT', 'id': '6', 'i': 16 }, { 'symbol': 'BTC/USDT', 'id': '7', 'i': 17 }, { 'symbol': 'BTC/USDT', 'id': '8', 'i': 18 }, { 'symbol': 'BTC/USDT', 'id': '9', 'i': 19 }, { 'symbol': 'BTC/USDT', 'id': '10', 'i': 20 }, ])); const middle = { 'symbol': 'BTC/USDT', 'id': '8', 'i': 28 }; cache.append (middle); assert (equals (cache, [ { 'symbol': 'BTC/USDT', 'id': '6', 'i': 16 }, { 'symbol': 'BTC/USDT', 'id': '7', 'i': 17 }, { 'symbol': 'BTC/USDT', 'id': '9', 'i': 19 }, { 'symbol': 'BTC/USDT', 'id': '10', 'i': 20 }, { 'symbol': 'BTC/USDT', 'id': '8', 'i': 28 }, ])); const otherMiddle = { 'symbol': 'BTC/USDT', 'id': '7', 'i': 27 }; cache.append (otherMiddle); assert (equals (cache, [ { 'symbol': 'BTC/USDT', 'id': '6', 'i': 16 }, { 'symbol': 'BTC/USDT', 'id': '9', 'i': 19 }, { 'symbol': 'BTC/USDT', 'id': '10', 'i': 20 }, { 'symbol': 'BTC/USDT', 'id': '8', 'i': 28 }, { 'symbol': 'BTC/USDT', 'id': '7', 'i': 27 }, ])); for (let i = 30; i < 33; i++) { cache.append ({ 'symbol': 'BTC/USDT', 'id': i.toString (), 'i': i + 10, }); } assert (equals (cache, [ { 'symbol': 'BTC/USDT', 'id': '8', 'i': 28 }, { 'symbol': 'BTC/USDT', 'id': '7', 'i': 27 }, { 'symbol': 'BTC/USDT', 'id': '30', 'i': 40 }, { 'symbol': 'BTC/USDT', 'id': '31', 'i': 41 }, { 'symbol': 'BTC/USDT', 'id': '32', 'i': 42 } ])); const first = { 'symbol': 'BTC/USDT', 'id': '8', 'i': 38 }; cache.append (first); assert (equals (cache, [ { 'symbol': 'BTC/USDT', 'id': '7', 'i': 27 }, { 'symbol': 'BTC/USDT', 'id': '30', 'i': 40 }, { 'symbol': 'BTC/USDT', 'id': '31', 'i': 41 }, { 'symbol': 'BTC/USDT', 'id': '32', 'i': 42 }, { 'symbol': 'BTC/USDT', 'id': '8', 'i': 38 }, ])); const another = { 'symbol': 'BTC/USDT', 'id': '30', 'i': 50 }; cache.append (another); assert (equals (cache, [ { 'symbol': 'BTC/USDT', 'id': '7', 'i': 27 }, { 'symbol': 'BTC/USDT', 'id': '31', 'i': 41 }, { 'symbol': 'BTC/USDT', 'id': '32', 'i': 42 }, { 'symbol': 'BTC/USDT', 'id': '8', 'i': 38 }, { 'symbol': 'BTC/USDT', 'id': '30', 'i': 50 }, ])); // ---------------------------------------------------------------------------- // test ArrayCacheBySymbolById limit with symbol set let symbol = 'BTC/USDT'; cache = new ArrayCacheBySymbolById (); let initialLength = 5; for (let i = 0; i < initialLength; i++) { cache.append ({ 'symbol': symbol, 'id': i.toString (), 'i': i, }); } let limited = cache.getLimit (symbol, undefined); assert (initialLength === limited); cache = new ArrayCacheBySymbolById (); let appendItemsLength = 3; for (let i = 0; i < appendItemsLength; i++) { cache.append ({ 'symbol': symbol, 'id': i.toString (), 'i': i, }); } let outsideLimit = 5; limited = cache.getLimit (symbol, outsideLimit); assert (appendItemsLength === limited); outsideLimit = 2; // if limit < newsUpdate that should be returned limited = cache.getLimit (symbol, outsideLimit); assert (outsideLimit === limited); // ---------------------------------------------------------------------------- // test ArrayCacheBySymbolById limit with symbol undefined symbol = 'BTC/USDT'; cache = new ArrayCacheBySymbolById (); initialLength = 5; for (let i = 0; i < initialLength; i++) { cache.append ({ 'symbol': symbol, 'id': i.toString (), 'i': i, }); } limited = cache.getLimit (undefined, undefined); assert (initialLength === limited); cache = new ArrayCacheBySymbolById (); appendItemsLength = 3; for (let i = 0; i < appendItemsLength; i++) { cache.append ({ 'symbol': symbol, 'id': i.toString (), 'i': i, }); } outsideLimit = 5; limited = cache.getLimit (symbol, outsideLimit); assert (appendItemsLength === limited); outsideLimit = 2; // if limit < newsUpdate that should be returned limited = cache.getLimit (symbol, outsideLimit); assert (outsideLimit === limited); // ---------------------------------------------------------------------------- // test ArrayCacheBySymbolById, same order should not increase the limit cache = new ArrayCacheBySymbolById (); symbol = 'BTC/USDT'; const otherSymbol = 'ETH/USDT'; cache.append ({ 'symbol': symbol, 'id': 'singleId', 'i': 3 }); cache.append ({ 'symbol': symbol, 'id': 'singleId', 'i': 3 }); cache.append ({ 'symbol': otherSymbol, 'id': 'singleId', 'i': 3 }); outsideLimit = 5; limited = cache.getLimit (symbol, outsideLimit); const limited2 = cache.getLimit (undefined, outsideLimit); assert (1 == limited); assert (2 == limited2); // ---------------------------------------------------------------------------- // test testLimitArrayCacheByTimestamp limit cache = new ArrayCacheByTimestamp (); initialLength = 5; for (let i = 0; i < initialLength; i++) { cache.append ([ i * 10, i * 10, i * 10, i * 10 ]); } limited = cache.getLimit (undefined, undefined); assert (initialLength === limited); appendItemsLength = 3; for (let i = 0; i < appendItemsLength; i++) { cache.append ([ i * 4, i * 4, i * 4, i * 4 ]); } outsideLimit = 5; limited = cache.getLimit (undefined, outsideLimit); assert (appendItemsLength === limited); outsideLimit = 2; // if limit < newsUpdate that should be returned limited = cache.getLimit (undefined, outsideLimit); assert (outsideLimit === limited); // ---------------------------------------------------------------------------- // test ArrayCacheBySymbolById, watch all orders, same symbol and order id gets updated cache = new ArrayCacheBySymbolById (); symbol = 'BTC/USDT'; outsideLimit = 5; cache.append ({ 'symbol': symbol, 'id': 'oneId', 'i': 3 }); // create first order cache.getLimit (undefined, outsideLimit); // watch all orders cache.append ({ 'symbol': symbol, 'id': 'oneId', 'i': 4 }); // first order is closed cache.getLimit (undefined, outsideLimit); // watch all orders cache.append ({ 'symbol': symbol, 'id': 'twoId', 'i': 5 }); // create second order cache.getLimit (undefined, outsideLimit); // watch all orders cache.append ({ 'symbol': symbol, 'id': 'twoId', 'i': 6 }); // second order is closed limited = cache.getLimit (undefined, outsideLimit); // watch all orders assert (limited === 1); // one new update // ---------------------------------------------------------------------------- // test ArrayCacheBySymbolById, watch all orders, and watchOrders (symbol) work independently cache = new ArrayCacheBySymbolById (); symbol = 'BTC/USDT'; const symbol2 = 'ETH/USDT'; outsideLimit = 5; cache.append ({ 'symbol': symbol, 'id': 'one', 'i': 1 }); // create first order cache.append ({ 'symbol': symbol2, 'id': 'two', 'i': 1 }); // create second order assert (cache.getLimit (undefined, outsideLimit) === 2); // watch all orders assert (cache.getLimit (symbol, outsideLimit) === 1); // watch by symbol cache.append ({ 'symbol': symbol, 'id': 'one', 'i': 2 }); // update first order cache.append ({ 'symbol': symbol2, 'id': 'two', 'i': 2 }); // update second order assert (cache.getLimit (symbol, outsideLimit) === 1); // watch by symbol assert (cache.getLimit (undefined, outsideLimit) === 2); // watch all orders cache.append ({ 'symbol': symbol2, 'id': 'two', 'i': 3 }); // update second order cache.append ({ 'symbol': symbol2, 'id': 'three', 'i': 3 }); // create third order assert (cache.getLimit (undefined, outsideLimit) === 2); // watch all orders