@ch20026103/anysis 0.0.17-alpha1 → 0.0.18
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/demo/main.js +42 -11
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.js +5 -1
- package/dist/cjs/stockSkills/kd.d.ts +0 -18
- package/dist/cjs/stockSkills/kd.js +0 -65
- package/dist/cjs/stockSkills/kd.test.js +3 -50
- package/dist/cjs/stockSkills/mfi.d.ts +15 -0
- package/dist/cjs/stockSkills/mfi.js +166 -0
- package/dist/cjs/stockSkills/mfi.test.d.ts +1 -0
- package/dist/cjs/stockSkills/mfi.test.js +193 -0
- package/dist/cjs/stockSkills/obv.d.ts +4 -7
- package/dist/cjs/stockSkills/obv.js +2 -15
- package/dist/cjs/stockSkills/obv.test.js +5 -3
- package/dist/cjs/stockSkills/obv_ema.d.ts +15 -0
- package/dist/cjs/stockSkills/obv_ema.js +49 -0
- package/dist/cjs/stockSkills/obv_ema.test.d.ts +1 -0
- package/dist/cjs/stockSkills/obv_ema.test.js +23 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/stockSkills/kd.d.ts +0 -18
- package/dist/esm/stockSkills/kd.js +0 -65
- package/dist/esm/stockSkills/kd.test.js +3 -50
- package/dist/esm/stockSkills/mfi.d.ts +15 -0
- package/dist/esm/stockSkills/mfi.js +164 -0
- package/dist/esm/stockSkills/mfi.test.d.ts +1 -0
- package/dist/esm/stockSkills/mfi.test.js +191 -0
- package/dist/esm/stockSkills/obv.d.ts +4 -7
- package/dist/esm/stockSkills/obv.js +2 -15
- package/dist/esm/stockSkills/obv.test.js +5 -3
- package/dist/esm/stockSkills/obv_ema.d.ts +15 -0
- package/dist/esm/stockSkills/obv_ema.js +47 -0
- package/dist/esm/stockSkills/obv_ema.test.d.ts +1 -0
- package/dist/esm/stockSkills/obv_ema.test.js +21 -0
- package/dist/umd/index.js +256 -121
- package/package.json +1 -1
|
@@ -7,19 +7,16 @@ type ResObv = {
|
|
|
7
7
|
export type ObvResType = {
|
|
8
8
|
dataset: StockListType;
|
|
9
9
|
obv: number;
|
|
10
|
-
obvList: number[];
|
|
11
10
|
preClose: number;
|
|
12
|
-
obvMa: number;
|
|
13
|
-
type: number;
|
|
14
11
|
};
|
|
15
12
|
interface ObvType {
|
|
16
|
-
init: (data: NewStockType
|
|
17
|
-
next: (data: NewStockType, preList: ObvResType
|
|
13
|
+
init: (data: NewStockType) => ObvResType;
|
|
14
|
+
next: (data: NewStockType, preList: ObvResType) => ObvResType;
|
|
18
15
|
getObv: (list: NewStockListType, period: number) => ResObv[];
|
|
19
16
|
}
|
|
20
17
|
export default class Obv implements ObvType {
|
|
21
|
-
init(data: NewStockType
|
|
22
|
-
next(data: NewStockType, preList: ObvResType
|
|
18
|
+
init(data: NewStockType): ObvResType;
|
|
19
|
+
next(data: NewStockType, preList: ObvResType): ObvResType;
|
|
23
20
|
getObv(list: NewStockListType): ResObv[];
|
|
24
21
|
}
|
|
25
22
|
export {};
|
|
@@ -27,14 +27,11 @@ var Obv = /** @class */ (function () {
|
|
|
27
27
|
enumerable: false,
|
|
28
28
|
configurable: true,
|
|
29
29
|
writable: true,
|
|
30
|
-
value: function (data
|
|
30
|
+
value: function (data) {
|
|
31
31
|
return {
|
|
32
32
|
dataset: [data],
|
|
33
33
|
obv: data.v,
|
|
34
|
-
obvList: [data.v],
|
|
35
34
|
preClose: data.c,
|
|
36
|
-
obvMa: 0,
|
|
37
|
-
type: type,
|
|
38
35
|
};
|
|
39
36
|
}
|
|
40
37
|
});
|
|
@@ -42,7 +39,7 @@ var Obv = /** @class */ (function () {
|
|
|
42
39
|
enumerable: false,
|
|
43
40
|
configurable: true,
|
|
44
41
|
writable: true,
|
|
45
|
-
value: function (data, preList
|
|
42
|
+
value: function (data, preList) {
|
|
46
43
|
var currentVolume = data.v;
|
|
47
44
|
var currentClose = data.c;
|
|
48
45
|
// obv
|
|
@@ -53,20 +50,10 @@ var Obv = /** @class */ (function () {
|
|
|
53
50
|
else if (currentClose < preList.preClose) {
|
|
54
51
|
obv -= currentVolume;
|
|
55
52
|
}
|
|
56
|
-
// obv Ma
|
|
57
|
-
var obvList = preList.obvList;
|
|
58
|
-
obvList.push(obv);
|
|
59
|
-
if (obvList.length > type)
|
|
60
|
-
obvList.shift();
|
|
61
|
-
var sum = obvList.reduce(function (pre, current) { return pre + current; }, 0);
|
|
62
|
-
var vma = Math.round((sum / type) * 100) / 100;
|
|
63
53
|
return {
|
|
64
54
|
dataset: __spreadArray(__spreadArray([], preList.dataset, true), [data], false),
|
|
65
55
|
obv: obv,
|
|
66
56
|
preClose: currentClose,
|
|
67
|
-
obvList: obvList,
|
|
68
|
-
obvMa: vma,
|
|
69
|
-
type: type,
|
|
70
57
|
};
|
|
71
58
|
}
|
|
72
59
|
});
|
|
@@ -5,13 +5,15 @@ var test_data_test_1 = require("./test_data.test");
|
|
|
5
5
|
describe("test obv methods", function () {
|
|
6
6
|
it("test init", function () {
|
|
7
7
|
var obv = new obv_1.default();
|
|
8
|
-
var init = obv.init(test_data_test_1.data_9904[0]
|
|
8
|
+
var init = obv.init(test_data_test_1.data_9904[0]);
|
|
9
9
|
var res = init;
|
|
10
10
|
for (var i = 1; i < test_data_test_1.data_9904.length; i++) {
|
|
11
11
|
var item = test_data_test_1.data_9904[i];
|
|
12
|
-
res = obv.next(item, res
|
|
12
|
+
res = obv.next(item, res);
|
|
13
13
|
}
|
|
14
|
-
expect({ obv: res.obv
|
|
14
|
+
expect({ obv: res.obv }).toEqual({
|
|
15
|
+
obv: 504538,
|
|
16
|
+
});
|
|
15
17
|
});
|
|
16
18
|
it("test getObv()", function () {
|
|
17
19
|
var kd = new obv_1.default();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type ObvEmaResType = {
|
|
2
|
+
obvList: number[];
|
|
3
|
+
ema: number;
|
|
4
|
+
ma: number;
|
|
5
|
+
type: number;
|
|
6
|
+
};
|
|
7
|
+
interface ObvEmaType {
|
|
8
|
+
init: (obv: number, type: number) => ObvEmaResType;
|
|
9
|
+
next: (obv: number, preList: ObvEmaResType, type: number) => ObvEmaResType;
|
|
10
|
+
}
|
|
11
|
+
export default class ObvEma implements ObvEmaType {
|
|
12
|
+
init(obv: number, type: number): ObvEmaResType;
|
|
13
|
+
next(obv: number, preList: ObvEmaResType, type: number): ObvEmaResType;
|
|
14
|
+
}
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var ObvEma = /** @class */ (function () {
|
|
4
|
+
function ObvEma() {
|
|
5
|
+
}
|
|
6
|
+
Object.defineProperty(ObvEma.prototype, "init", {
|
|
7
|
+
enumerable: false,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true,
|
|
10
|
+
value: function (obv, type) {
|
|
11
|
+
return {
|
|
12
|
+
obvList: [obv],
|
|
13
|
+
ema: 0,
|
|
14
|
+
ma: 0,
|
|
15
|
+
type: type,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(ObvEma.prototype, "next", {
|
|
20
|
+
enumerable: false,
|
|
21
|
+
configurable: true,
|
|
22
|
+
writable: true,
|
|
23
|
+
value: function (obv, preList, type) {
|
|
24
|
+
var obvList = preList.obvList;
|
|
25
|
+
obvList.push(obv);
|
|
26
|
+
var ma = 0;
|
|
27
|
+
var ema = 0;
|
|
28
|
+
if (obvList.length === type) {
|
|
29
|
+
var sum = obvList.reduce(function (pre, current) { return pre + current; }, 0);
|
|
30
|
+
ma = Math.round((sum / type) * 100) / 100;
|
|
31
|
+
ema = ma;
|
|
32
|
+
}
|
|
33
|
+
else if (obvList.length > type) {
|
|
34
|
+
obvList.shift();
|
|
35
|
+
var sum = obvList.reduce(function (pre, current) { return pre + current; }, 0);
|
|
36
|
+
ma = Math.round((sum / type) * 100) / 100;
|
|
37
|
+
ema = (obv * 2 + (type - 1) * preList.ema) / (type + 1);
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
obvList: obvList,
|
|
41
|
+
ema: ema,
|
|
42
|
+
ma: ma,
|
|
43
|
+
type: type,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return ObvEma;
|
|
48
|
+
}());
|
|
49
|
+
exports.default = ObvEma;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var obv_1 = require("./obv");
|
|
4
|
+
var obv_ema_1 = require("./obv_ema");
|
|
5
|
+
var test_data_test_1 = require("./test_data.test");
|
|
6
|
+
describe("ObvEma", function () {
|
|
7
|
+
it("test init", function () {
|
|
8
|
+
var obv = new obv_1.default();
|
|
9
|
+
var obvEma = new obv_ema_1.default();
|
|
10
|
+
var obvData = obv.init(test_data_test_1.data_9904[0]);
|
|
11
|
+
var emaData = obvEma.init(obvData.obv, 5);
|
|
12
|
+
for (var i = 1; i < test_data_test_1.data_9904.length; i++) {
|
|
13
|
+
var item = test_data_test_1.data_9904[i];
|
|
14
|
+
obvData = obv.next(item, obvData);
|
|
15
|
+
emaData = obvEma.next(obvData.obv, emaData, 5);
|
|
16
|
+
}
|
|
17
|
+
expect({ obv: obvData.obv, ma: emaData.ma, ema: emaData.ema }).toEqual({
|
|
18
|
+
obv: 504538,
|
|
19
|
+
ma: 494302.2,
|
|
20
|
+
ema: 496758.8736585481,
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
});
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ export { default as dateFormat } from "./stockSkills/utils/dateFormat.js";
|
|
|
18
18
|
export { default as Week } from "./stockSkills/week.js";
|
|
19
19
|
export { default as Vma } from "./stockSkills/vma.js";
|
|
20
20
|
export { default as Williams } from "./stockSkills/williams.js";
|
|
21
|
+
export { default as ObvEma } from "./stockSkills/obv_ema.js";
|
|
22
|
+
export { default as Mfi } from "./stockSkills/mfi.js";
|
|
21
23
|
export { add } from "./test/add.js";
|
|
22
24
|
export { minus } from "./test/minus.js";
|
|
23
25
|
export { default as calculateDivisionFactor } from "./utils/calculateDivisionFactor.js";
|
package/dist/esm/index.js
CHANGED
|
@@ -21,6 +21,8 @@ export { default as dateFormat } from "./stockSkills/utils/dateFormat.js";
|
|
|
21
21
|
export { default as Week } from "./stockSkills/week.js";
|
|
22
22
|
export { default as Vma } from "./stockSkills/vma.js";
|
|
23
23
|
export { default as Williams } from "./stockSkills/williams.js";
|
|
24
|
+
export { default as ObvEma } from "./stockSkills/obv_ema.js";
|
|
25
|
+
export { default as Mfi } from "./stockSkills/mfi.js";
|
|
24
26
|
export { add } from "./test/add.js";
|
|
25
27
|
export { minus } from "./test/minus.js";
|
|
26
28
|
export { default as calculateDivisionFactor } from "./utils/calculateDivisionFactor.js";
|
|
@@ -1,18 +1,4 @@
|
|
|
1
1
|
import { StockListType, StockType } from "./types";
|
|
2
|
-
type ResRSV = {
|
|
3
|
-
c: number;
|
|
4
|
-
rsv: number;
|
|
5
|
-
[key: string]: unknown;
|
|
6
|
-
};
|
|
7
|
-
type ResKD = {
|
|
8
|
-
c: number;
|
|
9
|
-
rsv: number;
|
|
10
|
-
k: number;
|
|
11
|
-
d: number;
|
|
12
|
-
"k-d": number;
|
|
13
|
-
j: number;
|
|
14
|
-
[key: string]: unknown;
|
|
15
|
-
};
|
|
16
2
|
export type KdResType = {
|
|
17
3
|
dataset: StockListType;
|
|
18
4
|
rsv: number;
|
|
@@ -25,13 +11,9 @@ export type KdResType = {
|
|
|
25
11
|
interface KdClassType {
|
|
26
12
|
init: (data: StockType, type: number) => KdResType;
|
|
27
13
|
next: (data: StockType, preList: KdResType, type: number) => KdResType;
|
|
28
|
-
getRSV: (list: StockListType) => ResRSV[];
|
|
29
|
-
getKD: (list: StockListType) => ResKD[];
|
|
30
14
|
}
|
|
31
15
|
export default class Kd implements KdClassType {
|
|
32
16
|
init(data: StockType, type: number): KdResType;
|
|
33
17
|
next(data: StockType, preList: KdResType, type: number): KdResType;
|
|
34
|
-
getRSV(list: StockListType): ResRSV[];
|
|
35
|
-
getKD(list: StockListType): ResKD[];
|
|
36
18
|
}
|
|
37
19
|
export {};
|
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
var __assign = (this && this.__assign) || function () {
|
|
2
|
-
__assign = Object.assign || function(t) {
|
|
3
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
-
s = arguments[i];
|
|
5
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
-
t[p] = s[p];
|
|
7
|
-
}
|
|
8
|
-
return t;
|
|
9
|
-
};
|
|
10
|
-
return __assign.apply(this, arguments);
|
|
11
|
-
};
|
|
12
1
|
var Kd = /** @class */ (function () {
|
|
13
2
|
function Kd() {
|
|
14
3
|
}
|
|
@@ -74,60 +63,6 @@ var Kd = /** @class */ (function () {
|
|
|
74
63
|
}
|
|
75
64
|
}
|
|
76
65
|
});
|
|
77
|
-
Object.defineProperty(Kd.prototype, "getRSV", {
|
|
78
|
-
enumerable: false,
|
|
79
|
-
configurable: true,
|
|
80
|
-
writable: true,
|
|
81
|
-
value: function (list) {
|
|
82
|
-
var res = [];
|
|
83
|
-
for (var i = 0; i < list.length; i++) {
|
|
84
|
-
if (i < 8)
|
|
85
|
-
res[i] = __assign(__assign({}, list[i]), { rsv: 0 });
|
|
86
|
-
else {
|
|
87
|
-
var low = Math.min.apply(Math, list.slice(i - 8, i + 1).map(function (item) { return item.l; }));
|
|
88
|
-
var hight = Math.max.apply(Math, list.slice(i - 8, i + 1).map(function (item) { return item.h; }));
|
|
89
|
-
var close_2 = list[i].c;
|
|
90
|
-
var rsv = ((close_2 - low) / (hight - low)) * 100;
|
|
91
|
-
rsv = Math.round(rsv * 100) / 100;
|
|
92
|
-
res[i] = __assign(__assign({}, list[i]), { rsv: rsv });
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return res;
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
Object.defineProperty(Kd.prototype, "getKD", {
|
|
99
|
-
enumerable: false,
|
|
100
|
-
configurable: true,
|
|
101
|
-
writable: true,
|
|
102
|
-
value: function (list) {
|
|
103
|
-
var res = [];
|
|
104
|
-
var yesterdayK = 50;
|
|
105
|
-
var yesterdayD = 50;
|
|
106
|
-
for (var i = 0; i < list.length; i++) {
|
|
107
|
-
if (i < 8)
|
|
108
|
-
res[i] = __assign(__assign({}, list[i]), { rsv: 0, k: 0, d: 0, "k-d": 0, j: 0 });
|
|
109
|
-
else {
|
|
110
|
-
var low = Math.min.apply(Math, list.slice(i - 8, i + 1).map(function (item) { return item.l; }));
|
|
111
|
-
var hight = Math.max.apply(Math, list.slice(i - 8, i + 1).map(function (item) { return item.h; }));
|
|
112
|
-
var close_3 = list[i].c;
|
|
113
|
-
var rsv = ((close_3 - low) / (hight - low)) * 100;
|
|
114
|
-
rsv = Math.round(rsv * 100) / 100;
|
|
115
|
-
var k = (2 / 3) * yesterdayK + (1 / 3) * rsv;
|
|
116
|
-
var d = (2 / 3) * yesterdayD + (1 / 3) * k;
|
|
117
|
-
var k_d = k - d;
|
|
118
|
-
var j = 3 * k - 2 * d;
|
|
119
|
-
k = Math.round(k * 100) / 100;
|
|
120
|
-
d = Math.round(d * 100) / 100;
|
|
121
|
-
k_d = Math.round(k_d * 100) / 100;
|
|
122
|
-
j = Math.round(j * 100) / 100;
|
|
123
|
-
res[i] = __assign(__assign({}, list[i]), { rsv: rsv, k: k, d: d, "k-d": k_d, j: j });
|
|
124
|
-
yesterdayK = k;
|
|
125
|
-
yesterdayD = d;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return res;
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
66
|
return Kd;
|
|
132
67
|
}());
|
|
133
68
|
export default Kd;
|
|
@@ -4,61 +4,14 @@ describe("test kd methods", function () {
|
|
|
4
4
|
it("test init", function () {
|
|
5
5
|
var index = data.length - 1;
|
|
6
6
|
var kd = new Kd();
|
|
7
|
-
var realData = kd.getKD(data)[index];
|
|
8
7
|
var init = kd.init(data[0], 9);
|
|
9
8
|
var res = init;
|
|
10
9
|
for (var i = 1; i <= index; i++) {
|
|
11
10
|
var item = data[i];
|
|
12
11
|
res = kd.next(item, res, 9);
|
|
13
12
|
}
|
|
14
|
-
expect(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
h: realData.h,
|
|
18
|
-
l: realData.l,
|
|
19
|
-
},
|
|
20
|
-
rsv: realData.rsv,
|
|
21
|
-
"k-d": realData["k-d"],
|
|
22
|
-
k: realData.k,
|
|
23
|
-
d: realData.d,
|
|
24
|
-
}).toEqual({
|
|
25
|
-
dataset: {
|
|
26
|
-
c: res.dataset[res.dataset.length - 1].c,
|
|
27
|
-
h: res.dataset[res.dataset.length - 1].h,
|
|
28
|
-
l: res.dataset[res.dataset.length - 1].l,
|
|
29
|
-
},
|
|
30
|
-
rsv: res.rsv,
|
|
31
|
-
"k-d": res["k-d"],
|
|
32
|
-
k: res.k,
|
|
33
|
-
d: res.d,
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
it("test getRSV()", function () {
|
|
37
|
-
var kd = new Kd();
|
|
38
|
-
expect(kd.getRSV(data)[data.length - 1]).toEqual({
|
|
39
|
-
o: 26.4,
|
|
40
|
-
l: 34.3,
|
|
41
|
-
h: 34.8,
|
|
42
|
-
c: 34.65,
|
|
43
|
-
v: 12765,
|
|
44
|
-
t: 20230216,
|
|
45
|
-
rsv: 90.63,
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
it("test getKD()", function () {
|
|
49
|
-
var kd = new Kd();
|
|
50
|
-
expect(kd.getKD(data)[data.length - 1]).toEqual({
|
|
51
|
-
o: 26.4,
|
|
52
|
-
l: 34.3,
|
|
53
|
-
h: 34.8,
|
|
54
|
-
c: 34.65,
|
|
55
|
-
v: 12765,
|
|
56
|
-
t: 20230216,
|
|
57
|
-
rsv: 90.63,
|
|
58
|
-
k: 64.41,
|
|
59
|
-
d: 45.25,
|
|
60
|
-
"k-d": 19.16,
|
|
61
|
-
j: 6.93,
|
|
62
|
-
});
|
|
13
|
+
expect(res.k).toEqual(64.41);
|
|
14
|
+
expect(res.d).toEqual(45.25);
|
|
15
|
+
expect(res.j).toEqual(102.73);
|
|
63
16
|
});
|
|
64
17
|
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { StockListType, StockType } from "./types";
|
|
2
|
+
export type MfiResType = {
|
|
3
|
+
dataset: StockListType;
|
|
4
|
+
mfi: number | null;
|
|
5
|
+
type: number;
|
|
6
|
+
sumPositiveMF: number;
|
|
7
|
+
sumNegativeMF: number;
|
|
8
|
+
};
|
|
9
|
+
export default class Mfi {
|
|
10
|
+
private getTypicalPrice;
|
|
11
|
+
private getRawMoneyFlow;
|
|
12
|
+
init(data: StockType, type: number): MfiResType;
|
|
13
|
+
next(data: StockType, preList: MfiResType, type: number): MfiResType;
|
|
14
|
+
calculateMFI(prices: StockListType, period?: number): number[];
|
|
15
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var Mfi = /** @class */ (function () {
|
|
13
|
+
function Mfi() {
|
|
14
|
+
}
|
|
15
|
+
// 計算典型價格 (Typical Price)
|
|
16
|
+
Object.defineProperty(Mfi.prototype, "getTypicalPrice", {
|
|
17
|
+
enumerable: false,
|
|
18
|
+
configurable: true,
|
|
19
|
+
writable: true,
|
|
20
|
+
value: function (data) {
|
|
21
|
+
return (data.h + data.l + data.c) / 3;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
// 計算原始資金流量 (Raw Money Flow)
|
|
25
|
+
Object.defineProperty(Mfi.prototype, "getRawMoneyFlow", {
|
|
26
|
+
enumerable: false,
|
|
27
|
+
configurable: true,
|
|
28
|
+
writable: true,
|
|
29
|
+
value: function (data) {
|
|
30
|
+
return this.getTypicalPrice(data) * data.v;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
Object.defineProperty(Mfi.prototype, "init", {
|
|
34
|
+
enumerable: false,
|
|
35
|
+
configurable: true,
|
|
36
|
+
writable: true,
|
|
37
|
+
value: function (data, type) {
|
|
38
|
+
return {
|
|
39
|
+
dataset: [data],
|
|
40
|
+
mfi: null,
|
|
41
|
+
type: type,
|
|
42
|
+
sumPositiveMF: 0,
|
|
43
|
+
sumNegativeMF: 0,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
Object.defineProperty(Mfi.prototype, "next", {
|
|
48
|
+
enumerable: false,
|
|
49
|
+
configurable: true,
|
|
50
|
+
writable: true,
|
|
51
|
+
value: function (data, preList, type) {
|
|
52
|
+
preList.dataset.push(data);
|
|
53
|
+
// 資料不足,不計算 MFI
|
|
54
|
+
if (preList.dataset.length < type + 1) {
|
|
55
|
+
return __assign(__assign({}, preList), { mfi: null, type: type, sumPositiveMF: 0, sumNegativeMF: 0 });
|
|
56
|
+
}
|
|
57
|
+
var sumPositiveMF = preList.sumPositiveMF;
|
|
58
|
+
var sumNegativeMF = preList.sumNegativeMF;
|
|
59
|
+
if (preList.dataset.length === type + 1) {
|
|
60
|
+
// 第一次達到計算條件,初始化計算
|
|
61
|
+
sumPositiveMF = 0;
|
|
62
|
+
sumNegativeMF = 0;
|
|
63
|
+
for (var i = 1; i <= type; i++) {
|
|
64
|
+
var currentTP = this.getTypicalPrice(preList.dataset[i]);
|
|
65
|
+
var prevTP = this.getTypicalPrice(preList.dataset[i - 1]);
|
|
66
|
+
var rawMF = this.getRawMoneyFlow(preList.dataset[i]);
|
|
67
|
+
if (currentTP > prevTP) {
|
|
68
|
+
sumPositiveMF += rawMF;
|
|
69
|
+
}
|
|
70
|
+
else if (currentTP < prevTP) {
|
|
71
|
+
sumNegativeMF += rawMF;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// 增量更新:移除最舊的影響,加上最新的影響
|
|
77
|
+
// 移除最舊的資料影響
|
|
78
|
+
var oldestTP = this.getTypicalPrice(preList.dataset[0]);
|
|
79
|
+
var secondOldestTP = this.getTypicalPrice(preList.dataset[1]);
|
|
80
|
+
var oldestRawMF = this.getRawMoneyFlow(preList.dataset[1]);
|
|
81
|
+
if (secondOldestTP > oldestTP) {
|
|
82
|
+
sumPositiveMF -= oldestRawMF;
|
|
83
|
+
}
|
|
84
|
+
else if (secondOldestTP < oldestTP) {
|
|
85
|
+
sumNegativeMF -= oldestRawMF;
|
|
86
|
+
}
|
|
87
|
+
// 移除最舊的資料
|
|
88
|
+
preList.dataset.shift();
|
|
89
|
+
// 加上最新的資料影響
|
|
90
|
+
var newTP = this.getTypicalPrice(preList.dataset[preList.dataset.length - 1]);
|
|
91
|
+
var prevTP = this.getTypicalPrice(preList.dataset[preList.dataset.length - 2]);
|
|
92
|
+
var newRawMF = this.getRawMoneyFlow(preList.dataset[preList.dataset.length - 1]);
|
|
93
|
+
if (newTP > prevTP) {
|
|
94
|
+
sumPositiveMF += newRawMF;
|
|
95
|
+
}
|
|
96
|
+
else if (newTP < prevTP) {
|
|
97
|
+
sumNegativeMF += newRawMF;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// 計算 MFI
|
|
101
|
+
var mfi;
|
|
102
|
+
if (sumNegativeMF === 0) {
|
|
103
|
+
mfi = 100;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
var moneyFlowRatio = sumPositiveMF / sumNegativeMF;
|
|
107
|
+
mfi = 100 - (100 / (1 + moneyFlowRatio));
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
dataset: preList.dataset,
|
|
111
|
+
type: type,
|
|
112
|
+
mfi: mfi,
|
|
113
|
+
sumPositiveMF: sumPositiveMF,
|
|
114
|
+
sumNegativeMF: sumNegativeMF
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
Object.defineProperty(Mfi.prototype, "calculateMFI", {
|
|
119
|
+
enumerable: false,
|
|
120
|
+
configurable: true,
|
|
121
|
+
writable: true,
|
|
122
|
+
value: function (prices, period) {
|
|
123
|
+
if (period === void 0) { period = 14; }
|
|
124
|
+
if (prices.length < period + 1) {
|
|
125
|
+
return [];
|
|
126
|
+
}
|
|
127
|
+
var mfis = [];
|
|
128
|
+
// 從 period 開始,確保有足夠的資料進行比較
|
|
129
|
+
for (var endIdx = period; endIdx < prices.length; endIdx++) {
|
|
130
|
+
var sumPositiveMF = 0;
|
|
131
|
+
var sumNegativeMF = 0;
|
|
132
|
+
// 計算 period 個交易日的資金流量
|
|
133
|
+
// 從 endIdx - period + 1 到 endIdx,共 period 個資料點
|
|
134
|
+
// 但比較是從 endIdx - period + 2 開始(因為要跟前一天比)
|
|
135
|
+
for (var i = endIdx - period + 1; i <= endIdx; i++) {
|
|
136
|
+
// 確保 i-1 >= 0,避免溢位
|
|
137
|
+
if (i === 0)
|
|
138
|
+
continue;
|
|
139
|
+
var currentTP = this.getTypicalPrice(prices[i]);
|
|
140
|
+
var prevTP = this.getTypicalPrice(prices[i - 1]);
|
|
141
|
+
var rawMF = this.getRawMoneyFlow(prices[i]);
|
|
142
|
+
if (currentTP > prevTP) {
|
|
143
|
+
sumPositiveMF += rawMF;
|
|
144
|
+
}
|
|
145
|
+
else if (currentTP < prevTP) {
|
|
146
|
+
sumNegativeMF += rawMF;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// 計算 MFI
|
|
150
|
+
if (sumNegativeMF === 0) {
|
|
151
|
+
mfis.push(100);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
var moneyFlowRatio = sumPositiveMF / sumNegativeMF;
|
|
155
|
+
var mfi = 100 - (100 / (1 + moneyFlowRatio));
|
|
156
|
+
mfis.push(mfi);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return mfis;
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
return Mfi;
|
|
163
|
+
}());
|
|
164
|
+
export default Mfi;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|