pinets 0.1.0 → 0.1.31
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/README.md +9 -1
- package/dist/pinets.dev.browser.js +10612 -0
- package/dist/pinets.dev.cjs +730 -273
- package/dist/pinets.dev.cjs.map +1 -1
- package/dist/pinets.dev.es.js +784 -172
- package/dist/pinets.dev.es.js.map +1 -1
- package/dist/types/Context.class.d.ts +24 -2
- package/dist/types/PineTS.class.d.ts +1 -1
- package/dist/types/marketData/Binance/BinanceProvider.class.d.ts +3 -0
- package/dist/types/namespaces/Core.d.ts +3 -0
- package/dist/types/namespaces/PineArray.d.ts +62 -0
- package/dist/types/namespaces/PineColor.d.ts +0 -0
- package/dist/types/namespaces/PineMath.d.ts +20 -19
- package/dist/types/namespaces/PineRequest.d.ts +2 -1
- package/dist/types/namespaces/TechnicalAnalysis.d.ts +1 -1
- package/dist/types/transpiler/ScopeManager.class.d.ts +2 -0
- package/package.json +48 -48
package/dist/pinets.dev.es.js
CHANGED
|
@@ -1,24 +1,42 @@
|
|
|
1
|
+
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (C) 2025 Alaa-eddine KADDOURI
|
|
4
|
+
*
|
|
5
|
+
* This program is free software: you can redistribute it and/or modify
|
|
6
|
+
* it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
* (at your option) any later version.
|
|
9
|
+
*
|
|
10
|
+
* This program is distributed in the hope that it will be useful,
|
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
* GNU Affero General Public License for more details.
|
|
14
|
+
*
|
|
15
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
*/
|
|
1
18
|
import * as acorn from 'acorn';
|
|
2
19
|
import * as walk from 'acorn-walk';
|
|
3
20
|
import * as astring from 'astring';
|
|
4
21
|
|
|
5
|
-
var __defProp$
|
|
6
|
-
var __defNormalProp$
|
|
7
|
-
var __publicField$
|
|
22
|
+
var __defProp$7 = Object.defineProperty;
|
|
23
|
+
var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
24
|
+
var __publicField$7 = (obj, key, value) => __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
8
25
|
class ScopeManager {
|
|
9
26
|
constructor() {
|
|
10
|
-
__publicField$
|
|
11
|
-
__publicField$
|
|
12
|
-
__publicField$
|
|
13
|
-
__publicField$
|
|
14
|
-
__publicField$
|
|
15
|
-
__publicField$
|
|
16
|
-
__publicField$
|
|
17
|
-
__publicField$
|
|
18
|
-
__publicField$
|
|
27
|
+
__publicField$7(this, "scopes", []);
|
|
28
|
+
__publicField$7(this, "scopeTypes", []);
|
|
29
|
+
__publicField$7(this, "scopeCounts", /* @__PURE__ */ new Map());
|
|
30
|
+
__publicField$7(this, "contextBoundVars", /* @__PURE__ */ new Set());
|
|
31
|
+
__publicField$7(this, "arrayPatternElements", /* @__PURE__ */ new Set());
|
|
32
|
+
__publicField$7(this, "rootParams", /* @__PURE__ */ new Set());
|
|
33
|
+
__publicField$7(this, "varKinds", /* @__PURE__ */ new Map());
|
|
34
|
+
__publicField$7(this, "loopVars", /* @__PURE__ */ new Set());
|
|
35
|
+
__publicField$7(this, "loopVarNames", /* @__PURE__ */ new Map());
|
|
19
36
|
// Map original names to transformed names
|
|
20
|
-
__publicField$
|
|
21
|
-
__publicField$
|
|
37
|
+
__publicField$7(this, "paramIdCounter", 0);
|
|
38
|
+
__publicField$7(this, "cacheIdCounter", 0);
|
|
39
|
+
__publicField$7(this, "tempVarCounter", 0);
|
|
22
40
|
this.pushScope("glb");
|
|
23
41
|
}
|
|
24
42
|
get nextParamIdArg() {
|
|
@@ -27,6 +45,12 @@ class ScopeManager {
|
|
|
27
45
|
name: `'p${this.paramIdCounter++}'`
|
|
28
46
|
};
|
|
29
47
|
}
|
|
48
|
+
get nextCacheIdArg() {
|
|
49
|
+
return {
|
|
50
|
+
type: "Identifier",
|
|
51
|
+
name: `'cache_${this.cacheIdCounter++}'`
|
|
52
|
+
};
|
|
53
|
+
}
|
|
30
54
|
pushScope(type) {
|
|
31
55
|
this.scopes.push(/* @__PURE__ */ new Map());
|
|
32
56
|
this.scopeTypes.push(type);
|
|
@@ -204,6 +228,9 @@ function transformMemberExpression(memberNode, originalParamName, scopeManager)
|
|
|
204
228
|
}
|
|
205
229
|
function transformVariableDeclaration(varNode, scopeManager) {
|
|
206
230
|
varNode.declarations.forEach((decl) => {
|
|
231
|
+
if (decl.init.name == "na") {
|
|
232
|
+
decl.init.name = "NaN";
|
|
233
|
+
}
|
|
207
234
|
const isContextProperty = decl.init && decl.init.type === "MemberExpression" && decl.init.object && (decl.init.object.name === "context" || decl.init.object.name === CONTEXT_NAME || decl.init.object.name === "context2");
|
|
208
235
|
const isSubContextProperty = decl.init && decl.init.type === "MemberExpression" && decl.init.object?.object && (decl.init.object.object.name === "context" || decl.init.object.object.name === CONTEXT_NAME || decl.init.object.object.name === "context2");
|
|
209
236
|
const isArrowFunction = decl.init && decl.init.type === "ArrowFunctionExpression";
|
|
@@ -366,7 +393,28 @@ function transformVariableDeclaration(varNode, scopeManager) {
|
|
|
366
393
|
}
|
|
367
394
|
};
|
|
368
395
|
if (isArrayPatternVar) {
|
|
369
|
-
assignmentExpr.expression.right.object.property.name +=
|
|
396
|
+
assignmentExpr.expression.right.object.property.name += `?.[0][${decl.init.property.value}]`;
|
|
397
|
+
const obj = assignmentExpr.expression.right.object;
|
|
398
|
+
assignmentExpr.expression.right = {
|
|
399
|
+
type: "CallExpression",
|
|
400
|
+
callee: {
|
|
401
|
+
type: "MemberExpression",
|
|
402
|
+
object: {
|
|
403
|
+
type: "Identifier",
|
|
404
|
+
name: CONTEXT_NAME
|
|
405
|
+
},
|
|
406
|
+
property: {
|
|
407
|
+
type: "Identifier",
|
|
408
|
+
name: "init"
|
|
409
|
+
},
|
|
410
|
+
computed: false
|
|
411
|
+
},
|
|
412
|
+
arguments: [
|
|
413
|
+
targetVarRef,
|
|
414
|
+
obj
|
|
415
|
+
/*, decl.init.property.value*/
|
|
416
|
+
]
|
|
417
|
+
};
|
|
370
418
|
}
|
|
371
419
|
if (isArrowFunction) {
|
|
372
420
|
scopeManager.pushScope("fn");
|
|
@@ -519,14 +567,22 @@ function transformAssignmentExpression(node, scopeManager) {
|
|
|
519
567
|
{ parent: node.right, inNamespaceCall: false },
|
|
520
568
|
{
|
|
521
569
|
Identifier(node2, state, c) {
|
|
570
|
+
if (node2.name == "na") {
|
|
571
|
+
node2.name = "NaN";
|
|
572
|
+
}
|
|
522
573
|
node2.parent = state.parent;
|
|
523
574
|
transformIdentifier(node2, scopeManager);
|
|
524
575
|
const isBinaryOperation = node2.parent && node2.parent.type === "BinaryExpression";
|
|
525
576
|
const isConditional = node2.parent && node2.parent.type === "ConditionalExpression";
|
|
526
|
-
|
|
577
|
+
const isContextBound = scopeManager.isContextBound(node2.name) && !scopeManager.isRootParam(node2.name);
|
|
578
|
+
const hasArrayAccess = node2.parent && node2.parent.type === "MemberExpression" && node2.parent.computed && node2.parent.object === node2;
|
|
579
|
+
const isParamCall = node2.parent && node2.parent._isParamCall;
|
|
580
|
+
const isMemberExpression = node2.parent && node2.parent.type === "MemberExpression";
|
|
581
|
+
const isReserved = node2.name === "NaN";
|
|
582
|
+
if (isContextBound || isConditional || isBinaryOperation) {
|
|
527
583
|
if (node2.type === "MemberExpression") {
|
|
528
584
|
transformArrayIndex(node2, scopeManager);
|
|
529
|
-
} else if (node2.type === "Identifier") {
|
|
585
|
+
} else if (node2.type === "Identifier" && !isMemberExpression && !hasArrayAccess && !isParamCall && !isReserved) {
|
|
530
586
|
addArrayAccess(node2);
|
|
531
587
|
}
|
|
532
588
|
}
|
|
@@ -708,6 +764,10 @@ function transformReturnStatement(node, scopeManager) {
|
|
|
708
764
|
}
|
|
709
765
|
function transformIdentifierForParam(node, scopeManager) {
|
|
710
766
|
if (node.type === "Identifier") {
|
|
767
|
+
if (node.name === "na") {
|
|
768
|
+
node.name = "NaN";
|
|
769
|
+
return node;
|
|
770
|
+
}
|
|
711
771
|
if (scopeManager.isLoopVariable(node.name)) {
|
|
712
772
|
return node;
|
|
713
773
|
}
|
|
@@ -761,40 +821,58 @@ function transformIdentifierForParam(node, scopeManager) {
|
|
|
761
821
|
}
|
|
762
822
|
return node;
|
|
763
823
|
}
|
|
824
|
+
function getParamFromUnaryExpression(node, scopeManager, namespace) {
|
|
825
|
+
const transformedArgument = transformOperand(node.argument, scopeManager, namespace);
|
|
826
|
+
const unaryExpr = {
|
|
827
|
+
type: "UnaryExpression",
|
|
828
|
+
operator: node.operator,
|
|
829
|
+
prefix: node.prefix,
|
|
830
|
+
argument: transformedArgument,
|
|
831
|
+
start: node.start,
|
|
832
|
+
end: node.end
|
|
833
|
+
};
|
|
834
|
+
return unaryExpr;
|
|
835
|
+
}
|
|
764
836
|
function transformOperand(node, scopeManager, namespace = "") {
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
if (node.type === "MemberExpression") {
|
|
769
|
-
const transformedObject = node.object.type === "Identifier" ? transformIdentifierForParam(node.object, scopeManager) : node.object;
|
|
770
|
-
return {
|
|
771
|
-
type: "MemberExpression",
|
|
772
|
-
object: transformedObject,
|
|
773
|
-
property: node.property,
|
|
774
|
-
computed: node.computed
|
|
775
|
-
};
|
|
776
|
-
} else if (node.type === "Identifier") {
|
|
777
|
-
if (scopeManager.isLoopVariable(node.name)) {
|
|
778
|
-
return node;
|
|
837
|
+
switch (node.type) {
|
|
838
|
+
case "BinaryExpression": {
|
|
839
|
+
return getParamFromBinaryExpression(node, scopeManager, namespace);
|
|
779
840
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
return
|
|
841
|
+
case "MemberExpression": {
|
|
842
|
+
const transformedObject = node.object.type === "Identifier" ? transformIdentifierForParam(node.object, scopeManager) : node.object;
|
|
843
|
+
return {
|
|
844
|
+
type: "MemberExpression",
|
|
845
|
+
object: transformedObject,
|
|
846
|
+
property: node.property,
|
|
847
|
+
computed: node.computed
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
case "Identifier": {
|
|
851
|
+
if (scopeManager.isLoopVariable(node.name)) {
|
|
852
|
+
return node;
|
|
853
|
+
}
|
|
854
|
+
const isMemberExprProperty = node.parent && node.parent.type === "MemberExpression" && node.parent.property === node;
|
|
855
|
+
if (isMemberExprProperty) {
|
|
856
|
+
return node;
|
|
857
|
+
}
|
|
858
|
+
const transformedObject = transformIdentifierForParam(node, scopeManager);
|
|
859
|
+
return {
|
|
860
|
+
type: "MemberExpression",
|
|
861
|
+
object: transformedObject,
|
|
862
|
+
property: {
|
|
863
|
+
type: "Literal",
|
|
864
|
+
value: 0
|
|
865
|
+
},
|
|
866
|
+
computed: true
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
case "UnaryExpression": {
|
|
870
|
+
return getParamFromUnaryExpression(node, scopeManager, namespace);
|
|
783
871
|
}
|
|
784
|
-
const transformedObject = transformIdentifierForParam(node, scopeManager);
|
|
785
|
-
return {
|
|
786
|
-
type: "MemberExpression",
|
|
787
|
-
object: transformedObject,
|
|
788
|
-
property: {
|
|
789
|
-
type: "Literal",
|
|
790
|
-
value: 0
|
|
791
|
-
},
|
|
792
|
-
computed: true
|
|
793
|
-
};
|
|
794
872
|
}
|
|
795
873
|
return node;
|
|
796
874
|
}
|
|
797
|
-
function
|
|
875
|
+
function getParamFromBinaryExpression(node, scopeManager, namespace) {
|
|
798
876
|
const transformedLeft = transformOperand(node.left, scopeManager, namespace);
|
|
799
877
|
const transformedRight = transformOperand(node.right, scopeManager, namespace);
|
|
800
878
|
const binaryExpr = {
|
|
@@ -815,28 +893,89 @@ function transformBinaryExpression(node, scopeManager, namespace) {
|
|
|
815
893
|
transformMemberExpression(node2, "", scopeManager);
|
|
816
894
|
}
|
|
817
895
|
});
|
|
896
|
+
return binaryExpr;
|
|
897
|
+
}
|
|
898
|
+
function getParamFromLogicalExpression(node, scopeManager, namespace) {
|
|
899
|
+
const transformedLeft = transformOperand(node.left, scopeManager, namespace);
|
|
900
|
+
const transformedRight = transformOperand(node.right, scopeManager, namespace);
|
|
901
|
+
const logicalExpr = {
|
|
902
|
+
type: "LogicalExpression",
|
|
903
|
+
operator: node.operator,
|
|
904
|
+
left: transformedLeft,
|
|
905
|
+
right: transformedRight,
|
|
906
|
+
start: node.start,
|
|
907
|
+
end: node.end
|
|
908
|
+
};
|
|
909
|
+
walk.recursive(logicalExpr, scopeManager, {
|
|
910
|
+
CallExpression(node2, scopeManager2) {
|
|
911
|
+
if (!node2._transformed) {
|
|
912
|
+
transformCallExpression(node2, scopeManager2);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
});
|
|
916
|
+
return logicalExpr;
|
|
917
|
+
}
|
|
918
|
+
function getParamFromConditionalExpression(node, scopeManager, namespace) {
|
|
919
|
+
walk.recursive(
|
|
920
|
+
node,
|
|
921
|
+
{ parent: node, inNamespaceCall: false },
|
|
922
|
+
{
|
|
923
|
+
Identifier(node2, state, c) {
|
|
924
|
+
if (node2.name == "NaN") return;
|
|
925
|
+
if (node2.name == "na") {
|
|
926
|
+
node2.name = "NaN";
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
node2.parent = state.parent;
|
|
930
|
+
transformIdentifier(node2, scopeManager);
|
|
931
|
+
const isBinaryOperation = node2.parent && node2.parent.type === "BinaryExpression";
|
|
932
|
+
const isConditional = node2.parent && node2.parent.type === "ConditionalExpression";
|
|
933
|
+
if (isConditional || isBinaryOperation) {
|
|
934
|
+
if (node2.type === "MemberExpression") {
|
|
935
|
+
transformArrayIndex(node2, scopeManager);
|
|
936
|
+
} else if (node2.type === "Identifier") {
|
|
937
|
+
addArrayAccess(node2);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
},
|
|
941
|
+
MemberExpression(node2, state, c) {
|
|
942
|
+
transformArrayIndex(node2, scopeManager);
|
|
943
|
+
if (node2.object) {
|
|
944
|
+
c(node2.object, { parent: node2, inNamespaceCall: state.inNamespaceCall });
|
|
945
|
+
}
|
|
946
|
+
},
|
|
947
|
+
CallExpression(node2, state, c) {
|
|
948
|
+
const isNamespaceCall = node2.callee && node2.callee.type === "MemberExpression" && node2.callee.object && node2.callee.object.type === "Identifier" && scopeManager.isContextBound(node2.callee.object.name);
|
|
949
|
+
transformCallExpression(node2, scopeManager);
|
|
950
|
+
node2.arguments.forEach((arg) => c(arg, { parent: node2, inNamespaceCall: isNamespaceCall || state.inNamespaceCall }));
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
);
|
|
818
954
|
return {
|
|
819
955
|
type: "CallExpression",
|
|
820
956
|
callee: {
|
|
821
957
|
type: "MemberExpression",
|
|
822
|
-
object: {
|
|
823
|
-
|
|
824
|
-
name: namespace
|
|
825
|
-
},
|
|
826
|
-
property: {
|
|
827
|
-
type: "Identifier",
|
|
828
|
-
name: "param"
|
|
829
|
-
},
|
|
830
|
-
computed: false
|
|
958
|
+
object: { type: "Identifier", name: namespace },
|
|
959
|
+
property: { type: "Identifier", name: "param" }
|
|
831
960
|
},
|
|
832
|
-
arguments: [
|
|
961
|
+
arguments: [node, UNDEFINED_ARG, scopeManager.nextParamIdArg],
|
|
833
962
|
_transformed: true,
|
|
834
963
|
_isParamCall: true
|
|
835
964
|
};
|
|
836
965
|
}
|
|
837
966
|
function transformFunctionArgument(arg, namespace, scopeManager) {
|
|
838
|
-
|
|
839
|
-
|
|
967
|
+
switch (arg?.type) {
|
|
968
|
+
case "BinaryExpression":
|
|
969
|
+
arg = getParamFromBinaryExpression(arg, scopeManager, namespace);
|
|
970
|
+
break;
|
|
971
|
+
case "LogicalExpression":
|
|
972
|
+
arg = getParamFromLogicalExpression(arg, scopeManager, namespace);
|
|
973
|
+
break;
|
|
974
|
+
case "ConditionalExpression":
|
|
975
|
+
return getParamFromConditionalExpression(arg, scopeManager, namespace);
|
|
976
|
+
case "UnaryExpression":
|
|
977
|
+
arg = getParamFromUnaryExpression(arg, scopeManager, namespace);
|
|
978
|
+
break;
|
|
840
979
|
}
|
|
841
980
|
const isArrayAccess = arg.type === "MemberExpression" && arg.computed && arg.property;
|
|
842
981
|
if (isArrayAccess) {
|
|
@@ -901,6 +1040,10 @@ function transformFunctionArgument(arg, namespace, scopeManager) {
|
|
|
901
1040
|
});
|
|
902
1041
|
}
|
|
903
1042
|
if (arg.type === "Identifier") {
|
|
1043
|
+
if (arg.name === "na") {
|
|
1044
|
+
arg.name = "NaN";
|
|
1045
|
+
return arg;
|
|
1046
|
+
}
|
|
904
1047
|
if (scopeManager.isContextBound(arg.name) && !scopeManager.isRootParam(arg.name)) {
|
|
905
1048
|
return {
|
|
906
1049
|
type: "CallExpression",
|
|
@@ -944,18 +1087,18 @@ function transformFunctionArgument(arg, namespace, scopeManager) {
|
|
|
944
1087
|
_isParamCall: true
|
|
945
1088
|
};
|
|
946
1089
|
}
|
|
947
|
-
function transformCallExpression(node, scopeManager) {
|
|
1090
|
+
function transformCallExpression(node, scopeManager, namespace) {
|
|
948
1091
|
if (node._transformed) {
|
|
949
1092
|
return;
|
|
950
1093
|
}
|
|
951
1094
|
const isNamespaceCall = node.callee && node.callee.type === "MemberExpression" && node.callee.object && node.callee.object.type === "Identifier" && (scopeManager.isContextBound(node.callee.object.name) || node.callee.object.name === "math" || node.callee.object.name === "ta");
|
|
952
1095
|
if (isNamespaceCall) {
|
|
953
|
-
const
|
|
1096
|
+
const namespace2 = node.callee.object.name;
|
|
954
1097
|
node.arguments = node.arguments.map((arg) => {
|
|
955
1098
|
if (arg._isParamCall) {
|
|
956
1099
|
return arg;
|
|
957
1100
|
}
|
|
958
|
-
return transformFunctionArgument(arg,
|
|
1101
|
+
return transformFunctionArgument(arg, namespace2, scopeManager);
|
|
959
1102
|
});
|
|
960
1103
|
node._transformed = true;
|
|
961
1104
|
} else if (node.callee && node.callee.type === "Identifier") {
|
|
@@ -969,13 +1112,29 @@ function transformCallExpression(node, scopeManager) {
|
|
|
969
1112
|
}
|
|
970
1113
|
node.arguments.forEach((arg) => {
|
|
971
1114
|
walk.recursive(arg, scopeManager, {
|
|
972
|
-
|
|
1115
|
+
Identifier(node2, state, c) {
|
|
1116
|
+
node2.parent = state.parent;
|
|
1117
|
+
transformIdentifier(node2, scopeManager);
|
|
1118
|
+
const isBinaryOperation = node2.parent && node2.parent.type === "BinaryExpression";
|
|
1119
|
+
const isConditional = node2.parent && node2.parent.type === "ConditionalExpression";
|
|
1120
|
+
if (isConditional || isBinaryOperation) {
|
|
1121
|
+
if (node2.type === "MemberExpression") {
|
|
1122
|
+
transformArrayIndex(node2, scopeManager);
|
|
1123
|
+
} else if (node2.type === "Identifier") {
|
|
1124
|
+
addArrayAccess(node2);
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
},
|
|
1128
|
+
CallExpression(node2, state, c) {
|
|
973
1129
|
if (!node2._transformed) {
|
|
974
1130
|
transformCallExpression(node2, state);
|
|
975
1131
|
}
|
|
976
1132
|
},
|
|
977
|
-
MemberExpression(node2) {
|
|
1133
|
+
MemberExpression(node2, state, c) {
|
|
978
1134
|
transformMemberExpression(node2, "", scopeManager);
|
|
1135
|
+
if (node2.object) {
|
|
1136
|
+
c(node2.object, { parent: node2, inNamespaceCall: state.inNamespaceCall });
|
|
1137
|
+
}
|
|
979
1138
|
}
|
|
980
1139
|
});
|
|
981
1140
|
});
|
|
@@ -1336,9 +1495,9 @@ function transpile(fn) {
|
|
|
1336
1495
|
return _wraperFunction(this);
|
|
1337
1496
|
}
|
|
1338
1497
|
|
|
1339
|
-
var __defProp$
|
|
1340
|
-
var __defNormalProp$
|
|
1341
|
-
var __publicField$
|
|
1498
|
+
var __defProp$6 = Object.defineProperty;
|
|
1499
|
+
var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1500
|
+
var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1342
1501
|
class PineTS {
|
|
1343
1502
|
constructor(source, tickerId, timeframe, limit, sDate, eDate) {
|
|
1344
1503
|
this.source = source;
|
|
@@ -1347,25 +1506,25 @@ class PineTS {
|
|
|
1347
1506
|
this.limit = limit;
|
|
1348
1507
|
this.sDate = sDate;
|
|
1349
1508
|
this.eDate = eDate;
|
|
1350
|
-
__publicField$
|
|
1509
|
+
__publicField$6(this, "data", []);
|
|
1351
1510
|
//#region [Pine Script built-in variables]
|
|
1352
|
-
__publicField$
|
|
1353
|
-
__publicField$
|
|
1354
|
-
__publicField$
|
|
1355
|
-
__publicField$
|
|
1356
|
-
__publicField$
|
|
1357
|
-
__publicField$
|
|
1358
|
-
__publicField$
|
|
1359
|
-
__publicField$
|
|
1360
|
-
__publicField$
|
|
1361
|
-
__publicField$
|
|
1511
|
+
__publicField$6(this, "open", []);
|
|
1512
|
+
__publicField$6(this, "high", []);
|
|
1513
|
+
__publicField$6(this, "low", []);
|
|
1514
|
+
__publicField$6(this, "close", []);
|
|
1515
|
+
__publicField$6(this, "volume", []);
|
|
1516
|
+
__publicField$6(this, "hl2", []);
|
|
1517
|
+
__publicField$6(this, "hlc3", []);
|
|
1518
|
+
__publicField$6(this, "ohlc4", []);
|
|
1519
|
+
__publicField$6(this, "openTime", []);
|
|
1520
|
+
__publicField$6(this, "closeTime", []);
|
|
1362
1521
|
//#endregion
|
|
1363
1522
|
//#region run context
|
|
1364
|
-
__publicField$
|
|
1523
|
+
__publicField$6(this, "_periods");
|
|
1365
1524
|
//#endregion
|
|
1366
1525
|
//public fn: Function;
|
|
1367
|
-
__publicField$
|
|
1368
|
-
__publicField$
|
|
1526
|
+
__publicField$6(this, "_readyPromise", null);
|
|
1527
|
+
__publicField$6(this, "_ready", false);
|
|
1369
1528
|
this._readyPromise = new Promise((resolve) => {
|
|
1370
1529
|
this.loadMarketData(source, tickerId, timeframe, limit, sDate, eDate).then((data) => {
|
|
1371
1530
|
const marketData = data.reverse();
|
|
@@ -1411,13 +1570,22 @@ class PineTS {
|
|
|
1411
1570
|
if (!this._readyPromise) throw new Error("PineTS is not ready");
|
|
1412
1571
|
return this._readyPromise;
|
|
1413
1572
|
}
|
|
1414
|
-
async run(
|
|
1573
|
+
async run(pineTSCode, n, useTACache) {
|
|
1415
1574
|
await this.ready();
|
|
1416
1575
|
if (!n) n = this._periods;
|
|
1417
|
-
const context = new Context(
|
|
1418
|
-
|
|
1576
|
+
const context = new Context({
|
|
1577
|
+
marketData: this.data,
|
|
1578
|
+
source: this.source,
|
|
1579
|
+
tickerId: this.tickerId,
|
|
1580
|
+
timeframe: this.timeframe,
|
|
1581
|
+
limit: this.limit,
|
|
1582
|
+
sDate: this.sDate,
|
|
1583
|
+
eDate: this.eDate
|
|
1584
|
+
});
|
|
1585
|
+
context.pineTSCode = pineTSCode;
|
|
1586
|
+
context.useTACache = useTACache;
|
|
1419
1587
|
const transformer = transpile.bind(this);
|
|
1420
|
-
let
|
|
1588
|
+
let transpiledFn = transformer(pineTSCode);
|
|
1421
1589
|
const contextVarNames = ["const", "var", "let", "params"];
|
|
1422
1590
|
for (let i = this._periods - n, idx = n - 1; i < this._periods; i++, idx--) {
|
|
1423
1591
|
context.idx = i;
|
|
@@ -1431,7 +1599,7 @@ class PineTS {
|
|
|
1431
1599
|
context.data.ohlc4 = this.ohlc4.slice(idx);
|
|
1432
1600
|
context.data.openTime = this.openTime.slice(idx);
|
|
1433
1601
|
context.data.closeTime = this.closeTime.slice(idx);
|
|
1434
|
-
const result = await
|
|
1602
|
+
const result = await transpiledFn(context);
|
|
1435
1603
|
if (typeof result === "object") {
|
|
1436
1604
|
if (typeof context.result !== "object") {
|
|
1437
1605
|
context.result = {};
|
|
@@ -1462,13 +1630,30 @@ class PineTS {
|
|
|
1462
1630
|
}
|
|
1463
1631
|
}
|
|
1464
1632
|
|
|
1465
|
-
var __defProp$
|
|
1466
|
-
var __defNormalProp$
|
|
1467
|
-
var __publicField$
|
|
1633
|
+
var __defProp$5 = Object.defineProperty;
|
|
1634
|
+
var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1635
|
+
var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1468
1636
|
class Core {
|
|
1469
1637
|
constructor(context) {
|
|
1470
1638
|
this.context = context;
|
|
1471
|
-
__publicField$
|
|
1639
|
+
__publicField$5(this, "color", {
|
|
1640
|
+
param: (source, index = 0) => {
|
|
1641
|
+
if (Array.isArray(source)) {
|
|
1642
|
+
return source[index];
|
|
1643
|
+
}
|
|
1644
|
+
return source;
|
|
1645
|
+
},
|
|
1646
|
+
rgb: (r, g, b, a) => a ? `rgba(${r}, ${g}, ${b}, ${a})` : `rgb(${r}, ${g}, ${b})`,
|
|
1647
|
+
new: (color, a) => {
|
|
1648
|
+
if (color && color.startsWith("#")) {
|
|
1649
|
+
const hex = color.slice(1);
|
|
1650
|
+
const r = parseInt(hex.slice(0, 2), 16);
|
|
1651
|
+
const g = parseInt(hex.slice(2, 4), 16);
|
|
1652
|
+
const b = parseInt(hex.slice(4, 6), 16);
|
|
1653
|
+
return a ? `rgba(${r}, ${g}, ${b}, ${a})` : `rgb(${r}, ${g}, ${b})`;
|
|
1654
|
+
}
|
|
1655
|
+
return a ? `rgba(${color}, ${a})` : color;
|
|
1656
|
+
},
|
|
1472
1657
|
white: "white",
|
|
1473
1658
|
lime: "lime",
|
|
1474
1659
|
green: "green",
|
|
@@ -1500,7 +1685,7 @@ class Core {
|
|
|
1500
1685
|
this.context.plots[title].data.push({
|
|
1501
1686
|
time: this.context.marketData[this.context.marketData.length - this.context.idx - 1].openTime,
|
|
1502
1687
|
value: series[0],
|
|
1503
|
-
options: this.extractPlotOptions(options)
|
|
1688
|
+
options: { ...this.extractPlotOptions(options), style: "char" }
|
|
1504
1689
|
});
|
|
1505
1690
|
}
|
|
1506
1691
|
plot(series, title, options) {
|
|
@@ -1517,11 +1702,9 @@ class Core {
|
|
|
1517
1702
|
return Array.isArray(series) ? isNaN(series[0]) : isNaN(series);
|
|
1518
1703
|
}
|
|
1519
1704
|
nz(series, replacement = 0) {
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
return isNaN(series) ? replacement : series;
|
|
1524
|
-
}
|
|
1705
|
+
const val = Array.isArray(series) ? series[0] : series;
|
|
1706
|
+
const rep = Array.isArray(series) ? replacement[0] : replacement;
|
|
1707
|
+
return isNaN(val) ? rep : val;
|
|
1525
1708
|
}
|
|
1526
1709
|
}
|
|
1527
1710
|
|
|
@@ -1579,75 +1762,95 @@ class Input {
|
|
|
1579
1762
|
}
|
|
1580
1763
|
}
|
|
1581
1764
|
|
|
1582
|
-
var __defProp$
|
|
1583
|
-
var __defNormalProp$
|
|
1584
|
-
var __publicField$
|
|
1765
|
+
var __defProp$4 = Object.defineProperty;
|
|
1766
|
+
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1767
|
+
var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1585
1768
|
class PineMath {
|
|
1586
1769
|
constructor(context) {
|
|
1587
1770
|
this.context = context;
|
|
1588
|
-
__publicField$
|
|
1771
|
+
__publicField$4(this, "_cache", {});
|
|
1589
1772
|
}
|
|
1590
|
-
param(source, index
|
|
1773
|
+
param(source, index, name) {
|
|
1774
|
+
if (!this.context.params[name]) this.context.params[name] = [];
|
|
1591
1775
|
if (Array.isArray(source)) {
|
|
1592
|
-
|
|
1776
|
+
if (index) {
|
|
1777
|
+
this.context.params[name] = source.slice(index);
|
|
1778
|
+
this.context.params[name].length = source.length;
|
|
1779
|
+
return this.context.params[name];
|
|
1780
|
+
}
|
|
1781
|
+
this.context.params[name] = source.slice(0);
|
|
1782
|
+
return this.context.params[name];
|
|
1783
|
+
} else {
|
|
1784
|
+
this.context.params[name][0] = source;
|
|
1785
|
+
return this.context.params[name];
|
|
1593
1786
|
}
|
|
1594
|
-
return source;
|
|
1595
1787
|
}
|
|
1596
|
-
abs(
|
|
1597
|
-
return Math.abs(
|
|
1788
|
+
abs(source) {
|
|
1789
|
+
return Math.abs(source[0]);
|
|
1598
1790
|
}
|
|
1599
|
-
pow(
|
|
1600
|
-
return Math.pow(
|
|
1791
|
+
pow(source, power) {
|
|
1792
|
+
return Math.pow(source[0], power[0]);
|
|
1601
1793
|
}
|
|
1602
|
-
sqrt(
|
|
1603
|
-
return Math.sqrt(
|
|
1794
|
+
sqrt(source) {
|
|
1795
|
+
return Math.sqrt(source[0]);
|
|
1604
1796
|
}
|
|
1605
|
-
log(
|
|
1606
|
-
return Math.log(
|
|
1797
|
+
log(source) {
|
|
1798
|
+
return Math.log(source[0]);
|
|
1607
1799
|
}
|
|
1608
|
-
ln(
|
|
1609
|
-
return Math.log(
|
|
1800
|
+
ln(source) {
|
|
1801
|
+
return Math.log(source[0]);
|
|
1610
1802
|
}
|
|
1611
|
-
exp(
|
|
1612
|
-
return Math.exp(
|
|
1803
|
+
exp(source) {
|
|
1804
|
+
return Math.exp(source[0]);
|
|
1613
1805
|
}
|
|
1614
|
-
floor(
|
|
1615
|
-
return Math.floor(
|
|
1806
|
+
floor(source) {
|
|
1807
|
+
return Math.floor(source[0]);
|
|
1616
1808
|
}
|
|
1617
|
-
ceil(
|
|
1618
|
-
return Math.ceil(
|
|
1809
|
+
ceil(source) {
|
|
1810
|
+
return Math.ceil(source[0]);
|
|
1619
1811
|
}
|
|
1620
|
-
round(
|
|
1621
|
-
return Math.round(
|
|
1812
|
+
round(source) {
|
|
1813
|
+
return Math.round(source[0]);
|
|
1622
1814
|
}
|
|
1623
1815
|
random() {
|
|
1624
1816
|
return Math.random();
|
|
1625
1817
|
}
|
|
1626
|
-
max(...
|
|
1627
|
-
|
|
1818
|
+
max(...source) {
|
|
1819
|
+
const arg = source.map((e) => Array.isArray(e) ? e[0] : e);
|
|
1820
|
+
return Math.max(...arg);
|
|
1821
|
+
}
|
|
1822
|
+
min(...source) {
|
|
1823
|
+
const arg = source.map((e) => Array.isArray(e) ? e[0] : e);
|
|
1824
|
+
return Math.min(...arg);
|
|
1628
1825
|
}
|
|
1629
|
-
|
|
1630
|
-
|
|
1826
|
+
//sum of last n values
|
|
1827
|
+
sum(source, length) {
|
|
1828
|
+
const len = Array.isArray(length) ? length[0] : length;
|
|
1829
|
+
if (Array.isArray(source)) {
|
|
1830
|
+
return source.slice(0, len).reduce((a, b) => a + b, 0);
|
|
1831
|
+
}
|
|
1832
|
+
return source;
|
|
1631
1833
|
}
|
|
1632
|
-
sin(
|
|
1633
|
-
return Math.sin(
|
|
1834
|
+
sin(source) {
|
|
1835
|
+
return Math.sin(source[0]);
|
|
1634
1836
|
}
|
|
1635
|
-
cos(
|
|
1636
|
-
return Math.cos(
|
|
1837
|
+
cos(source) {
|
|
1838
|
+
return Math.cos(source[0]);
|
|
1637
1839
|
}
|
|
1638
|
-
tan(
|
|
1639
|
-
return Math.tan(
|
|
1840
|
+
tan(source) {
|
|
1841
|
+
return Math.tan(source[0]);
|
|
1640
1842
|
}
|
|
1641
|
-
|
|
1642
|
-
return Math.
|
|
1843
|
+
acos(source) {
|
|
1844
|
+
return Math.acos(source[0]);
|
|
1643
1845
|
}
|
|
1644
|
-
|
|
1645
|
-
return Math.
|
|
1846
|
+
asin(source) {
|
|
1847
|
+
return Math.asin(source[0]);
|
|
1646
1848
|
}
|
|
1647
|
-
atan(
|
|
1648
|
-
return Math.atan(
|
|
1849
|
+
atan(source) {
|
|
1850
|
+
return Math.atan(source[0]);
|
|
1649
1851
|
}
|
|
1650
|
-
avg(...
|
|
1852
|
+
avg(...sources) {
|
|
1853
|
+
const args = sources.map((e) => Array.isArray(e) ? e[0] : e);
|
|
1651
1854
|
return args.reduce((a, b) => {
|
|
1652
1855
|
const aVal = Array.isArray(a) ? a[0] : a;
|
|
1653
1856
|
const bVal = Array.isArray(b) ? b[0] : b;
|
|
@@ -1656,13 +1859,14 @@ class PineMath {
|
|
|
1656
1859
|
}
|
|
1657
1860
|
}
|
|
1658
1861
|
|
|
1659
|
-
var __defProp$
|
|
1660
|
-
var __defNormalProp$
|
|
1661
|
-
var __publicField$
|
|
1862
|
+
var __defProp$3 = Object.defineProperty;
|
|
1863
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1864
|
+
var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1865
|
+
const TIMEFRAMES = ["1", "3", "5", "15", "30", "45", "60", "120", "180", "240", "D", "W", "M"];
|
|
1662
1866
|
class PineRequest {
|
|
1663
1867
|
constructor(context) {
|
|
1664
1868
|
this.context = context;
|
|
1665
|
-
__publicField$
|
|
1869
|
+
__publicField$3(this, "_cache", {});
|
|
1666
1870
|
}
|
|
1667
1871
|
param(source, index, name) {
|
|
1668
1872
|
if (!this.context.params[name]) this.context.params[name] = [];
|
|
@@ -1678,8 +1882,42 @@ class PineRequest {
|
|
|
1678
1882
|
return [source, name];
|
|
1679
1883
|
}
|
|
1680
1884
|
}
|
|
1681
|
-
async security(symbol, timeframe, expression) {
|
|
1682
|
-
|
|
1885
|
+
async security(symbol, timeframe, expression, gaps = false, lookahead = false, ignore_invalid_symbol = false, currency = null, calc_bars_count = null) {
|
|
1886
|
+
const _symbol = symbol[0];
|
|
1887
|
+
const _timeframe = timeframe[0];
|
|
1888
|
+
const _expression = expression[0];
|
|
1889
|
+
const _expression_name = expression[1];
|
|
1890
|
+
const ctxTimeframeIdx = TIMEFRAMES.indexOf(this.context.timeframe);
|
|
1891
|
+
const reqTimeframeIdx = TIMEFRAMES.indexOf(_timeframe);
|
|
1892
|
+
if (ctxTimeframeIdx == -1 || reqTimeframeIdx == -1) {
|
|
1893
|
+
throw new Error("Invalid timeframe");
|
|
1894
|
+
}
|
|
1895
|
+
if (ctxTimeframeIdx > reqTimeframeIdx) {
|
|
1896
|
+
throw new Error("Only higher timeframes are supported for now");
|
|
1897
|
+
}
|
|
1898
|
+
if (ctxTimeframeIdx === reqTimeframeIdx) {
|
|
1899
|
+
return _expression;
|
|
1900
|
+
}
|
|
1901
|
+
const myOpenTime = this.context.data.openTime[0];
|
|
1902
|
+
const myCloseTime = this.context.data.closeTime[0];
|
|
1903
|
+
if (this.context.cache[_expression_name]) {
|
|
1904
|
+
const secContext2 = this.context.cache[_expression_name];
|
|
1905
|
+
const secContextIdx2 = this._findSecContextIdx(myOpenTime, myCloseTime, secContext2.data.openTime, secContext2.data.closeTime, lookahead);
|
|
1906
|
+
return secContextIdx2 == -1 ? NaN : secContext2.params[_expression_name][secContextIdx2];
|
|
1907
|
+
}
|
|
1908
|
+
const pineTS = new PineTS(this.context.source, _symbol, _timeframe, this.context.limit || 1e3, this.context.sDate, this.context.eDate);
|
|
1909
|
+
const secContext = await pineTS.run(this.context.pineTSCode);
|
|
1910
|
+
this.context.cache[_expression_name] = secContext;
|
|
1911
|
+
const secContextIdx = this._findSecContextIdx(myOpenTime, myCloseTime, secContext.data.openTime, secContext.data.closeTime, lookahead);
|
|
1912
|
+
return secContextIdx == -1 ? NaN : secContext.params[_expression_name][secContextIdx];
|
|
1913
|
+
}
|
|
1914
|
+
_findSecContextIdx(myOpenTime, myCloseTime, openTime, closeTime, lookahead = false) {
|
|
1915
|
+
for (let i = 0; i < openTime.length; i++) {
|
|
1916
|
+
if (openTime[i] <= myOpenTime && myCloseTime <= closeTime[i]) {
|
|
1917
|
+
return i + (lookahead ? 1 : 2);
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
return -1;
|
|
1683
1921
|
}
|
|
1684
1922
|
}
|
|
1685
1923
|
|
|
@@ -1700,6 +1938,7 @@ class TechnicalAnalysis {
|
|
|
1700
1938
|
if (Array.isArray(source)) {
|
|
1701
1939
|
if (index) {
|
|
1702
1940
|
this.context.params[name] = source.slice(index);
|
|
1941
|
+
this.context.params[name].length = source.length;
|
|
1703
1942
|
return this.context.params[name];
|
|
1704
1943
|
}
|
|
1705
1944
|
this.context.params[name] = source.slice(0);
|
|
@@ -1715,9 +1954,21 @@ class TechnicalAnalysis {
|
|
|
1715
1954
|
const idx = this.context.idx;
|
|
1716
1955
|
return this.context.precision(result[idx]);
|
|
1717
1956
|
}
|
|
1718
|
-
sma(source, _period) {
|
|
1957
|
+
sma(source, _period, _cacheId) {
|
|
1719
1958
|
const period = Array.isArray(_period) ? _period[0] : _period;
|
|
1720
|
-
const
|
|
1959
|
+
const reversedSource = source.slice(0).reverse();
|
|
1960
|
+
if (this.context.useTACache && _cacheId) {
|
|
1961
|
+
if (!this.context.cache[_cacheId]) {
|
|
1962
|
+
this.context.cache[_cacheId] = {};
|
|
1963
|
+
}
|
|
1964
|
+
const cacheObj = this.context.cache[_cacheId];
|
|
1965
|
+
if (cacheObj) {
|
|
1966
|
+
const result2 = sma_cache(reversedSource, period, cacheObj);
|
|
1967
|
+
const idx2 = this.context.idx;
|
|
1968
|
+
return this.context.precision(result2[idx2]);
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
const result = sma(reversedSource, period);
|
|
1721
1972
|
const idx = this.context.idx;
|
|
1722
1973
|
return this.context.precision(result[idx]);
|
|
1723
1974
|
}
|
|
@@ -1906,6 +2157,35 @@ function rma(source, period) {
|
|
|
1906
2157
|
}
|
|
1907
2158
|
return result;
|
|
1908
2159
|
}
|
|
2160
|
+
function sma_cache(source, period, cacheObj) {
|
|
2161
|
+
const result = cacheObj.previousResult || new Array(source.length).fill(NaN);
|
|
2162
|
+
const lastProcessedIndex = cacheObj.lastProcessedIndex || -1;
|
|
2163
|
+
let previousSum = cacheObj.previousSum || 0;
|
|
2164
|
+
if (lastProcessedIndex === -1 || source.length !== lastProcessedIndex + 1) {
|
|
2165
|
+
previousSum = 0;
|
|
2166
|
+
for (let i = 0; i < period; i++) {
|
|
2167
|
+
previousSum += source[i] || 0;
|
|
2168
|
+
}
|
|
2169
|
+
result[period - 1] = previousSum / period;
|
|
2170
|
+
for (let i = 0; i < period - 1; i++) {
|
|
2171
|
+
result[i] = NaN;
|
|
2172
|
+
}
|
|
2173
|
+
for (let i = period; i < source.length; i++) {
|
|
2174
|
+
previousSum = previousSum - (source[i - period] || 0) + (source[i] || 0);
|
|
2175
|
+
result[i] = previousSum / period;
|
|
2176
|
+
}
|
|
2177
|
+
} else if (source.length === lastProcessedIndex + 2) {
|
|
2178
|
+
const newIndex = source.length - 1;
|
|
2179
|
+
previousSum = previousSum - (source[newIndex - period] || 0) + (source[newIndex] || 0);
|
|
2180
|
+
result[newIndex] = previousSum / period;
|
|
2181
|
+
} else {
|
|
2182
|
+
return sma(source, period);
|
|
2183
|
+
}
|
|
2184
|
+
cacheObj.previousSum = previousSum;
|
|
2185
|
+
cacheObj.lastProcessedIndex = source.length - 1;
|
|
2186
|
+
cacheObj.previousResult = result;
|
|
2187
|
+
return result;
|
|
2188
|
+
}
|
|
1909
2189
|
function sma(source, period) {
|
|
1910
2190
|
const result = new Array(source.length).fill(NaN);
|
|
1911
2191
|
for (let i = period - 1; i < source.length; i++) {
|
|
@@ -2024,7 +2304,7 @@ function lowest(source, length) {
|
|
|
2024
2304
|
let min = Infinity;
|
|
2025
2305
|
for (let j = 0; j < length; j++) {
|
|
2026
2306
|
const value = source[i - j];
|
|
2027
|
-
if (isNaN(value)) {
|
|
2307
|
+
if (isNaN(value) || value === void 0) {
|
|
2028
2308
|
min = min === Infinity ? NaN : min;
|
|
2029
2309
|
} else {
|
|
2030
2310
|
min = Math.min(min, value);
|
|
@@ -2144,13 +2424,212 @@ function calculateSupertrend(high, low, close, factor, atrPeriod) {
|
|
|
2144
2424
|
return [supertrend, direction];
|
|
2145
2425
|
}
|
|
2146
2426
|
|
|
2147
|
-
var __defProp = Object.defineProperty;
|
|
2148
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2149
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2427
|
+
var __defProp$2 = Object.defineProperty;
|
|
2428
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2429
|
+
var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2430
|
+
class PineArrayObject {
|
|
2431
|
+
constructor(array) {
|
|
2432
|
+
this.array = array;
|
|
2433
|
+
}
|
|
2434
|
+
}
|
|
2435
|
+
class PineArray {
|
|
2436
|
+
constructor(context) {
|
|
2437
|
+
this.context = context;
|
|
2438
|
+
__publicField$2(this, "_cache", {});
|
|
2439
|
+
}
|
|
2440
|
+
param(source, index = 0) {
|
|
2441
|
+
if (Array.isArray(source)) {
|
|
2442
|
+
return source[index];
|
|
2443
|
+
}
|
|
2444
|
+
return source;
|
|
2445
|
+
}
|
|
2446
|
+
/**
|
|
2447
|
+
* This function simulates PineScript's array.get() function
|
|
2448
|
+
* @param id - the array object to get the value from
|
|
2449
|
+
* @param index - the index of the value to get
|
|
2450
|
+
* @returns the value at the given index
|
|
2451
|
+
*/
|
|
2452
|
+
get(id, index) {
|
|
2453
|
+
return id.array[index];
|
|
2454
|
+
}
|
|
2455
|
+
set(id, index, value) {
|
|
2456
|
+
id.array[index] = value;
|
|
2457
|
+
}
|
|
2458
|
+
push(id, value) {
|
|
2459
|
+
id.array.push(value);
|
|
2460
|
+
}
|
|
2461
|
+
// Basic statistics
|
|
2462
|
+
sum(id) {
|
|
2463
|
+
return id.array.reduce((a, b) => a + (isNaN(b) ? 0 : b), 0);
|
|
2464
|
+
}
|
|
2465
|
+
avg(id) {
|
|
2466
|
+
return this.sum(id) / id.array.length;
|
|
2467
|
+
}
|
|
2468
|
+
min(id, nth = 0) {
|
|
2469
|
+
const sorted = [...id.array].sort((a, b) => a - b);
|
|
2470
|
+
return sorted[nth] ?? this.context.NA;
|
|
2471
|
+
}
|
|
2472
|
+
max(id, nth = 0) {
|
|
2473
|
+
const sorted = [...id.array].sort((a, b) => b - a);
|
|
2474
|
+
return sorted[nth] ?? this.context.NA;
|
|
2475
|
+
}
|
|
2476
|
+
size(id) {
|
|
2477
|
+
return id.array.length;
|
|
2478
|
+
}
|
|
2479
|
+
// Array creation
|
|
2480
|
+
new_bool(size, initial_value = false) {
|
|
2481
|
+
return new PineArrayObject(Array(size).fill(initial_value));
|
|
2482
|
+
}
|
|
2483
|
+
new_float(size, initial_value = NaN) {
|
|
2484
|
+
return new PineArrayObject(Array(size).fill(initial_value));
|
|
2485
|
+
}
|
|
2486
|
+
new_int(size, initial_value = 0) {
|
|
2487
|
+
return new PineArrayObject(Array(size).fill(Math.round(initial_value)));
|
|
2488
|
+
}
|
|
2489
|
+
new_string(size, initial_value = "") {
|
|
2490
|
+
return new PineArrayObject(Array(size).fill(initial_value));
|
|
2491
|
+
}
|
|
2492
|
+
new(size, initial_value) {
|
|
2493
|
+
return new PineArrayObject(Array(size).fill(initial_value));
|
|
2494
|
+
}
|
|
2495
|
+
// Array operations
|
|
2496
|
+
slice(id, start, end) {
|
|
2497
|
+
const adjustedEnd = end !== void 0 ? end + 1 : void 0;
|
|
2498
|
+
return new PineArrayObject(id.array.slice(start, adjustedEnd));
|
|
2499
|
+
}
|
|
2500
|
+
reverse(id) {
|
|
2501
|
+
id.array.reverse();
|
|
2502
|
+
}
|
|
2503
|
+
includes(id, value) {
|
|
2504
|
+
return id.array.includes(value);
|
|
2505
|
+
}
|
|
2506
|
+
indexof(id, value) {
|
|
2507
|
+
return id.array.indexOf(value);
|
|
2508
|
+
}
|
|
2509
|
+
lastindexof(id, value) {
|
|
2510
|
+
return id.array.lastIndexOf(value);
|
|
2511
|
+
}
|
|
2512
|
+
// More complex functions
|
|
2513
|
+
stdev(id, biased = true) {
|
|
2514
|
+
const mean = this.avg(id);
|
|
2515
|
+
const deviations = id.array.map((x) => Math.pow(x - mean, 2));
|
|
2516
|
+
const divisor = biased ? id.array.length : id.array.length - 1;
|
|
2517
|
+
return Math.sqrt(this.sum(new PineArrayObject(deviations)) / divisor);
|
|
2518
|
+
}
|
|
2519
|
+
variance(id, biased = true) {
|
|
2520
|
+
const mean = this.avg(id);
|
|
2521
|
+
const deviations = id.array.map((x) => Math.pow(x - mean, 2));
|
|
2522
|
+
const divisor = biased ? id.array.length : id.array.length - 1;
|
|
2523
|
+
return this.sum(new PineArrayObject(deviations)) / divisor;
|
|
2524
|
+
}
|
|
2525
|
+
covariance(arr1, arr2, biased = true) {
|
|
2526
|
+
if (arr1.array.length !== arr2.array.length || arr1.array.length < 2) return NaN;
|
|
2527
|
+
const divisor = biased ? arr1.array.length : arr1.array.length - 1;
|
|
2528
|
+
const mean1 = this.avg(arr1);
|
|
2529
|
+
const mean2 = this.avg(arr2);
|
|
2530
|
+
let sum = 0;
|
|
2531
|
+
for (let i = 0; i < arr1.array.length; i++) {
|
|
2532
|
+
sum += (arr1.array[i] - mean1) * (arr2.array[i] - mean2);
|
|
2533
|
+
}
|
|
2534
|
+
return sum / divisor;
|
|
2535
|
+
}
|
|
2536
|
+
// Additional utility methods
|
|
2537
|
+
first(id) {
|
|
2538
|
+
return id.array.length > 0 ? id.array[0] : this.context.NA;
|
|
2539
|
+
}
|
|
2540
|
+
last(id) {
|
|
2541
|
+
return id.array.length > 0 ? id.array[id.array.length - 1] : this.context.NA;
|
|
2542
|
+
}
|
|
2543
|
+
clear(id) {
|
|
2544
|
+
id.array.length = 0;
|
|
2545
|
+
}
|
|
2546
|
+
join(id, separator = ",") {
|
|
2547
|
+
return id.array.join(separator);
|
|
2548
|
+
}
|
|
2549
|
+
/** Array Manipulation Functions */
|
|
2550
|
+
abs(id) {
|
|
2551
|
+
return new PineArrayObject(id.array.map((val) => Math.abs(val)));
|
|
2552
|
+
}
|
|
2553
|
+
concat(id, other) {
|
|
2554
|
+
id.array.push(...other.array);
|
|
2555
|
+
return id;
|
|
2556
|
+
}
|
|
2557
|
+
copy(id) {
|
|
2558
|
+
return new PineArrayObject([...id.array]);
|
|
2559
|
+
}
|
|
2560
|
+
every(id, callback) {
|
|
2561
|
+
return id.array.every(callback);
|
|
2562
|
+
}
|
|
2563
|
+
fill(id, value, start = 0, end) {
|
|
2564
|
+
const length = id.array.length;
|
|
2565
|
+
const adjustedEnd = end !== void 0 ? Math.min(end, length) : length;
|
|
2566
|
+
for (let i = start; i < adjustedEnd; i++) {
|
|
2567
|
+
id.array[i] = value;
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
from(source) {
|
|
2571
|
+
return new PineArrayObject([...source]);
|
|
2572
|
+
}
|
|
2573
|
+
insert(id, index, value) {
|
|
2574
|
+
id.array.splice(index, 0, value);
|
|
2575
|
+
}
|
|
2576
|
+
pop(id) {
|
|
2577
|
+
return id.array.pop();
|
|
2578
|
+
}
|
|
2579
|
+
range(id) {
|
|
2580
|
+
return this.max(id) - this.min(id);
|
|
2581
|
+
}
|
|
2582
|
+
remove(id, index) {
|
|
2583
|
+
if (index >= 0 && index < id.array.length) {
|
|
2584
|
+
return id.array.splice(index, 1)[0];
|
|
2585
|
+
}
|
|
2586
|
+
return this.context.NA;
|
|
2587
|
+
}
|
|
2588
|
+
shift(id) {
|
|
2589
|
+
return id.array.shift();
|
|
2590
|
+
}
|
|
2591
|
+
sort(id, order = "asc") {
|
|
2592
|
+
id.array.sort((a, b) => order === "asc" ? a - b : b - a);
|
|
2593
|
+
}
|
|
2594
|
+
sort_indices(id, comparator) {
|
|
2595
|
+
const indices = id.array.map((_, index) => index);
|
|
2596
|
+
indices.sort((a, b) => {
|
|
2597
|
+
const valA = id.array[a];
|
|
2598
|
+
const valB = id.array[b];
|
|
2599
|
+
return comparator ? comparator(valA, valB) : valA - valB;
|
|
2600
|
+
});
|
|
2601
|
+
return new PineArrayObject(indices);
|
|
2602
|
+
}
|
|
2603
|
+
standardize(id) {
|
|
2604
|
+
const mean = this.avg(id);
|
|
2605
|
+
const stdev = this.stdev(id);
|
|
2606
|
+
if (stdev === 0) {
|
|
2607
|
+
return new PineArrayObject(id.array.map(() => 0));
|
|
2608
|
+
}
|
|
2609
|
+
return new PineArrayObject(id.array.map((x) => (x - mean) / stdev));
|
|
2610
|
+
}
|
|
2611
|
+
unshift(id, value) {
|
|
2612
|
+
id.array.unshift(value);
|
|
2613
|
+
}
|
|
2614
|
+
some(id, callback) {
|
|
2615
|
+
return id.array.some(callback);
|
|
2616
|
+
}
|
|
2617
|
+
}
|
|
2618
|
+
|
|
2619
|
+
var __defProp$1 = Object.defineProperty;
|
|
2620
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2621
|
+
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2150
2622
|
class Context {
|
|
2151
|
-
constructor(
|
|
2152
|
-
|
|
2153
|
-
|
|
2623
|
+
constructor({
|
|
2624
|
+
marketData,
|
|
2625
|
+
source,
|
|
2626
|
+
tickerId,
|
|
2627
|
+
timeframe,
|
|
2628
|
+
limit,
|
|
2629
|
+
sDate,
|
|
2630
|
+
eDate
|
|
2631
|
+
}) {
|
|
2632
|
+
__publicField$1(this, "data", {
|
|
2154
2633
|
open: [],
|
|
2155
2634
|
high: [],
|
|
2156
2635
|
low: [],
|
|
@@ -2160,23 +2639,43 @@ class Context {
|
|
|
2160
2639
|
hlc3: [],
|
|
2161
2640
|
ohlc4: []
|
|
2162
2641
|
});
|
|
2163
|
-
__publicField(this, "
|
|
2164
|
-
__publicField(this, "
|
|
2165
|
-
__publicField(this, "
|
|
2166
|
-
__publicField(this, "
|
|
2167
|
-
__publicField(this, "
|
|
2168
|
-
__publicField(this, "
|
|
2169
|
-
__publicField(this, "
|
|
2170
|
-
__publicField(this, "
|
|
2171
|
-
__publicField(this, "
|
|
2172
|
-
__publicField(this, "
|
|
2173
|
-
__publicField(this, "
|
|
2174
|
-
__publicField(this, "
|
|
2175
|
-
__publicField(this, "
|
|
2642
|
+
__publicField$1(this, "cache", {});
|
|
2643
|
+
__publicField$1(this, "useTACache", false);
|
|
2644
|
+
__publicField$1(this, "NA", NaN);
|
|
2645
|
+
__publicField$1(this, "math");
|
|
2646
|
+
__publicField$1(this, "ta");
|
|
2647
|
+
__publicField$1(this, "input");
|
|
2648
|
+
__publicField$1(this, "request");
|
|
2649
|
+
__publicField$1(this, "array");
|
|
2650
|
+
__publicField$1(this, "core");
|
|
2651
|
+
__publicField$1(this, "lang");
|
|
2652
|
+
__publicField$1(this, "idx", 0);
|
|
2653
|
+
__publicField$1(this, "params", {});
|
|
2654
|
+
__publicField$1(this, "const", {});
|
|
2655
|
+
__publicField$1(this, "var", {});
|
|
2656
|
+
__publicField$1(this, "let", {});
|
|
2657
|
+
__publicField$1(this, "result");
|
|
2658
|
+
__publicField$1(this, "plots", {});
|
|
2659
|
+
__publicField$1(this, "marketData");
|
|
2660
|
+
__publicField$1(this, "source");
|
|
2661
|
+
__publicField$1(this, "tickerId");
|
|
2662
|
+
__publicField$1(this, "timeframe", "");
|
|
2663
|
+
__publicField$1(this, "limit");
|
|
2664
|
+
__publicField$1(this, "sDate");
|
|
2665
|
+
__publicField$1(this, "eDate");
|
|
2666
|
+
__publicField$1(this, "pineTSCode");
|
|
2667
|
+
this.marketData = marketData;
|
|
2668
|
+
this.source = source;
|
|
2669
|
+
this.tickerId = tickerId;
|
|
2670
|
+
this.timeframe = timeframe;
|
|
2671
|
+
this.limit = limit;
|
|
2672
|
+
this.sDate = sDate;
|
|
2673
|
+
this.eDate = eDate;
|
|
2176
2674
|
this.math = new PineMath(this);
|
|
2177
2675
|
this.ta = new TechnicalAnalysis(this);
|
|
2178
2676
|
this.input = new Input(this);
|
|
2179
2677
|
this.request = new PineRequest(this);
|
|
2678
|
+
this.array = new PineArray(this);
|
|
2180
2679
|
const core = new Core(this);
|
|
2181
2680
|
this.core = {
|
|
2182
2681
|
plotchar: core.plotchar.bind(core),
|
|
@@ -2212,12 +2711,13 @@ class Context {
|
|
|
2212
2711
|
return trg;
|
|
2213
2712
|
}
|
|
2214
2713
|
/**
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2714
|
+
* this function is used to set the floating point precision of a number
|
|
2715
|
+
* by default it is set to 10 decimals which is the same as pine script
|
|
2716
|
+
* @param n - the number to be precision
|
|
2717
|
+
* @param decimals - the number of decimals to precision to
|
|
2718
|
+
|
|
2719
|
+
* @returns the precision number
|
|
2720
|
+
*/
|
|
2221
2721
|
precision(n, decimals = 10) {
|
|
2222
2722
|
if (typeof n !== "number" || isNaN(n)) return n;
|
|
2223
2723
|
return Number(n.toFixed(decimals));
|
|
@@ -2236,6 +2736,7 @@ class Context {
|
|
|
2236
2736
|
if (Array.isArray(source)) {
|
|
2237
2737
|
if (index) {
|
|
2238
2738
|
this.params[name] = source.slice(index);
|
|
2739
|
+
this.params[name].length = source.length;
|
|
2239
2740
|
return this.params[name];
|
|
2240
2741
|
}
|
|
2241
2742
|
this.params[name] = source.slice(0);
|
|
@@ -2248,6 +2749,9 @@ class Context {
|
|
|
2248
2749
|
//#endregion
|
|
2249
2750
|
}
|
|
2250
2751
|
|
|
2752
|
+
var __defProp = Object.defineProperty;
|
|
2753
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2754
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2251
2755
|
const BINANCE_API_URL = "https://api.binance.com/api/v3";
|
|
2252
2756
|
const timeframe_to_binance = {
|
|
2253
2757
|
"1": "1m",
|
|
@@ -2270,6 +2774,8 @@ const timeframe_to_binance = {
|
|
|
2270
2774
|
// 3 hours (not directly supported by Binance, needs custom handling)
|
|
2271
2775
|
"240": "4h",
|
|
2272
2776
|
// 4 hours
|
|
2777
|
+
"4H": "4h",
|
|
2778
|
+
// 4 hours
|
|
2273
2779
|
"1D": "1d",
|
|
2274
2780
|
// 1 day
|
|
2275
2781
|
D: "1d",
|
|
@@ -2283,15 +2789,119 @@ const timeframe_to_binance = {
|
|
|
2283
2789
|
M: "1M"
|
|
2284
2790
|
// 1 month
|
|
2285
2791
|
};
|
|
2792
|
+
class CacheManager {
|
|
2793
|
+
constructor(cacheDuration = 5 * 60 * 1e3) {
|
|
2794
|
+
__publicField(this, "cache");
|
|
2795
|
+
__publicField(this, "cacheDuration");
|
|
2796
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
2797
|
+
this.cacheDuration = cacheDuration;
|
|
2798
|
+
}
|
|
2799
|
+
generateKey(params) {
|
|
2800
|
+
return Object.entries(params).filter(([_, value]) => value !== void 0).map(([key, value]) => `${key}:${value}`).join("|");
|
|
2801
|
+
}
|
|
2802
|
+
get(params) {
|
|
2803
|
+
const key = this.generateKey(params);
|
|
2804
|
+
const cached = this.cache.get(key);
|
|
2805
|
+
if (!cached) return null;
|
|
2806
|
+
if (Date.now() - cached.timestamp > this.cacheDuration) {
|
|
2807
|
+
this.cache.delete(key);
|
|
2808
|
+
return null;
|
|
2809
|
+
}
|
|
2810
|
+
return cached.data;
|
|
2811
|
+
}
|
|
2812
|
+
set(params, data) {
|
|
2813
|
+
const key = this.generateKey(params);
|
|
2814
|
+
this.cache.set(key, {
|
|
2815
|
+
data,
|
|
2816
|
+
timestamp: Date.now()
|
|
2817
|
+
});
|
|
2818
|
+
}
|
|
2819
|
+
clear() {
|
|
2820
|
+
this.cache.clear();
|
|
2821
|
+
}
|
|
2822
|
+
// Optional: method to remove expired entries
|
|
2823
|
+
cleanup() {
|
|
2824
|
+
const now = Date.now();
|
|
2825
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
2826
|
+
if (now - entry.timestamp > this.cacheDuration) {
|
|
2827
|
+
this.cache.delete(key);
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2286
2832
|
class BinanceProvider {
|
|
2833
|
+
constructor() {
|
|
2834
|
+
__publicField(this, "cacheManager");
|
|
2835
|
+
this.cacheManager = new CacheManager(5 * 60 * 1e3);
|
|
2836
|
+
}
|
|
2837
|
+
async getMarketDataInterval(tickerId, timeframe, sDate, eDate) {
|
|
2838
|
+
try {
|
|
2839
|
+
const interval = timeframe_to_binance[timeframe.toUpperCase()];
|
|
2840
|
+
if (!interval) {
|
|
2841
|
+
console.error(`Unsupported timeframe: ${timeframe}`);
|
|
2842
|
+
return [];
|
|
2843
|
+
}
|
|
2844
|
+
const timeframeDurations = {
|
|
2845
|
+
"1m": 60 * 1e3,
|
|
2846
|
+
"3m": 3 * 60 * 1e3,
|
|
2847
|
+
"5m": 5 * 60 * 1e3,
|
|
2848
|
+
"15m": 15 * 60 * 1e3,
|
|
2849
|
+
"30m": 30 * 60 * 1e3,
|
|
2850
|
+
"1h": 60 * 60 * 1e3,
|
|
2851
|
+
"2h": 2 * 60 * 60 * 1e3,
|
|
2852
|
+
"4h": 4 * 60 * 60 * 1e3,
|
|
2853
|
+
"1d": 24 * 60 * 60 * 1e3,
|
|
2854
|
+
"1w": 7 * 24 * 60 * 60 * 1e3,
|
|
2855
|
+
"1M": 30 * 24 * 60 * 60 * 1e3
|
|
2856
|
+
};
|
|
2857
|
+
let allData = [];
|
|
2858
|
+
let currentStart = sDate;
|
|
2859
|
+
const endTime = eDate;
|
|
2860
|
+
const intervalDuration = timeframeDurations[interval];
|
|
2861
|
+
if (!intervalDuration) {
|
|
2862
|
+
console.error(`Duration not defined for interval: ${interval}`);
|
|
2863
|
+
return [];
|
|
2864
|
+
}
|
|
2865
|
+
while (currentStart < endTime) {
|
|
2866
|
+
const chunkEnd = Math.min(currentStart + 1e3 * intervalDuration, endTime);
|
|
2867
|
+
const data = await this.getMarketData(
|
|
2868
|
+
tickerId,
|
|
2869
|
+
timeframe,
|
|
2870
|
+
1e3,
|
|
2871
|
+
// Max allowed by Binance
|
|
2872
|
+
currentStart,
|
|
2873
|
+
chunkEnd
|
|
2874
|
+
);
|
|
2875
|
+
if (data.length === 0) break;
|
|
2876
|
+
allData = allData.concat(data);
|
|
2877
|
+
currentStart = data[data.length - 1].closeTime + 1;
|
|
2878
|
+
if (data.length < 1e3) break;
|
|
2879
|
+
}
|
|
2880
|
+
return allData;
|
|
2881
|
+
} catch (error) {
|
|
2882
|
+
console.error("Error in getMarketDataInterval:", error);
|
|
2883
|
+
return [];
|
|
2884
|
+
}
|
|
2885
|
+
}
|
|
2886
|
+
//TODO : allow querying more than 1000 klines
|
|
2887
|
+
//TODO : immplement cache
|
|
2287
2888
|
async getMarketData(tickerId, timeframe, limit, sDate, eDate) {
|
|
2288
2889
|
try {
|
|
2890
|
+
const cacheParams = { tickerId, timeframe, limit, sDate, eDate };
|
|
2891
|
+
const cachedData = this.cacheManager.get(cacheParams);
|
|
2892
|
+
if (cachedData) {
|
|
2893
|
+
console.log("cache hit", tickerId, timeframe, limit, sDate, eDate);
|
|
2894
|
+
return cachedData;
|
|
2895
|
+
}
|
|
2289
2896
|
const interval = timeframe_to_binance[timeframe.toUpperCase()];
|
|
2290
2897
|
if (!interval) {
|
|
2291
2898
|
console.error(`Unsupported timeframe: ${timeframe}`);
|
|
2292
2899
|
return [];
|
|
2293
2900
|
}
|
|
2294
2901
|
let url = `${BINANCE_API_URL}/klines?symbol=${tickerId}&interval=${interval}`;
|
|
2902
|
+
if (!limit && sDate && eDate) {
|
|
2903
|
+
return this.getMarketDataInterval(tickerId, timeframe, sDate, eDate);
|
|
2904
|
+
}
|
|
2295
2905
|
if (limit) {
|
|
2296
2906
|
url += `&limit=${limit}`;
|
|
2297
2907
|
}
|
|
@@ -2308,13 +2918,13 @@ class BinanceProvider {
|
|
|
2308
2918
|
const result = await response.json();
|
|
2309
2919
|
const data = result.map((item) => {
|
|
2310
2920
|
return {
|
|
2311
|
-
openTime: parseInt(item[0])
|
|
2921
|
+
openTime: parseInt(item[0]),
|
|
2312
2922
|
open: parseFloat(item[1]),
|
|
2313
2923
|
high: parseFloat(item[2]),
|
|
2314
2924
|
low: parseFloat(item[3]),
|
|
2315
2925
|
close: parseFloat(item[4]),
|
|
2316
2926
|
volume: parseFloat(item[5]),
|
|
2317
|
-
closeTime: parseInt(item[6])
|
|
2927
|
+
closeTime: parseInt(item[6]),
|
|
2318
2928
|
quoteAssetVolume: parseFloat(item[7]),
|
|
2319
2929
|
numberOfTrades: parseInt(item[8]),
|
|
2320
2930
|
takerBuyBaseAssetVolume: parseFloat(item[9]),
|
|
@@ -2322,6 +2932,7 @@ class BinanceProvider {
|
|
|
2322
2932
|
ignore: item[11]
|
|
2323
2933
|
};
|
|
2324
2934
|
});
|
|
2935
|
+
this.cacheManager.set(cacheParams, data);
|
|
2325
2936
|
return data;
|
|
2326
2937
|
} catch (error) {
|
|
2327
2938
|
console.error("Error in binance.klines:", error);
|
|
@@ -2332,6 +2943,7 @@ class BinanceProvider {
|
|
|
2332
2943
|
|
|
2333
2944
|
const Provider = {
|
|
2334
2945
|
Binance: new BinanceProvider()
|
|
2946
|
+
//TODO : add other providers (polygon, etc.)
|
|
2335
2947
|
};
|
|
2336
2948
|
|
|
2337
2949
|
export { Context, PineTS, Provider };
|