chart-library-native 1.0.0

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/index.d.ts ADDED
@@ -0,0 +1,66 @@
1
+ // ============================================================================
2
+ // 📄 bindings/react-native/index.d.ts
3
+ // Mục đích: TypeScript types & exports cho React Native
4
+ // ============================================================================
5
+
6
+ declare const ChartLibrary: {
7
+ calculateMA(closes: number[], period: number): (number | null)[];
8
+ calculateEMA(closes: number[], period: number): (number | null)[];
9
+
10
+ calculateMACD(
11
+ closes: number[],
12
+ fast: number,
13
+ slow: number,
14
+ signal: number
15
+ ): {
16
+ macd: (number | null)[];
17
+ signal: (number | null)[];
18
+ histogram: (number | null)[];
19
+ };
20
+
21
+ calculateRSI(closes: number[], period: number): (number | null)[];
22
+
23
+ calculateKDJ(
24
+ highs: number[],
25
+ lows: number[],
26
+ closes: number[],
27
+ n: number,
28
+ m1: number,
29
+ m2: number
30
+ ): {
31
+ k: (number | null)[];
32
+ d: (number | null)[];
33
+ j: (number | null)[];
34
+ };
35
+
36
+ calculateBOLL(
37
+ closes: number[],
38
+ period: number,
39
+ k: number
40
+ ): {
41
+ upper: (number | null)[];
42
+ middle: (number | null)[];
43
+ lower: (number | null)[];
44
+ };
45
+
46
+ calculateDMI(
47
+ opens: number[],
48
+ highs: number[],
49
+ lows: number[],
50
+ closes: number[],
51
+ period: number
52
+ ): {
53
+ pdi: (number | null)[];
54
+ mdi: (number | null)[];
55
+ adx: (number | null)[];
56
+ adxr: (number | null)[];
57
+ };
58
+ };
59
+
60
+ export default ChartLibrary;
61
+
62
+ // Usage in React Native:
63
+ // import ChartLibrary from 'chart-library-native'
64
+ // const ma = ChartLibrary.calculateMA([10, 11, 12, 13], 2);
65
+ // const macd = ChartLibrary.calculateMACD(closes, 12, 26, 9);
66
+
package/index.js ADDED
@@ -0,0 +1,86 @@
1
+ // ============================================================================
2
+ // 📄 bindings/react-native/index.js
3
+ // Mục đích: JavaScript entry point for React Native package
4
+ // ============================================================================
5
+
6
+ // Check if ChartLibrary is available (JSI module)
7
+ // This is registered by installChartLibrary() in jsi_bindings.cpp
8
+ let ChartLibrary = global.ChartLibrary;
9
+
10
+ if (!ChartLibrary) {
11
+ console.warn(
12
+ 'ChartLibrary: JSI module not found. ' +
13
+ 'Make sure you have properly installed and linked the native module. ' +
14
+ 'Call installChartLibrary(runtime) in your native code.'
15
+ );
16
+
17
+ // Provide a stub object to prevent crashes
18
+ ChartLibrary = {
19
+ calculateMA: () => { throw new Error('ChartLibrary not initialized'); },
20
+ calculateEMA: () => { throw new Error('ChartLibrary not initialized'); },
21
+ calculateMACD: () => { throw new Error('ChartLibrary not initialized'); },
22
+ calculateRSI: () => { throw new Error('ChartLibrary not initialized'); },
23
+ calculateKDJ: () => { throw new Error('ChartLibrary not initialized'); },
24
+ calculateBOLL: () => { throw new Error('ChartLibrary not initialized'); },
25
+ calculateDMI: () => { throw new Error('ChartLibrary not initialized'); },
26
+ };
27
+ }
28
+
29
+ // Export all indicator functions
30
+ // These directly call the JSI functions registered by installChartLibrary()
31
+ export default {
32
+ // Moving Averages
33
+ calculateMA: (closes, period) => {
34
+ if (!ChartLibrary.calculateMA) {
35
+ throw new Error('calculateMA is not available. Make sure native module is properly installed.');
36
+ }
37
+ return ChartLibrary.calculateMA(closes, period);
38
+ },
39
+
40
+ calculateEMA: (closes, period) => {
41
+ if (!ChartLibrary.calculateEMA) {
42
+ throw new Error('calculateEMA is not available. Make sure native module is properly installed.');
43
+ }
44
+ return ChartLibrary.calculateEMA(closes, period);
45
+ },
46
+
47
+ // MACD
48
+ calculateMACD: (closes, fastPeriod = 12, slowPeriod = 26, signalPeriod = 9) => {
49
+ if (!ChartLibrary.calculateMACD) {
50
+ throw new Error('calculateMACD is not available. Make sure native module is properly installed.');
51
+ }
52
+ return ChartLibrary.calculateMACD(closes, fastPeriod, slowPeriod, signalPeriod);
53
+ },
54
+
55
+ // RSI
56
+ calculateRSI: (closes, period = 14) => {
57
+ if (!ChartLibrary.calculateRSI) {
58
+ throw new Error('calculateRSI is not available. Make sure native module is properly installed.');
59
+ }
60
+ return ChartLibrary.calculateRSI(closes, period);
61
+ },
62
+
63
+ // KDJ
64
+ calculateKDJ: (highs, lows, closes, n = 9, m1 = 3, m2 = 3) => {
65
+ if (!ChartLibrary.calculateKDJ) {
66
+ throw new Error('calculateKDJ is not available. Make sure native module is properly installed.');
67
+ }
68
+ return ChartLibrary.calculateKDJ(highs, lows, closes, n, m1, m2);
69
+ },
70
+
71
+ // Bollinger Bands
72
+ calculateBOLL: (closes, period = 20, k = 2.0) => {
73
+ if (!ChartLibrary.calculateBOLL) {
74
+ throw new Error('calculateBOLL is not available. Make sure native module is properly installed.');
75
+ }
76
+ return ChartLibrary.calculateBOLL(closes, period, k);
77
+ },
78
+
79
+ // DMI (requires opens, highs, lows, closes)
80
+ calculateDMI: (opens, highs, lows, closes, period = 14) => {
81
+ if (!ChartLibrary.calculateDMI) {
82
+ throw new Error('calculateDMI is not available. Make sure native module is properly installed.');
83
+ }
84
+ return ChartLibrary.calculateDMI(opens, highs, lows, closes, period);
85
+ }
86
+ };
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "chart-library-native",
3
+ "version": "1.0.0",
4
+ "description": "âš¡ High-performance chart library with 20 technical indicators for React Native. C++ core + JSI bindings.",
5
+ "main": "index.js",
6
+ "types": "index.d.ts",
7
+ "module": "src/index.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./index.d.ts",
11
+ "import": "./index.js",
12
+ "require": "./index.js"
13
+ },
14
+ "./src": {
15
+ "types": "./src/index.ts",
16
+ "import": "./src/index.ts"
17
+ }
18
+ },
19
+ "files": [
20
+ "index.js",
21
+ "index.d.ts",
22
+ "src/",
23
+ "CMakeLists.txt",
24
+ "README.md",
25
+ "LICENSE",
26
+ "EXPO_SETUP.md"
27
+ ],
28
+ "scripts": {
29
+ "build": "tsc || echo 'TypeScript not installed, skipping build. Source files are in src/ and can be used directly.'",
30
+ "build:check": "tsc --noEmit",
31
+ "prepublishOnly": "echo 'Preparing to publish...'",
32
+ "test": "echo \"Error: no test specified\" && exit 1"
33
+ },
34
+ "keywords": [
35
+ "react-native",
36
+ "expo",
37
+ "chart",
38
+ "technical-indicators",
39
+ "trading",
40
+ "ma",
41
+ "macd",
42
+ "rsi",
43
+ "kdj",
44
+ "bollinger",
45
+ "dmi",
46
+ "indicators",
47
+ "stock",
48
+ "crypto",
49
+ "finance",
50
+ "c++",
51
+ "jsi",
52
+ "expo-development-build"
53
+ ],
54
+ "author": "",
55
+ "license": "MIT",
56
+ "repository": {
57
+ "type": "git",
58
+ "url": "https://github.com/yourusername/chart-across-platform.git"
59
+ },
60
+ "bugs": {
61
+ "url": "https://github.com/yourusername/chart-across-platform/issues"
62
+ },
63
+ "homepage": "https://github.com/yourusername/chart-across-platform#readme",
64
+ "peerDependencies": {
65
+ "react": ">=16.8.0",
66
+ "react-native": ">=0.60.0"
67
+ },
68
+ "devDependencies": {
69
+ "@types/react": "^18.0.0",
70
+ "@types/react-native": "^0.72.0",
71
+ "typescript": "^5.9.3"
72
+ },
73
+ "optionalDependencies": {
74
+ "typescript": "^5.0.0"
75
+ }
76
+ }
@@ -0,0 +1,249 @@
1
+ // ============================================================================
2
+ // 📄 bindings/react-native/src/ChartModule.cpp
3
+ // Mục đích: JSI Bridge Module Implementation for React Native
4
+ // ============================================================================
5
+
6
+ #include "ChartModule.h"
7
+ #include "helpers.h"
8
+ #include "../../core/indicators/indicators.h"
9
+ #include <stdexcept>
10
+
11
+ using namespace facebook;
12
+
13
+ namespace chart {
14
+ namespace reactnative {
15
+
16
+ // ========================================================================
17
+ // Install the module into JSI runtime
18
+ // ========================================================================
19
+ void ChartModule::install(jsi::Runtime& runtime) {
20
+ auto chartModule = std::make_shared<ChartModule>();
21
+ auto object = jsi::Object::createFromHostObject(runtime, chartModule);
22
+ runtime.global().setProperty(runtime, "ChartNative", std::move(object));
23
+ }
24
+
25
+ // ========================================================================
26
+ // Get property handler - maps JavaScript function calls to C++ functions
27
+ // ========================================================================
28
+ jsi::Value ChartModule::get(jsi::Runtime& runtime, const jsi::PropNameID& name) {
29
+ std::string propName = name.utf8(runtime);
30
+
31
+ // ========== MOVING AVERAGES ==========
32
+ if (propName == "calculateMA") {
33
+ return jsi::Function::createFromHostFunction(
34
+ runtime,
35
+ name,
36
+ 2, // 2 parameters: closes, period
37
+ [](jsi::Runtime& rt, const jsi::Value* args, size_t count) -> jsi::Value {
38
+ if (count < 2) {
39
+ throw jsi::JSError(rt, "calculateMA requires 2 arguments: closes, period");
40
+ }
41
+
42
+ auto closes = helpers::jsArrayToVector(rt, args[0]);
43
+ int period = static_cast<int>(args[1].asNumber());
44
+
45
+ auto result = indicators::calculateMA(closes, period);
46
+ return helpers::vectorToJSArray(rt, result);
47
+ }
48
+ );
49
+ }
50
+
51
+ if (propName == "calculateEMA") {
52
+ return jsi::Function::createFromHostFunction(
53
+ runtime,
54
+ name,
55
+ 2,
56
+ [](jsi::Runtime& rt, const jsi::Value* args, size_t count) -> jsi::Value {
57
+ if (count < 2) {
58
+ throw jsi::JSError(rt, "calculateEMA requires 2 arguments: closes, period");
59
+ }
60
+
61
+ auto closes = helpers::jsArrayToVector(rt, args[0]);
62
+ int period = static_cast<int>(args[1].asNumber());
63
+
64
+ auto result = indicators::calculateEMA(closes, period);
65
+ return helpers::vectorToJSArray(rt, result);
66
+ }
67
+ );
68
+ }
69
+
70
+ // ========== MACD ==========
71
+ if (propName == "calculateMACD") {
72
+ return jsi::Function::createFromHostFunction(
73
+ runtime,
74
+ name,
75
+ 4, // closes, fastPeriod, slowPeriod, signalPeriod
76
+ [](jsi::Runtime& rt, const jsi::Value* args, size_t count) -> jsi::Value {
77
+ if (count < 1) {
78
+ throw jsi::JSError(rt, "calculateMACD requires at least 1 argument: closes");
79
+ }
80
+
81
+ auto closes = helpers::jsArrayToVector(rt, args[0]);
82
+ int fastPeriod = count > 1 ? static_cast<int>(args[1].asNumber()) : 12;
83
+ int slowPeriod = count > 2 ? static_cast<int>(args[2].asNumber()) : 26;
84
+ int signalPeriod = count > 3 ? static_cast<int>(args[3].asNumber()) : 9;
85
+
86
+ auto result = indicators::calculateMACD(closes, fastPeriod, slowPeriod, signalPeriod);
87
+ return helpers::macdResultToJSObject(rt, result);
88
+ }
89
+ );
90
+ }
91
+
92
+ // ========== RSI ==========
93
+ if (propName == "calculateRSI") {
94
+ return jsi::Function::createFromHostFunction(
95
+ runtime,
96
+ name,
97
+ 2,
98
+ [](jsi::Runtime& rt, const jsi::Value* args, size_t count) -> jsi::Value {
99
+ if (count < 1) {
100
+ throw jsi::JSError(rt, "calculateRSI requires at least 1 argument: closes");
101
+ }
102
+
103
+ auto closes = helpers::jsArrayToVector(rt, args[0]);
104
+ int period = count > 1 ? static_cast<int>(args[1].asNumber()) : 14;
105
+
106
+ auto result = indicators::calculateRSI(closes, period);
107
+ return helpers::vectorToJSArray(rt, result);
108
+ }
109
+ );
110
+ }
111
+
112
+ // ========== KDJ ==========
113
+ if (propName == "calculateKDJ") {
114
+ return jsi::Function::createFromHostFunction(
115
+ runtime,
116
+ name,
117
+ 6, // highs, lows, closes, period, kSmooth, dSmooth
118
+ [](jsi::Runtime& rt, const jsi::Value* args, size_t count) -> jsi::Value {
119
+ if (count < 3) {
120
+ throw jsi::JSError(rt, "calculateKDJ requires at least 3 arguments: highs, lows, closes");
121
+ }
122
+
123
+ auto highs = helpers::jsArrayToVector(rt, args[0]);
124
+ auto lows = helpers::jsArrayToVector(rt, args[1]);
125
+ auto closes = helpers::jsArrayToVector(rt, args[2]);
126
+ int period = count > 3 ? static_cast<int>(args[3].asNumber()) : 9;
127
+ int kSmooth = count > 4 ? static_cast<int>(args[4].asNumber()) : 3;
128
+ int dSmooth = count > 5 ? static_cast<int>(args[5].asNumber()) : 3;
129
+
130
+ auto result = indicators::calculateKDJ(highs, lows, closes, period, kSmooth, dSmooth);
131
+ return helpers::kdjResultToJSObject(rt, result);
132
+ }
133
+ );
134
+ }
135
+
136
+ // ========== BOLLINGER BANDS ==========
137
+ if (propName == "calculateBollinger") {
138
+ return jsi::Function::createFromHostFunction(
139
+ runtime,
140
+ name,
141
+ 3, // closes, period, multiplier
142
+ [](jsi::Runtime& rt, const jsi::Value* args, size_t count) -> jsi::Value {
143
+ if (count < 1) {
144
+ throw jsi::JSError(rt, "calculateBollinger requires at least 1 argument: closes");
145
+ }
146
+
147
+ auto closes = helpers::jsArrayToVector(rt, args[0]);
148
+ int period = count > 1 ? static_cast<int>(args[1].asNumber()) : 20;
149
+ double multiplier = count > 2 ? args[2].asNumber() : 2.0;
150
+
151
+ auto result = indicators::calculateBollinger(closes, period, multiplier);
152
+ return helpers::bollingerResultToJSObject(rt, result);
153
+ }
154
+ );
155
+ }
156
+
157
+ // ========== DMI ==========
158
+ if (propName == "calculateDMI") {
159
+ return jsi::Function::createFromHostFunction(
160
+ runtime,
161
+ name,
162
+ 4, // highs, lows, closes, period
163
+ [](jsi::Runtime& rt, const jsi::Value* args, size_t count) -> jsi::Value {
164
+ if (count < 3) {
165
+ throw jsi::JSError(rt, "calculateDMI requires at least 3 arguments: highs, lows, closes");
166
+ }
167
+
168
+ auto highs = helpers::jsArrayToVector(rt, args[0]);
169
+ auto lows = helpers::jsArrayToVector(rt, args[1]);
170
+ auto closes = helpers::jsArrayToVector(rt, args[2]);
171
+ int period = count > 3 ? static_cast<int>(args[3].asNumber()) : 14;
172
+
173
+ auto result = indicators::calculateDMI(highs, lows, closes, period);
174
+ return helpers::dmiResultToJSObject(rt, result);
175
+ }
176
+ );
177
+ }
178
+
179
+ // ========== OBV ==========
180
+ if (propName == "calculateOBV") {
181
+ return jsi::Function::createFromHostFunction(
182
+ runtime,
183
+ name,
184
+ 2, // closes, volumes
185
+ [](jsi::Runtime& rt, const jsi::Value* args, size_t count) -> jsi::Value {
186
+ if (count < 2) {
187
+ throw jsi::JSError(rt, "calculateOBV requires 2 arguments: closes, volumes");
188
+ }
189
+
190
+ auto closes = helpers::jsArrayToVector(rt, args[0]);
191
+ auto volumes = helpers::jsArrayToVector(rt, args[1]);
192
+
193
+ auto result = indicators::calculateOBV(closes, volumes);
194
+ return helpers::vectorToJSArray(rt, result);
195
+ }
196
+ );
197
+ }
198
+
199
+ // ========== CCI ==========
200
+ if (propName == "calculateCCI") {
201
+ return jsi::Function::createFromHostFunction(
202
+ runtime,
203
+ name,
204
+ 4, // highs, lows, closes, period
205
+ [](jsi::Runtime& rt, const jsi::Value* args, size_t count) -> jsi::Value {
206
+ if (count < 3) {
207
+ throw jsi::JSError(rt, "calculateCCI requires at least 3 arguments: highs, lows, closes");
208
+ }
209
+
210
+ auto highs = helpers::jsArrayToVector(rt, args[0]);
211
+ auto lows = helpers::jsArrayToVector(rt, args[1]);
212
+ auto closes = helpers::jsArrayToVector(rt, args[2]);
213
+ int period = count > 3 ? static_cast<int>(args[3].asNumber()) : 20;
214
+
215
+ auto result = indicators::calculateCCI(highs, lows, closes, period);
216
+ return helpers::vectorToJSArray(rt, result);
217
+ }
218
+ );
219
+ }
220
+
221
+ // ========== ATR ==========
222
+ if (propName == "calculateATR") {
223
+ return jsi::Function::createFromHostFunction(
224
+ runtime,
225
+ name,
226
+ 4, // highs, lows, closes, period
227
+ [](jsi::Runtime& rt, const jsi::Value* args, size_t count) -> jsi::Value {
228
+ if (count < 3) {
229
+ throw jsi::JSError(rt, "calculateATR requires at least 3 arguments: highs, lows, closes");
230
+ }
231
+
232
+ auto highs = helpers::jsArrayToVector(rt, args[0]);
233
+ auto lows = helpers::jsArrayToVector(rt, args[1]);
234
+ auto closes = helpers::jsArrayToVector(rt, args[2]);
235
+ int period = count > 3 ? static_cast<int>(args[3].asNumber()) : 14;
236
+
237
+ auto result = indicators::calculateATR(highs, lows, closes, period);
238
+ return helpers::vectorToJSArray(rt, result);
239
+ }
240
+ );
241
+ }
242
+
243
+ // Return undefined for unknown properties
244
+ return jsi::Value::undefined();
245
+ }
246
+
247
+ } // namespace reactnative
248
+ } // namespace chart
249
+
@@ -0,0 +1,35 @@
1
+ // ============================================================================
2
+ // 📄 bindings/react-native/src/ChartModule.h
3
+ // Mục đích: JSI Bridge Module Header for React Native
4
+ // ============================================================================
5
+
6
+ #ifndef CHART_MODULE_H
7
+ #define CHART_MODULE_H
8
+
9
+ #include <jsi/jsi.h>
10
+ #include <memory>
11
+
12
+ using namespace facebook;
13
+
14
+ namespace chart {
15
+ namespace reactnative {
16
+
17
+ // ========================================================================
18
+ // ChartModule: JSI Module for React Native
19
+ // ========================================================================
20
+ class ChartModule : public jsi::HostObject {
21
+ public:
22
+ // Install the module into JSI runtime
23
+ static void install(jsi::Runtime& runtime);
24
+
25
+ // JSI HostObject methods
26
+ jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& name) override;
27
+
28
+ private:
29
+ };
30
+
31
+ } // namespace reactnative
32
+ } // namespace chart
33
+
34
+ #endif // CHART_MODULE_H
35
+