codifx 0.1.5 → 0.1.7
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/dist/cli/index.js +7 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/data/yahoo.d.ts +4 -0
- package/dist/data/yahoo.d.ts.map +1 -1
- package/dist/data/yahoo.js +70 -9
- package/dist/data/yahoo.js.map +1 -1
- package/dist/utils/version-checker.d.ts +14 -0
- package/dist/utils/version-checker.d.ts.map +1 -0
- package/dist/utils/version-checker.js +76 -0
- package/dist/utils/version-checker.js.map +1 -0
- package/package.json +5 -2
- package/templates/dashboard.html +7 -7
package/dist/cli/index.js
CHANGED
|
@@ -10,9 +10,16 @@ import { explainCommand } from "./commands/explain.js";
|
|
|
10
10
|
import { readFileSync } from "fs";
|
|
11
11
|
import { join, dirname } from "path";
|
|
12
12
|
import { fileURLToPath } from "url";
|
|
13
|
+
import { checkForUpdates, displayUpdateNotification, } from "../utils/version-checker.js";
|
|
13
14
|
// Get package version
|
|
14
15
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
16
|
const packageJson = JSON.parse(readFileSync(join(__dirname, "../../package.json"), "utf-8"));
|
|
17
|
+
// Check for updates (async, non-blocking for program setup)
|
|
18
|
+
checkForUpdates(packageJson.version).then((latestVersion) => {
|
|
19
|
+
if (latestVersion) {
|
|
20
|
+
displayUpdateNotification(packageJson.version, latestVersion);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
16
23
|
const program = new Command();
|
|
17
24
|
program
|
|
18
25
|
.name("codifx")
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
package/dist/data/yahoo.d.ts
CHANGED
|
@@ -12,6 +12,10 @@ export declare class YahooFinanceProvider extends BaseDataProvider {
|
|
|
12
12
|
* Convert our timeframe format to Yahoo Finance interval
|
|
13
13
|
*/
|
|
14
14
|
private convertTimeframe;
|
|
15
|
+
/**
|
|
16
|
+
* Validate individual candle for data quality
|
|
17
|
+
*/
|
|
18
|
+
private isValidCandle;
|
|
15
19
|
/**
|
|
16
20
|
* Calculate appropriate period range based on timeframe and limit
|
|
17
21
|
* If targetDate is provided, calculate from that date instead of today
|
package/dist/data/yahoo.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yahoo.d.ts","sourceRoot":"","sources":["../../src/data/yahoo.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEhD,qBAAa,oBAAqB,SAAQ,gBAAgB;IACtD,IAAI,SAAU;IACd,OAAO,CAAC,OAAO,CAAsD;IAE/D,UAAU,CACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,EACpB,KAAK,GAAE,MAAY,EACnB,UAAU,CAAC,EAAE,IAAI,GAClB,OAAO,CAAC,KAAK,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"yahoo.d.ts","sourceRoot":"","sources":["../../src/data/yahoo.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEhD,qBAAa,oBAAqB,SAAQ,gBAAgB;IACtD,IAAI,SAAU;IACd,OAAO,CAAC,OAAO,CAAsD;IAE/D,UAAU,CACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,EACpB,KAAK,GAAE,MAAY,EACnB,UAAU,CAAC,EAAE,IAAI,GAClB,OAAO,CAAC,KAAK,EAAE,CAAC;IAgFb,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAarC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;OAEG;IACH,OAAO,CAAC,aAAa;IAyCrB;;;OAGG;IACH,OAAO,CAAC,eAAe;CA0D1B"}
|
package/dist/data/yahoo.js
CHANGED
|
@@ -21,7 +21,7 @@ export class YahooFinanceProvider extends BaseDataProvider {
|
|
|
21
21
|
const result = response.data.chart.result[0];
|
|
22
22
|
const timestamps = result.timestamp;
|
|
23
23
|
const quote = result.indicators.quote[0];
|
|
24
|
-
const
|
|
24
|
+
const rawData = timestamps.map((timestamp, index) => ({
|
|
25
25
|
timestamp: timestamp * 1000, // Convert to milliseconds
|
|
26
26
|
open: quote.open[index],
|
|
27
27
|
high: quote.high[index],
|
|
@@ -29,20 +29,40 @@ export class YahooFinanceProvider extends BaseDataProvider {
|
|
|
29
29
|
close: quote.close[index],
|
|
30
30
|
volume: quote.volume[index],
|
|
31
31
|
}));
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
const validData = rawData
|
|
33
|
+
.filter((item) => {
|
|
34
|
+
return (item.timestamp !== null &&
|
|
35
|
+
item.close !== null &&
|
|
36
|
+
item.open !== null &&
|
|
37
|
+
item.high !== null &&
|
|
38
|
+
item.low !== null &&
|
|
39
|
+
item.volume !== null);
|
|
40
|
+
})
|
|
41
|
+
.map((item) => ({
|
|
42
|
+
timestamp: item.timestamp,
|
|
43
|
+
open: item.open,
|
|
44
|
+
close: item.close,
|
|
45
|
+
high: item.high,
|
|
46
|
+
low: item.low,
|
|
47
|
+
volume: item.volume,
|
|
48
|
+
}))
|
|
49
|
+
.filter((candle) => this.isValidCandle(candle));
|
|
50
|
+
// Ensure we have enough valid data (at least 80% of requested)
|
|
51
|
+
const minRequired = Math.floor(limit * 0.8);
|
|
52
|
+
if (validData.length < minRequired) {
|
|
53
|
+
throw new Error(`Insufficient valid data: only ${validData.length}/${limit} candles are valid. ` +
|
|
54
|
+
`Market may be closed or data quality is poor.`);
|
|
55
|
+
}
|
|
37
56
|
// Filter by targetDate if provided
|
|
57
|
+
let filteredData = validData;
|
|
38
58
|
if (targetDate) {
|
|
39
59
|
const maxTimestamp = targetDate.getTime();
|
|
40
|
-
|
|
60
|
+
filteredData = validData.filter((candle) => candle.timestamp <= maxTimestamp);
|
|
41
61
|
}
|
|
42
|
-
if (!this.validateData(
|
|
62
|
+
if (!this.validateData(filteredData)) {
|
|
43
63
|
throw new Error("Invalid data received from Yahoo Finance");
|
|
44
64
|
}
|
|
45
|
-
return this.sortData(
|
|
65
|
+
return this.sortData(filteredData).slice(-limit);
|
|
46
66
|
}
|
|
47
67
|
catch (error) {
|
|
48
68
|
if (axios.isAxiosError(error)) {
|
|
@@ -77,6 +97,47 @@ export class YahooFinanceProvider extends BaseDataProvider {
|
|
|
77
97
|
};
|
|
78
98
|
return mapping[timeframe];
|
|
79
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Validate individual candle for data quality
|
|
102
|
+
*/
|
|
103
|
+
isValidCandle(candle) {
|
|
104
|
+
// Check all values are valid numbers
|
|
105
|
+
if (typeof candle.timestamp !== "number" ||
|
|
106
|
+
typeof candle.open !== "number" ||
|
|
107
|
+
isNaN(candle.open) ||
|
|
108
|
+
typeof candle.close !== "number" ||
|
|
109
|
+
isNaN(candle.close) ||
|
|
110
|
+
typeof candle.high !== "number" ||
|
|
111
|
+
isNaN(candle.high) ||
|
|
112
|
+
typeof candle.low !== "number" ||
|
|
113
|
+
isNaN(candle.low) ||
|
|
114
|
+
typeof candle.volume !== "number" ||
|
|
115
|
+
isNaN(candle.volume)) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
// Sanity checks for OHLC relationships
|
|
119
|
+
if (candle.high < candle.low)
|
|
120
|
+
return false;
|
|
121
|
+
if (candle.high < candle.open)
|
|
122
|
+
return false;
|
|
123
|
+
if (candle.high < candle.close)
|
|
124
|
+
return false;
|
|
125
|
+
if (candle.low > candle.open)
|
|
126
|
+
return false;
|
|
127
|
+
if (candle.low > candle.close)
|
|
128
|
+
return false;
|
|
129
|
+
// Volume should be non-negative
|
|
130
|
+
if (candle.volume < 0)
|
|
131
|
+
return false;
|
|
132
|
+
// All prices should be positive
|
|
133
|
+
if (candle.open <= 0 ||
|
|
134
|
+
candle.close <= 0 ||
|
|
135
|
+
candle.high <= 0 ||
|
|
136
|
+
candle.low <= 0) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
80
141
|
/**
|
|
81
142
|
* Calculate appropriate period range based on timeframe and limit
|
|
82
143
|
* If targetDate is provided, calculate from that date instead of today
|
package/dist/data/yahoo.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yahoo.js","sourceRoot":"","sources":["../../src/data/yahoo.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEhD,MAAM,OAAO,oBAAqB,SAAQ,gBAAgB;IACtD,IAAI,GAAG,OAAO,CAAA;IACN,OAAO,GAAG,mDAAmD,CAAA;IAErE,KAAK,CAAC,UAAU,CACZ,MAAc,EACd,SAAoB,EACpB,QAAgB,GAAG,EACnB,UAAiB;QAEjB,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAA;YACjD,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,KAAK,EAAE,UAAU,CAAC,CAAA;YACjE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,IAAI,MAAM,EAAE,CAAA;YACvC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE;gBAClC,MAAM,EAAE;oBACJ,QAAQ;oBACR,KAAK,EAAE,MAAM;iBAChB;gBACD,OAAO,EAAE,KAAK;aACjB,CAAC,CAAA;YAEF,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;YAC5C,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAA;YACnC,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;YAExC,MAAM,
|
|
1
|
+
{"version":3,"file":"yahoo.js","sourceRoot":"","sources":["../../src/data/yahoo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version checker utility
|
|
3
|
+
* Checks if installed version is outdated compared to npm registry
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Check if update is available
|
|
7
|
+
* Returns latest version if update needed, null otherwise
|
|
8
|
+
*/
|
|
9
|
+
export declare function checkForUpdates(currentVersion: string): Promise<string | null>;
|
|
10
|
+
/**
|
|
11
|
+
* Display update notification and exit
|
|
12
|
+
*/
|
|
13
|
+
export declare function displayUpdateNotification(currentVersion: string, latestVersion: string): void;
|
|
14
|
+
//# sourceMappingURL=version-checker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-checker.d.ts","sourceRoot":"","sources":["../../src/utils/version-checker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA0CH;;;GAGG;AACH,wBAAsB,eAAe,CACjC,cAAc,EAAE,MAAM,GACvB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcxB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACrC,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,MAAM,GACtB,IAAI,CAoBN"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version checker utility
|
|
3
|
+
* Checks if installed version is outdated compared to npm registry
|
|
4
|
+
*/
|
|
5
|
+
import axios from "axios";
|
|
6
|
+
const PACKAGE_NAME = "codifx";
|
|
7
|
+
const CHECK_TIMEOUT = 3000; // 3 seconds timeout
|
|
8
|
+
/**
|
|
9
|
+
* Compare two semver versions
|
|
10
|
+
* Returns: 1 if v1 > v2, -1 if v1 < v2, 0 if equal
|
|
11
|
+
*/
|
|
12
|
+
function compareVersions(v1, v2) {
|
|
13
|
+
const parts1 = v1.split(".").map(Number);
|
|
14
|
+
const parts2 = v2.split(".").map(Number);
|
|
15
|
+
for (let i = 0; i < 3; i++) {
|
|
16
|
+
const num1 = parts1[i] || 0;
|
|
17
|
+
const num2 = parts2[i] || 0;
|
|
18
|
+
if (num1 > num2)
|
|
19
|
+
return 1;
|
|
20
|
+
if (num1 < num2)
|
|
21
|
+
return -1;
|
|
22
|
+
}
|
|
23
|
+
return 0;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get latest version from npm registry
|
|
27
|
+
*/
|
|
28
|
+
async function getLatestVersion() {
|
|
29
|
+
try {
|
|
30
|
+
const response = await axios.get(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, { timeout: CHECK_TIMEOUT });
|
|
31
|
+
return response.data.version;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Silently fail if can't reach npm (offline, timeout, etc)
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Check if update is available
|
|
40
|
+
* Returns latest version if update needed, null otherwise
|
|
41
|
+
*/
|
|
42
|
+
export async function checkForUpdates(currentVersion) {
|
|
43
|
+
const latestVersion = await getLatestVersion();
|
|
44
|
+
if (!latestVersion) {
|
|
45
|
+
return null; // Can't check, skip
|
|
46
|
+
}
|
|
47
|
+
const comparison = compareVersions(latestVersion, currentVersion);
|
|
48
|
+
if (comparison > 0) {
|
|
49
|
+
return latestVersion; // Update available
|
|
50
|
+
}
|
|
51
|
+
return null; // Up to date
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Display update notification and exit
|
|
55
|
+
*/
|
|
56
|
+
export function displayUpdateNotification(currentVersion, latestVersion) {
|
|
57
|
+
console.log("");
|
|
58
|
+
console.log("╔═══════════════════════════════════════════════════════╗");
|
|
59
|
+
console.log("║ ║");
|
|
60
|
+
console.log("║ 🚀 UPDATE AVAILABLE FOR CODIFX! 🚀 ║");
|
|
61
|
+
console.log("║ ║");
|
|
62
|
+
console.log("╠═══════════════════════════════════════════════════════╣");
|
|
63
|
+
console.log(`║ Current version: v${currentVersion.padEnd(30)} ║`);
|
|
64
|
+
console.log(`║ Latest version: v${latestVersion.padEnd(30)} ║`);
|
|
65
|
+
console.log("║ ║");
|
|
66
|
+
console.log("║ Update now to get the latest features and fixes! ║");
|
|
67
|
+
console.log("║ ║");
|
|
68
|
+
console.log("║ Run: npm update -g codifx ║");
|
|
69
|
+
console.log("║ ║");
|
|
70
|
+
console.log("╚═══════════════════════════════════════════════════════╝");
|
|
71
|
+
console.log("");
|
|
72
|
+
console.log("⚠️ Please update before continuing to ensure compatibility.");
|
|
73
|
+
console.log("");
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=version-checker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-checker.js","sourceRoot":"","sources":["../../src/utils/version-checker.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codifx",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Professional multi-type trading scanner CLI supporting scalping, day trading, and swing trading",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
"dev": "tsc --watch",
|
|
23
23
|
"start": "node bin/codifx.js",
|
|
24
24
|
"clean": "rm -rf dist",
|
|
25
|
-
"prepublishOnly": "npm run clean && npm run build"
|
|
25
|
+
"prepublishOnly": "npm run clean && npm run build",
|
|
26
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
27
|
+
"publish:package": "bash scripts/publish.sh"
|
|
26
28
|
},
|
|
27
29
|
"keywords": [
|
|
28
30
|
"trading",
|
|
@@ -65,6 +67,7 @@
|
|
|
65
67
|
"devDependencies": {
|
|
66
68
|
"@types/cli-progress": "^3.11.6",
|
|
67
69
|
"@types/node": "^20.10.0",
|
|
70
|
+
"javascript-obfuscator": "^5.1.0",
|
|
68
71
|
"typescript": "^5.3.0"
|
|
69
72
|
}
|
|
70
73
|
}
|
package/templates/dashboard.html
CHANGED
|
@@ -362,15 +362,15 @@
|
|
|
362
362
|
<div class="grid grid-cols-2 gap-3 text-sm">
|
|
363
363
|
<div>
|
|
364
364
|
<span class="text-gray-600">Entry:</span>
|
|
365
|
-
<span class="font-bold text-gray-800">Rp ${stock.entry.toLocaleString('id-ID')}</span>
|
|
365
|
+
<span class="font-bold text-gray-800">Rp ${Math.round(stock.entry).toLocaleString('id-ID')}</span>
|
|
366
366
|
</div>
|
|
367
367
|
<div>
|
|
368
368
|
<span class="text-gray-600">Stop Loss:</span>
|
|
369
|
-
<span class="font-bold text-red-600">Rp ${stock.stopLoss.toLocaleString('id-ID')}</span>
|
|
369
|
+
<span class="font-bold text-red-600">Rp ${Math.round(stock.stopLoss).toLocaleString('id-ID')}</span>
|
|
370
370
|
</div>
|
|
371
371
|
<div>
|
|
372
372
|
<span class="text-gray-600">Take Profit:</span>
|
|
373
|
-
<span class="font-bold text-green-600">Rp ${stock.takeProfit.toLocaleString('id-ID')}</span>
|
|
373
|
+
<span class="font-bold text-green-600">Rp ${Math.round(stock.takeProfit).toLocaleString('id-ID')}</span>
|
|
374
374
|
</div>
|
|
375
375
|
<div>
|
|
376
376
|
<span class="text-gray-600">Risk/Reward:</span>
|
|
@@ -378,11 +378,11 @@
|
|
|
378
378
|
</div>
|
|
379
379
|
<div>
|
|
380
380
|
<span class="text-gray-600">Support:</span>
|
|
381
|
-
<span class="font-bold text-gray-800">Rp ${stock.support.toLocaleString('id-ID')}</span>
|
|
381
|
+
<span class="font-bold text-gray-800">Rp ${Math.round(stock.support).toLocaleString('id-ID')}</span>
|
|
382
382
|
</div>
|
|
383
383
|
<div>
|
|
384
384
|
<span class="text-gray-600">Resistance:</span>
|
|
385
|
-
<span class="font-bold text-gray-800">Rp ${stock.resistance.toLocaleString('id-ID')}</span>
|
|
385
|
+
<span class="font-bold text-gray-800">Rp ${Math.round(stock.resistance).toLocaleString('id-ID')}</span>
|
|
386
386
|
</div>
|
|
387
387
|
</div>
|
|
388
388
|
</div>
|
|
@@ -397,8 +397,8 @@
|
|
|
397
397
|
<p class="text-sm text-gray-700">
|
|
398
398
|
💡 <strong>Recommendation:</strong> ${
|
|
399
399
|
stock.direction === 'BUY'
|
|
400
|
-
? `Consider entering at Rp ${stock.entry.toLocaleString('id-ID')} with stop loss at Rp ${stock.stopLoss.toLocaleString('id-ID')} and take profit at Rp ${stock.takeProfit.toLocaleString('id-ID')}.`
|
|
401
|
-
: `Consider short entry at Rp ${stock.entry.toLocaleString('id-ID')} with stop loss at Rp ${stock.stopLoss.toLocaleString('id-ID')} and take profit at Rp ${stock.takeProfit.toLocaleString('id-ID')}.`
|
|
400
|
+
? `Consider entering at Rp ${Math.round(stock.entry).toLocaleString('id-ID')} with stop loss at Rp ${Math.round(stock.stopLoss).toLocaleString('id-ID')} and take profit at Rp ${Math.round(stock.takeProfit).toLocaleString('id-ID')}.`
|
|
401
|
+
: `Consider short entry at Rp ${Math.round(stock.entry).toLocaleString('id-ID')} with stop loss at Rp ${Math.round(stock.stopLoss).toLocaleString('id-ID')} and take profit at Rp ${Math.round(stock.takeProfit).toLocaleString('id-ID')}.`
|
|
402
402
|
}
|
|
403
403
|
</p>
|
|
404
404
|
</div>
|