ohlcv-indicators 1.0.3 → 1.0.4
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/package.json +1 -1
- package/src/studies/volumeProfile.js +37 -18
- package/test/test.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ohlcv-indicators",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "A JavaScript library featuring optimized trading indicators for OHLCV arrays [{open, high, low, close, value}], utilizing BigNumber precision for enhanced accuracy.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -1,45 +1,64 @@
|
|
|
1
|
-
//volume profile can not be concatenated to the main class
|
|
2
|
-
|
|
3
1
|
export const VolumeProfile = (BigNumber, ohlcv, numBins = 10) => {
|
|
4
|
-
|
|
5
2
|
const { open, high, low, close, volume } = ohlcv;
|
|
6
3
|
|
|
7
4
|
// Determine the range of prices
|
|
8
5
|
const lowPrice = BigNumber.min(...low);
|
|
9
6
|
const highPrice = BigNumber.max(...high);
|
|
10
7
|
const binSize = highPrice.minus(lowPrice).dividedBy(numBins);
|
|
8
|
+
const zero = BigNumber(0);
|
|
9
|
+
|
|
10
|
+
// Initialize totals
|
|
11
|
+
const totals = {
|
|
12
|
+
upVolume: zero,
|
|
13
|
+
downVolume: zero,
|
|
14
|
+
grossVolume: zero,
|
|
15
|
+
};
|
|
11
16
|
|
|
12
17
|
// Initialize bins
|
|
13
18
|
const bins = Array.from({ length: numBins }, (_, i) => ({
|
|
14
19
|
price: lowPrice.plus(binSize.multipliedBy(i)),
|
|
15
|
-
upVolume:
|
|
16
|
-
downVolume:
|
|
20
|
+
upVolume: zero,
|
|
21
|
+
downVolume: zero,
|
|
22
|
+
grossVolume: zero,
|
|
17
23
|
}));
|
|
18
24
|
|
|
19
25
|
// Precompute binSize inversely to use multiplication instead of division in the loop
|
|
20
|
-
const inverseBinSize =
|
|
26
|
+
const inverseBinSize = BigNumber(1).dividedBy(binSize);
|
|
21
27
|
|
|
22
28
|
// Distribute volume into bins
|
|
23
|
-
|
|
24
|
-
for (let i = 0; i < numDataPoints; i++) {
|
|
29
|
+
close.forEach((currentClose, i) => {
|
|
25
30
|
const currentOpen = open[i];
|
|
26
31
|
const currentHigh = high[i];
|
|
27
32
|
const currentLow = low[i];
|
|
28
|
-
const currentClose = close[i];
|
|
29
33
|
const currentVolume = volume[i];
|
|
30
34
|
|
|
31
|
-
const upVolume = currentClose.isGreaterThanOrEqualTo(currentOpen) ? currentVolume :
|
|
32
|
-
const downVolume = currentClose.isLessThan(currentOpen) ? currentVolume :
|
|
35
|
+
const upVolume = currentClose.isGreaterThanOrEqualTo(currentOpen) ? currentVolume : zero;
|
|
36
|
+
const downVolume = currentClose.isLessThan(currentOpen) ? currentVolume : zero;
|
|
33
37
|
|
|
34
|
-
const lowIndex = currentLow.minus(lowPrice).multipliedBy(inverseBinSize).integerValue(BigNumber.ROUND_FLOOR).toNumber();
|
|
35
|
-
const highIndex = currentHigh.minus(lowPrice).multipliedBy(inverseBinSize).integerValue(BigNumber.ROUND_CEIL).toNumber();
|
|
38
|
+
const lowIndex = Math.max(0, currentLow.minus(lowPrice).multipliedBy(inverseBinSize).integerValue(BigNumber.ROUND_FLOOR).toNumber());
|
|
39
|
+
const highIndex = Math.min(numBins, currentHigh.minus(lowPrice).multipliedBy(inverseBinSize).integerValue(BigNumber.ROUND_CEIL).toNumber());
|
|
36
40
|
|
|
37
|
-
for (let j =
|
|
41
|
+
for (let j = lowIndex; j < highIndex; j++) {
|
|
38
42
|
bins[j].upVolume = bins[j].upVolume.plus(upVolume);
|
|
39
43
|
bins[j].downVolume = bins[j].downVolume.plus(downVolume);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
44
|
+
bins[j].grossVolume = bins[j].upVolume.plus(bins[j].downVolume); }
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Sum totals outside the loop
|
|
48
|
+
bins.forEach(({ upVolume, downVolume, grossVolume, netVolume }) => {
|
|
49
|
+
totals.upVolume = totals.upVolume.plus(upVolume);
|
|
50
|
+
totals.downVolume = totals.downVolume.plus(downVolume);
|
|
51
|
+
totals.grossVolume = totals.grossVolume.plus(grossVolume);
|
|
52
|
+
});
|
|
42
53
|
|
|
43
|
-
|
|
54
|
+
// Calculate percentage volumes
|
|
55
|
+
bins.forEach(bin => {
|
|
56
|
+
Object.keys(totals).forEach(k => {
|
|
57
|
+
if (!totals[k].isZero()) {
|
|
58
|
+
bin[`${k}Percent`] = (bin[k].dividedBy(totals[k])).times(100);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
});
|
|
44
62
|
|
|
45
|
-
|
|
63
|
+
return bins;
|
|
64
|
+
};
|
package/test/test.js
CHANGED
|
@@ -24,7 +24,7 @@ const TEST = async () => {
|
|
|
24
24
|
//.crossPairs([{fast: 'ema_9', slow: 'ema_21'}, {fast: 'close', slow: 'sma_200'}, {fast: 'rsi_14', slow: 30}])
|
|
25
25
|
|
|
26
26
|
const dataSet = indicators.getData()
|
|
27
|
-
const vp = VolumeProfile(BigNumber, dataSet)
|
|
27
|
+
const vp = VolumeProfile(BigNumber, dataSet, 5)
|
|
28
28
|
|
|
29
29
|
console.log(vp)
|
|
30
30
|
|