@ch20026103/anysis 0.0.19 → 0.0.20-alpha.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/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/stockSkills/cmf.d.ts +11 -0
- package/dist/cjs/stockSkills/cmf.js +90 -0
- package/dist/cjs/stockSkills/cmf.test.d.ts +1 -0
- package/dist/cjs/stockSkills/cmf.test.js +77 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/stockSkills/cmf.d.ts +11 -0
- package/dist/esm/stockSkills/cmf.js +88 -0
- package/dist/esm/stockSkills/cmf.test.d.ts +1 -0
- package/dist/esm/stockSkills/cmf.test.js +75 -0
- package/dist/umd/index.js +93 -4
- package/package.json +1 -1
package/dist/cjs/index.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export { default as ObvEma } from "./stockSkills/obv_ema.js";
|
|
|
22
22
|
export { default as Mfi } from "./stockSkills/mfi.js";
|
|
23
23
|
export { default as Ichimoku } from "./stockSkills/ichimoku.js";
|
|
24
24
|
export { default as Dmi } from "./stockSkills/dmi.js";
|
|
25
|
+
export { default as Cmf } from "./stockSkills/cmf.js";
|
|
25
26
|
export { add } from "./test/add.js";
|
|
26
27
|
export { minus } from "./test/minus.js";
|
|
27
28
|
export { default as calculateDivisionFactor } from "./utils/calculateDivisionFactor.js";
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseLsusbOutput = exports.isJSON = exports.calculateDivisionFactor = exports.minus = exports.add = exports.Dmi = exports.Ichimoku = exports.Mfi = exports.ObvEma = exports.Williams = exports.Vma = exports.Week = exports.dateFormat = exports.Rsi = exports.Obv = exports.Macd = exports.Ma = exports.Kd = exports.Gold = exports.Ema = exports.Boll = exports.calcSeasonalIndicesNoTrend = exports.weightMovingAverages = exports.movingAverages = exports.exponentialSmoothing = exports.findTroughByGradient = exports.findPeaksByGradient = exports.SwingExtremesType = exports.SwingExtremes = exports.slope = exports.simpleRegressionModel = exports.Angle = void 0;
|
|
3
|
+
exports.parseLsusbOutput = exports.isJSON = exports.calculateDivisionFactor = exports.minus = exports.add = exports.Cmf = exports.Dmi = exports.Ichimoku = exports.Mfi = exports.ObvEma = exports.Williams = exports.Vma = exports.Week = exports.dateFormat = exports.Rsi = exports.Obv = exports.Macd = exports.Ma = exports.Kd = exports.Gold = exports.Ema = exports.Boll = exports.calcSeasonalIndicesNoTrend = exports.weightMovingAverages = exports.movingAverages = exports.exponentialSmoothing = exports.findTroughByGradient = exports.findPeaksByGradient = exports.SwingExtremesType = exports.SwingExtremes = exports.slope = exports.simpleRegressionModel = exports.Angle = void 0;
|
|
4
4
|
/*
|
|
5
5
|
請注意,在 src/index.ts 中,我的導入包含文件擴展名(.js)。
|
|
6
6
|
如果需要支持 Node.js 和構建工具(ex: webpack),則不需要這樣做。 **因為commonJs默認js副檔名**
|
|
@@ -55,6 +55,8 @@ var ichimoku_js_1 = require("./stockSkills/ichimoku.js");
|
|
|
55
55
|
Object.defineProperty(exports, "Ichimoku", { enumerable: true, get: function () { return ichimoku_js_1.default; } });
|
|
56
56
|
var dmi_js_1 = require("./stockSkills/dmi.js");
|
|
57
57
|
Object.defineProperty(exports, "Dmi", { enumerable: true, get: function () { return dmi_js_1.default; } });
|
|
58
|
+
var cmf_js_1 = require("./stockSkills/cmf.js");
|
|
59
|
+
Object.defineProperty(exports, "Cmf", { enumerable: true, get: function () { return cmf_js_1.default; } });
|
|
58
60
|
var add_js_1 = require("./test/add.js");
|
|
59
61
|
Object.defineProperty(exports, "add", { enumerable: true, get: function () { return add_js_1.add; } });
|
|
60
62
|
var minus_js_1 = require("./test/minus.js");
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { StockListType, StockType } from "./types";
|
|
2
|
+
export type CmfResType = {
|
|
3
|
+
dataset: StockListType;
|
|
4
|
+
cmf: number;
|
|
5
|
+
ema: number;
|
|
6
|
+
cmfList: number[];
|
|
7
|
+
};
|
|
8
|
+
export default class Cmf {
|
|
9
|
+
init(data: StockType): CmfResType;
|
|
10
|
+
next(data: StockType, preList: CmfResType, period?: number, emaPeriod?: number): CmfResType;
|
|
11
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
3
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
4
|
+
if (ar || !(i in from)) {
|
|
5
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
6
|
+
ar[i] = from[i];
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
var Cmf = /** @class */ (function () {
|
|
13
|
+
function Cmf() {
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(Cmf.prototype, "init", {
|
|
16
|
+
enumerable: false,
|
|
17
|
+
configurable: true,
|
|
18
|
+
writable: true,
|
|
19
|
+
value: function (data) {
|
|
20
|
+
return {
|
|
21
|
+
dataset: [data],
|
|
22
|
+
cmf: 0,
|
|
23
|
+
ema: 0,
|
|
24
|
+
cmfList: [],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(Cmf.prototype, "next", {
|
|
29
|
+
enumerable: false,
|
|
30
|
+
configurable: true,
|
|
31
|
+
writable: true,
|
|
32
|
+
value: function (data, preList, period, emaPeriod) {
|
|
33
|
+
if (period === void 0) { period = 20; }
|
|
34
|
+
if (emaPeriod === void 0) { emaPeriod = 10; }
|
|
35
|
+
preList.dataset.push(data);
|
|
36
|
+
if (preList.dataset.length > period) {
|
|
37
|
+
preList.dataset.shift();
|
|
38
|
+
}
|
|
39
|
+
var cmf = 0;
|
|
40
|
+
// Calculate CMF
|
|
41
|
+
if (preList.dataset.length === period) {
|
|
42
|
+
var sumMfVol = 0;
|
|
43
|
+
var sumVol = 0;
|
|
44
|
+
for (var i = 0; i < preList.dataset.length; i++) {
|
|
45
|
+
var item = preList.dataset[i];
|
|
46
|
+
var h = item.h;
|
|
47
|
+
var l = item.l;
|
|
48
|
+
var c = item.c;
|
|
49
|
+
var v = item.v;
|
|
50
|
+
if (h === l) {
|
|
51
|
+
sumVol += v;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
var multiplier = (c - l - (h - c)) / (h - l);
|
|
55
|
+
var mfVol = multiplier * v;
|
|
56
|
+
sumMfVol += mfVol;
|
|
57
|
+
sumVol += v;
|
|
58
|
+
}
|
|
59
|
+
if (sumVol !== 0) {
|
|
60
|
+
cmf = sumMfVol / sumVol;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Calculate EMA of CMF
|
|
64
|
+
var ema = preList.ema;
|
|
65
|
+
var cmfList = __spreadArray([], preList.cmfList, true);
|
|
66
|
+
// Use current 'cmf' only if we had enough data for it (dataset.length === period)
|
|
67
|
+
if (preList.dataset.length === period) {
|
|
68
|
+
cmfList.push(cmf);
|
|
69
|
+
}
|
|
70
|
+
if (cmfList.length === emaPeriod) {
|
|
71
|
+
// First time we have enough data to calculate EMA (SMA seed)
|
|
72
|
+
var sum = cmfList.reduce(function (pre, current) { return pre + current; }, 0);
|
|
73
|
+
ema = sum / emaPeriod;
|
|
74
|
+
}
|
|
75
|
+
else if (cmfList.length > emaPeriod) {
|
|
76
|
+
cmfList.shift();
|
|
77
|
+
// EMA formula: (Current * 2 + (period - 1) * PreviousEMA) / (period + 1)
|
|
78
|
+
ema = (cmf * 2 + (emaPeriod - 1) * preList.ema) / (emaPeriod + 1);
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
dataset: preList.dataset,
|
|
82
|
+
cmf: cmf,
|
|
83
|
+
ema: ema,
|
|
84
|
+
cmfList: cmfList,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return Cmf;
|
|
89
|
+
}());
|
|
90
|
+
exports.default = Cmf;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var cmf_1 = require("./cmf");
|
|
4
|
+
describe("test Cmf methods", function () {
|
|
5
|
+
it("test CMF calculation with simple data (All Bullish)", function () {
|
|
6
|
+
var cmf = new cmf_1.default();
|
|
7
|
+
var period = 3;
|
|
8
|
+
// Data Case 1: Max positive MF
|
|
9
|
+
// H=10, L=0, C=10 => (10-0)-(10-10) = 10, Multiplier = 10/10 = 1.
|
|
10
|
+
var d1 = { c: 10, h: 10, l: 0, v: 100, o: 5, t: 1 };
|
|
11
|
+
var state = cmf.init(d1);
|
|
12
|
+
// Step 1: length 1 < 3. CMF = 0
|
|
13
|
+
expect(state.cmf).toBe(0);
|
|
14
|
+
state = cmf.next(d1, state, period); // length 2
|
|
15
|
+
expect(state.cmf).toBe(0);
|
|
16
|
+
state = cmf.next(d1, state, period); // length 3. SumMFV = 300, SumV = 300. CMF = 1.
|
|
17
|
+
expect(state.cmf).toBe(1);
|
|
18
|
+
});
|
|
19
|
+
it("test CMF calculation with mixed data", function () {
|
|
20
|
+
var cmf = new cmf_1.default();
|
|
21
|
+
var period = 3;
|
|
22
|
+
// Day 1: Mul=1, V=100 -> MFV=100
|
|
23
|
+
var d1 = { c: 10, h: 10, l: 0, v: 100, o: 5, t: 1 };
|
|
24
|
+
// Day 2: Mul=-1, V=100 -> MFV=-100. (C=0, H=10, L=0 => -10 / 10 = -1)
|
|
25
|
+
var d2 = { c: 0, h: 10, l: 0, v: 100, o: 5, t: 2 };
|
|
26
|
+
// Day 3: Mul=0, V=100 -> MFV=0. (C=5, H=10, L=0 => (5-0)-(10-5)=0)
|
|
27
|
+
var d3 = { c: 5, h: 10, l: 0, v: 100, o: 5, t: 3 };
|
|
28
|
+
var state = cmf.init(d1);
|
|
29
|
+
state = cmf.next(d2, state, period);
|
|
30
|
+
state = cmf.next(d3, state, period);
|
|
31
|
+
// Sum MFV = 100 - 100 + 0 = 0. CMF = 0.
|
|
32
|
+
expect(state.cmf).toBe(0);
|
|
33
|
+
});
|
|
34
|
+
it("test CMF EMA calculation", function () {
|
|
35
|
+
var instance = new cmf_1.default();
|
|
36
|
+
var period = 2;
|
|
37
|
+
var emaPeriod = 3;
|
|
38
|
+
// d1: CMF -> 0 (len 1)
|
|
39
|
+
var d1 = { c: 10, h: 10, l: 0, v: 100, o: 5, t: 1 };
|
|
40
|
+
var state = instance.init(d1);
|
|
41
|
+
// CMF undefined yet (0)
|
|
42
|
+
expect(state.cmf).toBe(0);
|
|
43
|
+
expect(state.ema).toBe(0);
|
|
44
|
+
// d2: CMF -> 1. (len 2). MFV=100+100=200, Vol=200.
|
|
45
|
+
var d2 = { c: 10, h: 10, l: 0, v: 100, o: 5, t: 2 };
|
|
46
|
+
state = instance.next(d2, state, period, emaPeriod);
|
|
47
|
+
expect(state.cmf).toBe(1);
|
|
48
|
+
// EMA calc: cmfList = [1]. len=1 < 3. ema=0.
|
|
49
|
+
expect(state.ema).toBe(0);
|
|
50
|
+
// d3: CMF -> 1. (len 2 shift). MFV=100+100=200.
|
|
51
|
+
var d3 = { c: 10, h: 10, l: 0, v: 100, o: 5, t: 3 };
|
|
52
|
+
state = instance.next(d3, state, period, emaPeriod);
|
|
53
|
+
expect(state.cmf).toBe(1);
|
|
54
|
+
// EMA calc: cmfList = [1, 1]. len=2 < 3. ema=0.
|
|
55
|
+
expect(state.ema).toBe(0);
|
|
56
|
+
// d4: CMF -> 1.
|
|
57
|
+
var d4 = { c: 10, h: 10, l: 0, v: 100, o: 5, t: 4 };
|
|
58
|
+
state = instance.next(d4, state, period, emaPeriod);
|
|
59
|
+
expect(state.cmf).toBe(1);
|
|
60
|
+
// EMA calc: cmfList = [1, 1, 1]. len=3. SMA = 1.
|
|
61
|
+
expect(state.ema).toBe(1);
|
|
62
|
+
// d5: CMF -> 2? No, let's make CMF different.
|
|
63
|
+
// period=2. window [d4, d5].
|
|
64
|
+
// d4: MFV=100, V=100.
|
|
65
|
+
// d5: c=0, h=10, l=0, v=100. mul=-1. MFV=-100.
|
|
66
|
+
// SumMFV = 100 - 100 = 0. CMF = 0.
|
|
67
|
+
var d5 = { c: 0, h: 10, l: 0, v: 100, o: 5, t: 5 };
|
|
68
|
+
state = instance.next(d5, state, period, emaPeriod);
|
|
69
|
+
expect(state.cmf).toBe(0);
|
|
70
|
+
// EMA calc: cmfList was [1, 1, 1]. Pushed 0 -> [1, 1, 1, 0]. Shift -> [1, 1, 0].
|
|
71
|
+
// Wait, implementation:
|
|
72
|
+
// push cmf -> [1, 1, 1, 0]
|
|
73
|
+
// if len > emaPeriod -> shift -> [1, 1, 0]
|
|
74
|
+
// EMA = (0 * 2 + (3-1) * 1) / (3+1) = (0 + 2) / 4 = 0.5.
|
|
75
|
+
expect(state.ema).toBe(0.5);
|
|
76
|
+
});
|
|
77
|
+
});
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export { default as ObvEma } from "./stockSkills/obv_ema.js";
|
|
|
22
22
|
export { default as Mfi } from "./stockSkills/mfi.js";
|
|
23
23
|
export { default as Ichimoku } from "./stockSkills/ichimoku.js";
|
|
24
24
|
export { default as Dmi } from "./stockSkills/dmi.js";
|
|
25
|
+
export { default as Cmf } from "./stockSkills/cmf.js";
|
|
25
26
|
export { add } from "./test/add.js";
|
|
26
27
|
export { minus } from "./test/minus.js";
|
|
27
28
|
export { default as calculateDivisionFactor } from "./utils/calculateDivisionFactor.js";
|
package/dist/esm/index.js
CHANGED
|
@@ -25,6 +25,7 @@ export { default as ObvEma } from "./stockSkills/obv_ema.js";
|
|
|
25
25
|
export { default as Mfi } from "./stockSkills/mfi.js";
|
|
26
26
|
export { default as Ichimoku } from "./stockSkills/ichimoku.js";
|
|
27
27
|
export { default as Dmi } from "./stockSkills/dmi.js";
|
|
28
|
+
export { default as Cmf } from "./stockSkills/cmf.js";
|
|
28
29
|
export { add } from "./test/add.js";
|
|
29
30
|
export { minus } from "./test/minus.js";
|
|
30
31
|
export { default as calculateDivisionFactor } from "./utils/calculateDivisionFactor.js";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { StockListType, StockType } from "./types";
|
|
2
|
+
export type CmfResType = {
|
|
3
|
+
dataset: StockListType;
|
|
4
|
+
cmf: number;
|
|
5
|
+
ema: number;
|
|
6
|
+
cmfList: number[];
|
|
7
|
+
};
|
|
8
|
+
export default class Cmf {
|
|
9
|
+
init(data: StockType): CmfResType;
|
|
10
|
+
next(data: StockType, preList: CmfResType, period?: number, emaPeriod?: number): CmfResType;
|
|
11
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
2
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
3
|
+
if (ar || !(i in from)) {
|
|
4
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
5
|
+
ar[i] = from[i];
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
9
|
+
};
|
|
10
|
+
var Cmf = /** @class */ (function () {
|
|
11
|
+
function Cmf() {
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(Cmf.prototype, "init", {
|
|
14
|
+
enumerable: false,
|
|
15
|
+
configurable: true,
|
|
16
|
+
writable: true,
|
|
17
|
+
value: function (data) {
|
|
18
|
+
return {
|
|
19
|
+
dataset: [data],
|
|
20
|
+
cmf: 0,
|
|
21
|
+
ema: 0,
|
|
22
|
+
cmfList: [],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
Object.defineProperty(Cmf.prototype, "next", {
|
|
27
|
+
enumerable: false,
|
|
28
|
+
configurable: true,
|
|
29
|
+
writable: true,
|
|
30
|
+
value: function (data, preList, period, emaPeriod) {
|
|
31
|
+
if (period === void 0) { period = 20; }
|
|
32
|
+
if (emaPeriod === void 0) { emaPeriod = 10; }
|
|
33
|
+
preList.dataset.push(data);
|
|
34
|
+
if (preList.dataset.length > period) {
|
|
35
|
+
preList.dataset.shift();
|
|
36
|
+
}
|
|
37
|
+
var cmf = 0;
|
|
38
|
+
// Calculate CMF
|
|
39
|
+
if (preList.dataset.length === period) {
|
|
40
|
+
var sumMfVol = 0;
|
|
41
|
+
var sumVol = 0;
|
|
42
|
+
for (var i = 0; i < preList.dataset.length; i++) {
|
|
43
|
+
var item = preList.dataset[i];
|
|
44
|
+
var h = item.h;
|
|
45
|
+
var l = item.l;
|
|
46
|
+
var c = item.c;
|
|
47
|
+
var v = item.v;
|
|
48
|
+
if (h === l) {
|
|
49
|
+
sumVol += v;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
var multiplier = (c - l - (h - c)) / (h - l);
|
|
53
|
+
var mfVol = multiplier * v;
|
|
54
|
+
sumMfVol += mfVol;
|
|
55
|
+
sumVol += v;
|
|
56
|
+
}
|
|
57
|
+
if (sumVol !== 0) {
|
|
58
|
+
cmf = sumMfVol / sumVol;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Calculate EMA of CMF
|
|
62
|
+
var ema = preList.ema;
|
|
63
|
+
var cmfList = __spreadArray([], preList.cmfList, true);
|
|
64
|
+
// Use current 'cmf' only if we had enough data for it (dataset.length === period)
|
|
65
|
+
if (preList.dataset.length === period) {
|
|
66
|
+
cmfList.push(cmf);
|
|
67
|
+
}
|
|
68
|
+
if (cmfList.length === emaPeriod) {
|
|
69
|
+
// First time we have enough data to calculate EMA (SMA seed)
|
|
70
|
+
var sum = cmfList.reduce(function (pre, current) { return pre + current; }, 0);
|
|
71
|
+
ema = sum / emaPeriod;
|
|
72
|
+
}
|
|
73
|
+
else if (cmfList.length > emaPeriod) {
|
|
74
|
+
cmfList.shift();
|
|
75
|
+
// EMA formula: (Current * 2 + (period - 1) * PreviousEMA) / (period + 1)
|
|
76
|
+
ema = (cmf * 2 + (emaPeriod - 1) * preList.ema) / (emaPeriod + 1);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
dataset: preList.dataset,
|
|
80
|
+
cmf: cmf,
|
|
81
|
+
ema: ema,
|
|
82
|
+
cmfList: cmfList,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
return Cmf;
|
|
87
|
+
}());
|
|
88
|
+
export default Cmf;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import Cmf from "./cmf";
|
|
2
|
+
describe("test Cmf methods", function () {
|
|
3
|
+
it("test CMF calculation with simple data (All Bullish)", function () {
|
|
4
|
+
var cmf = new Cmf();
|
|
5
|
+
var period = 3;
|
|
6
|
+
// Data Case 1: Max positive MF
|
|
7
|
+
// H=10, L=0, C=10 => (10-0)-(10-10) = 10, Multiplier = 10/10 = 1.
|
|
8
|
+
var d1 = { c: 10, h: 10, l: 0, v: 100, o: 5, t: 1 };
|
|
9
|
+
var state = cmf.init(d1);
|
|
10
|
+
// Step 1: length 1 < 3. CMF = 0
|
|
11
|
+
expect(state.cmf).toBe(0);
|
|
12
|
+
state = cmf.next(d1, state, period); // length 2
|
|
13
|
+
expect(state.cmf).toBe(0);
|
|
14
|
+
state = cmf.next(d1, state, period); // length 3. SumMFV = 300, SumV = 300. CMF = 1.
|
|
15
|
+
expect(state.cmf).toBe(1);
|
|
16
|
+
});
|
|
17
|
+
it("test CMF calculation with mixed data", function () {
|
|
18
|
+
var cmf = new Cmf();
|
|
19
|
+
var period = 3;
|
|
20
|
+
// Day 1: Mul=1, V=100 -> MFV=100
|
|
21
|
+
var d1 = { c: 10, h: 10, l: 0, v: 100, o: 5, t: 1 };
|
|
22
|
+
// Day 2: Mul=-1, V=100 -> MFV=-100. (C=0, H=10, L=0 => -10 / 10 = -1)
|
|
23
|
+
var d2 = { c: 0, h: 10, l: 0, v: 100, o: 5, t: 2 };
|
|
24
|
+
// Day 3: Mul=0, V=100 -> MFV=0. (C=5, H=10, L=0 => (5-0)-(10-5)=0)
|
|
25
|
+
var d3 = { c: 5, h: 10, l: 0, v: 100, o: 5, t: 3 };
|
|
26
|
+
var state = cmf.init(d1);
|
|
27
|
+
state = cmf.next(d2, state, period);
|
|
28
|
+
state = cmf.next(d3, state, period);
|
|
29
|
+
// Sum MFV = 100 - 100 + 0 = 0. CMF = 0.
|
|
30
|
+
expect(state.cmf).toBe(0);
|
|
31
|
+
});
|
|
32
|
+
it("test CMF EMA calculation", function () {
|
|
33
|
+
var instance = new Cmf();
|
|
34
|
+
var period = 2;
|
|
35
|
+
var emaPeriod = 3;
|
|
36
|
+
// d1: CMF -> 0 (len 1)
|
|
37
|
+
var d1 = { c: 10, h: 10, l: 0, v: 100, o: 5, t: 1 };
|
|
38
|
+
var state = instance.init(d1);
|
|
39
|
+
// CMF undefined yet (0)
|
|
40
|
+
expect(state.cmf).toBe(0);
|
|
41
|
+
expect(state.ema).toBe(0);
|
|
42
|
+
// d2: CMF -> 1. (len 2). MFV=100+100=200, Vol=200.
|
|
43
|
+
var d2 = { c: 10, h: 10, l: 0, v: 100, o: 5, t: 2 };
|
|
44
|
+
state = instance.next(d2, state, period, emaPeriod);
|
|
45
|
+
expect(state.cmf).toBe(1);
|
|
46
|
+
// EMA calc: cmfList = [1]. len=1 < 3. ema=0.
|
|
47
|
+
expect(state.ema).toBe(0);
|
|
48
|
+
// d3: CMF -> 1. (len 2 shift). MFV=100+100=200.
|
|
49
|
+
var d3 = { c: 10, h: 10, l: 0, v: 100, o: 5, t: 3 };
|
|
50
|
+
state = instance.next(d3, state, period, emaPeriod);
|
|
51
|
+
expect(state.cmf).toBe(1);
|
|
52
|
+
// EMA calc: cmfList = [1, 1]. len=2 < 3. ema=0.
|
|
53
|
+
expect(state.ema).toBe(0);
|
|
54
|
+
// d4: CMF -> 1.
|
|
55
|
+
var d4 = { c: 10, h: 10, l: 0, v: 100, o: 5, t: 4 };
|
|
56
|
+
state = instance.next(d4, state, period, emaPeriod);
|
|
57
|
+
expect(state.cmf).toBe(1);
|
|
58
|
+
// EMA calc: cmfList = [1, 1, 1]. len=3. SMA = 1.
|
|
59
|
+
expect(state.ema).toBe(1);
|
|
60
|
+
// d5: CMF -> 2? No, let's make CMF different.
|
|
61
|
+
// period=2. window [d4, d5].
|
|
62
|
+
// d4: MFV=100, V=100.
|
|
63
|
+
// d5: c=0, h=10, l=0, v=100. mul=-1. MFV=-100.
|
|
64
|
+
// SumMFV = 100 - 100 = 0. CMF = 0.
|
|
65
|
+
var d5 = { c: 0, h: 10, l: 0, v: 100, o: 5, t: 5 };
|
|
66
|
+
state = instance.next(d5, state, period, emaPeriod);
|
|
67
|
+
expect(state.cmf).toBe(0);
|
|
68
|
+
// EMA calc: cmfList was [1, 1, 1]. Pushed 0 -> [1, 1, 1, 0]. Shift -> [1, 1, 0].
|
|
69
|
+
// Wait, implementation:
|
|
70
|
+
// push cmf -> [1, 1, 1, 0]
|
|
71
|
+
// if len > emaPeriod -> shift -> [1, 1, 0]
|
|
72
|
+
// EMA = (0 * 2 + (3-1) * 1) / (3+1) = (0 + 2) / 4 = 0.5.
|
|
73
|
+
expect(state.ema).toBe(0.5);
|
|
74
|
+
});
|
|
75
|
+
});
|
package/dist/umd/index.js
CHANGED
|
@@ -1214,7 +1214,7 @@
|
|
|
1214
1214
|
};
|
|
1215
1215
|
return __assign$4.apply(this, arguments);
|
|
1216
1216
|
};
|
|
1217
|
-
var __spreadArray$
|
|
1217
|
+
var __spreadArray$2 = (undefined && undefined.__spreadArray) || function (to, from, pack) {
|
|
1218
1218
|
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
1219
1219
|
if (ar || !(i in from)) {
|
|
1220
1220
|
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
@@ -1254,7 +1254,7 @@
|
|
|
1254
1254
|
obv -= currentVolume;
|
|
1255
1255
|
}
|
|
1256
1256
|
return {
|
|
1257
|
-
dataset: __spreadArray$
|
|
1257
|
+
dataset: __spreadArray$2(__spreadArray$2([], preList.dataset, true), [data], false),
|
|
1258
1258
|
obv: obv,
|
|
1259
1259
|
preClose: currentClose,
|
|
1260
1260
|
};
|
|
@@ -1974,7 +1974,7 @@
|
|
|
1974
1974
|
};
|
|
1975
1975
|
return __assign.apply(this, arguments);
|
|
1976
1976
|
};
|
|
1977
|
-
var __spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) {
|
|
1977
|
+
var __spreadArray$1 = (undefined && undefined.__spreadArray) || function (to, from, pack) {
|
|
1978
1978
|
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
1979
1979
|
if (ar || !(i in from)) {
|
|
1980
1980
|
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
@@ -2110,7 +2110,7 @@
|
|
|
2110
2110
|
var diSum = pDi + mDi;
|
|
2111
2111
|
var dx = diSum === 0 ? 0 : (diDiff / diSum) * 100;
|
|
2112
2112
|
// ADX Logic
|
|
2113
|
-
var dxBuffer = __spreadArray([], preList.dxBuffer, true);
|
|
2113
|
+
var dxBuffer = __spreadArray$1([], preList.dxBuffer, true);
|
|
2114
2114
|
var adx = preList.adx;
|
|
2115
2115
|
var newSmoothAdx = preList.smoothAdx;
|
|
2116
2116
|
if (dxBuffer.length < type) {
|
|
@@ -2164,6 +2164,94 @@
|
|
|
2164
2164
|
return Dmi;
|
|
2165
2165
|
}());
|
|
2166
2166
|
|
|
2167
|
+
var __spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) {
|
|
2168
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
2169
|
+
if (ar || !(i in from)) {
|
|
2170
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
2171
|
+
ar[i] = from[i];
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
2175
|
+
};
|
|
2176
|
+
var Cmf = /** @class */ (function () {
|
|
2177
|
+
function Cmf() {
|
|
2178
|
+
}
|
|
2179
|
+
Object.defineProperty(Cmf.prototype, "init", {
|
|
2180
|
+
enumerable: false,
|
|
2181
|
+
configurable: true,
|
|
2182
|
+
writable: true,
|
|
2183
|
+
value: function (data) {
|
|
2184
|
+
return {
|
|
2185
|
+
dataset: [data],
|
|
2186
|
+
cmf: 0,
|
|
2187
|
+
ema: 0,
|
|
2188
|
+
cmfList: [],
|
|
2189
|
+
};
|
|
2190
|
+
}
|
|
2191
|
+
});
|
|
2192
|
+
Object.defineProperty(Cmf.prototype, "next", {
|
|
2193
|
+
enumerable: false,
|
|
2194
|
+
configurable: true,
|
|
2195
|
+
writable: true,
|
|
2196
|
+
value: function (data, preList, period, emaPeriod) {
|
|
2197
|
+
if (period === void 0) { period = 20; }
|
|
2198
|
+
if (emaPeriod === void 0) { emaPeriod = 10; }
|
|
2199
|
+
preList.dataset.push(data);
|
|
2200
|
+
if (preList.dataset.length > period) {
|
|
2201
|
+
preList.dataset.shift();
|
|
2202
|
+
}
|
|
2203
|
+
var cmf = 0;
|
|
2204
|
+
// Calculate CMF
|
|
2205
|
+
if (preList.dataset.length === period) {
|
|
2206
|
+
var sumMfVol = 0;
|
|
2207
|
+
var sumVol = 0;
|
|
2208
|
+
for (var i = 0; i < preList.dataset.length; i++) {
|
|
2209
|
+
var item = preList.dataset[i];
|
|
2210
|
+
var h = item.h;
|
|
2211
|
+
var l = item.l;
|
|
2212
|
+
var c = item.c;
|
|
2213
|
+
var v = item.v;
|
|
2214
|
+
if (h === l) {
|
|
2215
|
+
sumVol += v;
|
|
2216
|
+
continue;
|
|
2217
|
+
}
|
|
2218
|
+
var multiplier = (c - l - (h - c)) / (h - l);
|
|
2219
|
+
var mfVol = multiplier * v;
|
|
2220
|
+
sumMfVol += mfVol;
|
|
2221
|
+
sumVol += v;
|
|
2222
|
+
}
|
|
2223
|
+
if (sumVol !== 0) {
|
|
2224
|
+
cmf = sumMfVol / sumVol;
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
// Calculate EMA of CMF
|
|
2228
|
+
var ema = preList.ema;
|
|
2229
|
+
var cmfList = __spreadArray([], preList.cmfList, true);
|
|
2230
|
+
// Use current 'cmf' only if we had enough data for it (dataset.length === period)
|
|
2231
|
+
if (preList.dataset.length === period) {
|
|
2232
|
+
cmfList.push(cmf);
|
|
2233
|
+
}
|
|
2234
|
+
if (cmfList.length === emaPeriod) {
|
|
2235
|
+
// First time we have enough data to calculate EMA (SMA seed)
|
|
2236
|
+
var sum = cmfList.reduce(function (pre, current) { return pre + current; }, 0);
|
|
2237
|
+
ema = sum / emaPeriod;
|
|
2238
|
+
}
|
|
2239
|
+
else if (cmfList.length > emaPeriod) {
|
|
2240
|
+
cmfList.shift();
|
|
2241
|
+
// EMA formula: (Current * 2 + (period - 1) * PreviousEMA) / (period + 1)
|
|
2242
|
+
ema = (cmf * 2 + (emaPeriod - 1) * preList.ema) / (emaPeriod + 1);
|
|
2243
|
+
}
|
|
2244
|
+
return {
|
|
2245
|
+
dataset: preList.dataset,
|
|
2246
|
+
cmf: cmf,
|
|
2247
|
+
ema: ema,
|
|
2248
|
+
cmfList: cmfList,
|
|
2249
|
+
};
|
|
2250
|
+
}
|
|
2251
|
+
});
|
|
2252
|
+
return Cmf;
|
|
2253
|
+
}());
|
|
2254
|
+
|
|
2167
2255
|
function add(a, b) {
|
|
2168
2256
|
return a + b;
|
|
2169
2257
|
}
|
|
@@ -2202,6 +2290,7 @@
|
|
|
2202
2290
|
|
|
2203
2291
|
exports.Angle = TwoPointAngle;
|
|
2204
2292
|
exports.Boll = Boll;
|
|
2293
|
+
exports.Cmf = Cmf;
|
|
2205
2294
|
exports.Dmi = Dmi;
|
|
2206
2295
|
exports.Ema = Ema;
|
|
2207
2296
|
exports.Gold = Gold;
|