puvox-library 1.0.12 → 1.0.14
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.
- package/library_standard.js +229 -3
- package/package.json +1 -1
- package/test.js +4 -1
package/library_standard.js
CHANGED
@@ -158,7 +158,7 @@ const puvox_library =
|
|
158
158
|
stringToArrayToNumeric(arr){
|
159
159
|
return this.stringArrayToNumeric(this.stringToArray(arr));
|
160
160
|
},
|
161
|
-
|
161
|
+
|
162
162
|
objectCopy(obj){
|
163
163
|
return JSON.parse(JSON.stringify(obj));
|
164
164
|
},
|
@@ -1303,8 +1303,6 @@ const puvox_library =
|
|
1303
1303
|
)
|
1304
1304
|
},
|
1305
1305
|
|
1306
|
-
milliseconds(){ return (new Date().getTime()); },
|
1307
|
-
|
1308
1306
|
fancyTimeFormat(time)
|
1309
1307
|
{
|
1310
1308
|
var time = time.toFixed(0);
|
@@ -2945,6 +2943,234 @@ const puvox_library =
|
|
2945
2943
|
return filesList;
|
2946
2944
|
},
|
2947
2945
|
},
|
2946
|
+
|
2947
|
+
|
2948
|
+
|
2949
|
+
|
2950
|
+
|
2951
|
+
|
2952
|
+
|
2953
|
+
|
2954
|
+
|
2955
|
+
|
2956
|
+
|
2957
|
+
|
2958
|
+
|
2959
|
+
|
2960
|
+
|
2961
|
+
|
2962
|
+
|
2963
|
+
|
2964
|
+
|
2965
|
+
|
2966
|
+
// region: ####### from CCXT ##########
|
2967
|
+
// generic
|
2968
|
+
keys: Object.keys,
|
2969
|
+
values(x) { return ((!this.isArray (x)) ? Object.values (x) : x);},
|
2970
|
+
extend(...args) { return Object.assign ({}, ...args) ;}, // NB: side-effect free
|
2971
|
+
clone(x){ return (this.isArray (x) ? Array.from (x) : this.extend (x)) ;},
|
2972
|
+
index(x) { return new Set (this.values (x));},
|
2973
|
+
ordered: (x) => x, // a stub to keep assoc keys in order (in JS it does nothing, it's mostly for Python)
|
2974
|
+
unique(x) { return Array.from (this.index (x));},
|
2975
|
+
arrayConcat: (a, b) => a.concat (b),
|
2976
|
+
inArray (needle, haystack) {
|
2977
|
+
return haystack.includes (needle);
|
2978
|
+
},
|
2979
|
+
toArray (object) {
|
2980
|
+
return Object.values (object);
|
2981
|
+
},
|
2982
|
+
isEmpty (object) {
|
2983
|
+
if (!object) {
|
2984
|
+
return true;
|
2985
|
+
}
|
2986
|
+
return (Array.isArray (object) ? object : Object.keys (object)).length < 1;
|
2987
|
+
},
|
2988
|
+
keysort (x, out = {}) {
|
2989
|
+
for (const k of this.keys (x).sort ()) {
|
2990
|
+
out[k] = x[k];
|
2991
|
+
}
|
2992
|
+
return out;
|
2993
|
+
},
|
2994
|
+
indexBy (x, k, out = {}) {
|
2995
|
+
// description: https://github.com/ccxt/ccxt/blob/master/js/base/functions/generic.js
|
2996
|
+
for (const v of this.values (x)) {
|
2997
|
+
if (k in v) {
|
2998
|
+
out[v[k]] = v;
|
2999
|
+
}
|
3000
|
+
}
|
3001
|
+
|
3002
|
+
return out;
|
3003
|
+
},
|
3004
|
+
groupBy (x, k, out = {}) {
|
3005
|
+
// description: https://github.com/ccxt/ccxt/blob/master/js/base/functions/generic.js
|
3006
|
+
for (const v of this.values (x)) {
|
3007
|
+
if (k in v) {
|
3008
|
+
const p = v[k];
|
3009
|
+
out[p] = out[p] || [];
|
3010
|
+
out[p].push (v);
|
3011
|
+
}
|
3012
|
+
}
|
3013
|
+
return out;
|
3014
|
+
},
|
3015
|
+
filterBy (x, k, value = undefined, out = []) {
|
3016
|
+
// description: https://github.com/ccxt/ccxt/blob/master/js/base/functions/generic.js
|
3017
|
+
for (const v of this.values (x)) {
|
3018
|
+
if (v[k] === value) {
|
3019
|
+
out.push (v);
|
3020
|
+
}
|
3021
|
+
}
|
3022
|
+
return out;
|
3023
|
+
},
|
3024
|
+
sortBy: (array, key, descending = false, direction = descending ? -1 : 1) => array.sort ((a, b) => {
|
3025
|
+
if (a[key] < b[key]) {
|
3026
|
+
return -direction;
|
3027
|
+
} else if (a[key] > b[key]) {
|
3028
|
+
return direction;
|
3029
|
+
} else {
|
3030
|
+
return 0;
|
3031
|
+
}
|
3032
|
+
}),
|
3033
|
+
sortBy2: (array, key1, key2, descending = false, direction = descending ? -1 : 1) => array.sort ((a, b) => {
|
3034
|
+
if (a[key1] < b[key1]) {
|
3035
|
+
return -direction;
|
3036
|
+
} else if (a[key1] > b[key1]) {
|
3037
|
+
return direction;
|
3038
|
+
} else {
|
3039
|
+
if (a[key2] < b[key2]) {
|
3040
|
+
return -direction;
|
3041
|
+
} else if (a[key2] > b[key2]) {
|
3042
|
+
return direction;
|
3043
|
+
} else {
|
3044
|
+
return 0;
|
3045
|
+
}
|
3046
|
+
}
|
3047
|
+
}),
|
3048
|
+
flatten: function flatten (x, out = []) {
|
3049
|
+
|
3050
|
+
for (const v of x) {
|
3051
|
+
if (this.isArray (v)) {
|
3052
|
+
this.flatten (v, out);
|
3053
|
+
} else {
|
3054
|
+
out.push (v);
|
3055
|
+
}
|
3056
|
+
}
|
3057
|
+
|
3058
|
+
return out;
|
3059
|
+
},
|
3060
|
+
pluck(x, k) { return this.values (x).filter ((v) => k in v).map ((v) => v[k]);},
|
3061
|
+
omit (x, ...args) {
|
3062
|
+
if (!Array.isArray (x)) {
|
3063
|
+
const out = this.clone (x);
|
3064
|
+
for (const k of args) {
|
3065
|
+
if (this.isArray (k)) { // omit (x, ['a', 'b'])
|
3066
|
+
for (const kk of k) {
|
3067
|
+
delete out[kk];
|
3068
|
+
}
|
3069
|
+
} else {
|
3070
|
+
delete out[k]; // omit (x, 'a', 'b')
|
3071
|
+
}
|
3072
|
+
}
|
3073
|
+
return out;
|
3074
|
+
}
|
3075
|
+
return x;
|
3076
|
+
},
|
3077
|
+
sum (...xs) {
|
3078
|
+
const ns = xs.filter (isNumber); // leave only numbers
|
3079
|
+
return (ns.length > 0) ? ns.reduce ((a, b) => a + b, 0) : undefined;
|
3080
|
+
},
|
3081
|
+
deepExtend: function deepExtend (...xs) {
|
3082
|
+
let out = undefined;
|
3083
|
+
for (const x of xs) {
|
3084
|
+
if (this.isDictionary (x)) {
|
3085
|
+
if (!this.isDictionary (out)) {
|
3086
|
+
out = {};
|
3087
|
+
}
|
3088
|
+
for (const k in x) { // eslint-disable-line guard-for-in
|
3089
|
+
out[k] = this.deepExtend (out[k], x[k]);
|
3090
|
+
}
|
3091
|
+
} else {
|
3092
|
+
out = x;
|
3093
|
+
}
|
3094
|
+
}
|
3095
|
+
return out;
|
3096
|
+
},
|
3097
|
+
// type
|
3098
|
+
isNumber: Number.isFinite,
|
3099
|
+
isInteger: Number.isInteger,
|
3100
|
+
isArray: Array.isArray,
|
3101
|
+
hasProps: o => ((o !== undefined) && (o !== null)),
|
3102
|
+
isString: s => (typeof s === 'string'),
|
3103
|
+
isObject: o => ((o !== null) && (typeof o === 'object')),
|
3104
|
+
isRegExp: o => (o instanceof RegExp),
|
3105
|
+
isDictionary(o ){return (this.isObject (o) && (Object.getPrototypeOf (o) === Object.prototype) && !isArray (o) && !isRegExp (o));},
|
3106
|
+
isStringCoercible(x){ return ((this.hasProps (x) && x.toString) || this.isNumber (x));},
|
3107
|
+
prop (o, k) { return (this.isObject (o) && o[k] !== '' && o[k] !== null ? o[k] : undefined);},
|
3108
|
+
getValueFromKeysInArray(object, array) { return object[array.find (k => this.prop (object,k) !== undefined)];},
|
3109
|
+
asFloat (x) { return ((this.isNumber (x) || (this.isString (x) && x.length !== 0)) ? parseFloat (x) : NaN);}
|
3110
|
+
,
|
3111
|
+
asInteger(x) { return ((this.isNumber (x) || (this.isString (x) && x.length !== 0)) ? Math.trunc (Number(x)) : NaN);},
|
3112
|
+
// safeFloat:(o, k, $default, n = asFloat (prop (o, k))) => (this.isNumber (n) ? n : $default),
|
3113
|
+
// safeInteger: (o, k, $default, n = asInteger (prop (o, k))) => (this.isNumber (n) ? n : $default),
|
3114
|
+
// safeTimestamp: (o, k, $default, n = asFloat (prop (o, k))) => (isNumber (n) ? parseInt (n * 1000) : $default),
|
3115
|
+
// safeValue(o, k, $default, x = prop (o, k)) { return (hasProps (x) ? x : $default); },
|
3116
|
+
// safeString(o, k, $default, x = prop (o, k)){ return (this.isStringCoercible (x) ? String (x) : $default);},
|
3117
|
+
// safeStringLower(o, k, $default, x = prop (o, k)){ return (this.isStringCoercible (x) ? String (x).toLowerCase () : $default ? $default.toLowerCase () : $default);},
|
3118
|
+
// safeStringUpper(o, k, $default, x = prop (o, k)){ return (this.isStringCoercible (x) ? String (x).toUpperCase () : $default ? $default.toUpperCase () : $default);},
|
3119
|
+
|
3120
|
+
// misc
|
3121
|
+
parseTimeframe(timeframe){
|
3122
|
+
const amount = timeframe.slice (0, -1);
|
3123
|
+
const unit = timeframe.slice (-1);
|
3124
|
+
let scale = undefined;
|
3125
|
+
if (unit === 'y') { scale = 60 * 60 * 24 * 365; }
|
3126
|
+
else if (unit === 'M') { scale = 60 * 60 * 24 * 30; }
|
3127
|
+
else if (unit === 'w') { scale = 60 * 60 * 24 * 7; }
|
3128
|
+
else if (unit === 'd') { scale = 60 * 60 * 24; }
|
3129
|
+
else if (unit === 'h') { scale = 60 * 60;}
|
3130
|
+
else if (unit === 'm') { scale = 60; }
|
3131
|
+
else if (unit === 's') { scale = 1; }
|
3132
|
+
else { throw new NotSupported ('timeframe unit ' + unit + ' is not supported'); }
|
3133
|
+
return amount * scale;
|
3134
|
+
},
|
3135
|
+
roundTimeframe(timeframe, timestamp, direction = ROUND_DOWN) {
|
3136
|
+
const ms = this.parseTimeframe (timeframe) * 1000
|
3137
|
+
// Get offset based on timeframe in milliseconds
|
3138
|
+
const offset = timestamp % ms
|
3139
|
+
return timestamp - offset + ((direction === ROUND_UP) ? ms : 0);
|
3140
|
+
},
|
3141
|
+
json:(data, params = undefined) => JSON.stringify (data),
|
3142
|
+
isJsonEncodedObject: object => (
|
3143
|
+
(typeof object === 'string') &&
|
3144
|
+
(object.length >= 2) &&
|
3145
|
+
((object[0] === '{') || (object[0] === '['))
|
3146
|
+
),
|
3147
|
+
// number
|
3148
|
+
precisionFromString (string) {
|
3149
|
+
const split = string.replace (/0+$/g, '').split ('.')
|
3150
|
+
return (split.length > 1) ? (split[1].length) : 0
|
3151
|
+
},
|
3152
|
+
numberToString (x) { // avoids scientific notation for too large and too small numbers
|
3153
|
+
if (x === undefined) return undefined; if (typeof x !== 'number') return x.toString (); const s = x.toString (); if (Math.abs (x) < 1.0) { const n_e = s.split ('e-'); const n = n_e[0].replace ('.', ''); const e = parseInt (n_e[1]); const neg = (s[0] === '-'); if (e) { x = (neg ? '-' : '') + '0.' + (new Array (e)).join ('0') + n.substring (neg); return x; } } else { const parts = s.split ('e'); if (parts[1]) { let e = parseInt (parts[1]); const m = parts[0].split ('.'); let part = ''; if (m[1]) { e -= m[1].length; part = m[1]; } return m[0] + part + (new Array (e + 1)).join ('0'); } } return s;
|
3154
|
+
},
|
3155
|
+
// platform
|
3156
|
+
isBrowser: typeof window !== 'undefined',
|
3157
|
+
isElectron: typeof process !== 'undefined' && typeof process.versions !== 'undefined' && typeof process.versions.electron !== 'undefined',
|
3158
|
+
isWebWorker: typeof WorkerGlobalScope !== 'undefined' && (self instanceof WorkerGlobalScope),
|
3159
|
+
isWindows: typeof process !== 'undefined' && process.platform === "win32",
|
3160
|
+
isNode: !(this.isBrowser || this.isWebWorker),
|
3161
|
+
defaultFetch: fetch,
|
3162
|
+
//string
|
3163
|
+
uuid: a => a ? (a ^ Math.random () * 16 >> a / 4).toString (16) : ([1e7]+-1e3+-4e3+-8e3+-1e11).replace (/[018]/g, uuid),
|
3164
|
+
capitalize: s => s.length ? (s.charAt (0).toUpperCase () + s.slice (1)) : s,
|
3165
|
+
strip: s => s.replace(/^\s+|\s+$/g, ''),
|
3166
|
+
// time
|
3167
|
+
now: Date.now,
|
3168
|
+
milliseconds: Date.now, // milliseconds(){ return (new Date().getTime()); },
|
3169
|
+
seconds: () => Math.floor (Date.now () / 1000),
|
3170
|
+
// endregion: ####### from CCXT ##########
|
3171
|
+
|
3172
|
+
|
3173
|
+
|
2948
3174
|
};
|
2949
3175
|
|
2950
3176
|
|
package/package.json
CHANGED