@ch20026103/anysis 0.0.19-alpha1 → 0.0.19

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.
@@ -21,6 +21,7 @@ export { default as Williams } from "./stockSkills/williams.js";
21
21
  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
+ export { default as Dmi } from "./stockSkills/dmi.js";
24
25
  export { add } from "./test/add.js";
25
26
  export { minus } from "./test/minus.js";
26
27
  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.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.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副檔名**
@@ -53,6 +53,8 @@ var mfi_js_1 = require("./stockSkills/mfi.js");
53
53
  Object.defineProperty(exports, "Mfi", { enumerable: true, get: function () { return mfi_js_1.default; } });
54
54
  var ichimoku_js_1 = require("./stockSkills/ichimoku.js");
55
55
  Object.defineProperty(exports, "Ichimoku", { enumerable: true, get: function () { return ichimoku_js_1.default; } });
56
+ var dmi_js_1 = require("./stockSkills/dmi.js");
57
+ Object.defineProperty(exports, "Dmi", { enumerable: true, get: function () { return dmi_js_1.default; } });
56
58
  var add_js_1 = require("./test/add.js");
57
59
  Object.defineProperty(exports, "add", { enumerable: true, get: function () { return add_js_1.add; } });
58
60
  var minus_js_1 = require("./test/minus.js");
@@ -0,0 +1,28 @@
1
+ import { StockListType, StockType } from "./types";
2
+ export type DmiResType = {
3
+ dataset: StockListType;
4
+ pDi: number;
5
+ mDi: number;
6
+ adx: number;
7
+ type: number;
8
+ smoothTr: number;
9
+ smoothPdm: number;
10
+ smoothMdm: number;
11
+ dxBuffer: number[];
12
+ smoothAdx: number;
13
+ };
14
+ export default class Dmi {
15
+ init(data: StockType, type: number): DmiResType;
16
+ next(data: StockType, preList: DmiResType, type: number): DmiResType;
17
+ calculateDmiValues(list: StockListType, period?: number): {
18
+ pDi: number;
19
+ mDi: number;
20
+ adx: number;
21
+ c: number;
22
+ v: number;
23
+ l: number;
24
+ h: number;
25
+ o: number;
26
+ t: number;
27
+ }[];
28
+ }
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
14
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
15
+ if (ar || !(i in from)) {
16
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
17
+ ar[i] = from[i];
18
+ }
19
+ }
20
+ return to.concat(ar || Array.prototype.slice.call(from));
21
+ };
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ var Dmi = /** @class */ (function () {
24
+ function Dmi() {
25
+ }
26
+ Object.defineProperty(Dmi.prototype, "init", {
27
+ enumerable: false,
28
+ configurable: true,
29
+ writable: true,
30
+ value: function (data, type) {
31
+ return {
32
+ dataset: [data],
33
+ pDi: 0,
34
+ mDi: 0,
35
+ adx: 0,
36
+ type: type,
37
+ smoothTr: 0,
38
+ smoothPdm: 0,
39
+ smoothMdm: 0,
40
+ dxBuffer: [],
41
+ smoothAdx: 0,
42
+ };
43
+ }
44
+ });
45
+ Object.defineProperty(Dmi.prototype, "next", {
46
+ enumerable: false,
47
+ configurable: true,
48
+ writable: true,
49
+ value: function (data, preList, type) {
50
+ preList.dataset.push(data);
51
+ // Need type + 1 data points to have 'type' periods of change
52
+ if (preList.dataset.length < type + 1) {
53
+ return __assign(__assign({}, preList), { pDi: 0, mDi: 0, adx: 0 });
54
+ }
55
+ else {
56
+ var currentTr = 0;
57
+ var currentPdm = 0;
58
+ var currentMdm = 0;
59
+ // Logic to get TR, +DM, -DM for the NEWEST data point
60
+ // We need the newest point and the one before it.
61
+ // If we are in the initialization phase (length === type + 1), we process the whole window.
62
+ // If we are in the incremental phase (length > type + 1), we just process the last step.
63
+ var newSmoothTr = preList.smoothTr;
64
+ var newSmoothPdm = preList.smoothPdm;
65
+ var newSmoothMdm = preList.smoothMdm;
66
+ if (preList.dataset.length === type + 1) {
67
+ // Initialization: Calculate sum of first N periods (using N+1 data points)
68
+ var sumTr = 0;
69
+ var sumPdm = 0;
70
+ var sumMdm = 0;
71
+ for (var i = 1; i <= type; i++) {
72
+ var curr = preList.dataset[i];
73
+ var prev = preList.dataset[i - 1];
74
+ // TR
75
+ var hl = curr.h - curr.l;
76
+ var hpc = Math.abs(curr.h - prev.c);
77
+ var lpc = Math.abs(curr.l - prev.c);
78
+ var tr = Math.max(hl, hpc, lpc);
79
+ // DM
80
+ var hph = curr.h - prev.h;
81
+ var pll = prev.l - curr.l;
82
+ var pdm = 0;
83
+ var mdm = 0;
84
+ if (hph > pll && hph > 0) {
85
+ pdm = hph;
86
+ }
87
+ if (pll > hph && pll > 0) {
88
+ mdm = pll;
89
+ }
90
+ sumTr += tr;
91
+ sumPdm += pdm;
92
+ sumMdm += mdm;
93
+ }
94
+ // Wilder's first value is often just the Sum.
95
+ // But to make it consistent with the "Average" view for the formula:
96
+ // NextAvg = (PrevAvg * (N-1) + Curr) / N
97
+ // The first "PrevAvg" acts as the seed. The seed is usually the Simple Average.
98
+ // So we divide by type.
99
+ newSmoothTr = sumTr; // Some sources say keep Sum. But standard indicators often normalize to Average range.
100
+ // Let's check RSI implementation. RSI divides by type: gains / type.
101
+ // So we will divide by type to get the Average TR/DM.
102
+ // Wait! DMI standard often keeps the SUM for the first value?
103
+ // Wilder's book: "+DM14 is the sum of the +DM for the last 14 days".
104
+ // Then subsequent: "+DM14_today = +DM14_yesterday - (+DM14_yesterday/14) + +DM_today".
105
+ // This formula maintains the "Sum" magnitude (approx 14x the average).
106
+ // BUT, RSI implementation uses Average magnitude (0-100 range inputs usually lead to small AvgGain).
107
+ // Let's stick to the RSI pattern: Average.
108
+ // Formula: (Avg * (N-1) + Curr) / N. This maintains "Average" magnitude.
109
+ // If we used Sum logic: (Sum - Sum/N + Curr) = Sum * (1 - 1/N) + Curr.
110
+ // These are mathematically consistent in shape, just scaled by N.
111
+ // DI calculation is (Pdm / Tr) * 100. The scale cancels out!
112
+ // So using Average is safer for preventing overflow and easier to debug (per-day values).
113
+ newSmoothTr = sumTr / type;
114
+ newSmoothPdm = sumPdm / type;
115
+ newSmoothMdm = sumMdm / type;
116
+ }
117
+ else {
118
+ // Shift if needed to keep dataset size manageable, though strictly we only need last 2 points
119
+ // reusing rsi pattern:
120
+ if (preList.dataset.length > type + 1) {
121
+ preList.dataset.shift();
122
+ }
123
+ var curr = preList.dataset[preList.dataset.length - 1];
124
+ var prev = preList.dataset[preList.dataset.length - 2];
125
+ // TR
126
+ var hl = curr.h - curr.l;
127
+ var hpc = Math.abs(curr.h - prev.c);
128
+ var lpc = Math.abs(curr.l - prev.c);
129
+ var tr = Math.max(hl, hpc, lpc);
130
+ // DM
131
+ var hph = curr.h - prev.h;
132
+ var pll = prev.l - curr.l;
133
+ var pdm = 0;
134
+ var mdm = 0;
135
+ if (hph > pll && hph > 0)
136
+ pdm = hph;
137
+ if (pll > hph && pll > 0)
138
+ mdm = pll;
139
+ // Wilder's Smoothing (Average form)
140
+ newSmoothTr = (preList.smoothTr * (type - 1) + tr) / type;
141
+ newSmoothPdm = (preList.smoothPdm * (type - 1) + pdm) / type;
142
+ newSmoothMdm = (preList.smoothMdm * (type - 1) + mdm) / type;
143
+ }
144
+ // Calculate DI
145
+ // Avoid division by zero
146
+ var pDi = newSmoothTr === 0 ? 0 : (newSmoothPdm / newSmoothTr) * 100;
147
+ var mDi = newSmoothTr === 0 ? 0 : (newSmoothMdm / newSmoothTr) * 100;
148
+ // Calculate DX
149
+ var diDiff = Math.abs(pDi - mDi);
150
+ var diSum = pDi + mDi;
151
+ var dx = diSum === 0 ? 0 : (diDiff / diSum) * 100;
152
+ // ADX Logic
153
+ var dxBuffer = __spreadArray([], preList.dxBuffer, true);
154
+ var adx = preList.adx;
155
+ var newSmoothAdx = preList.smoothAdx;
156
+ if (dxBuffer.length < type) {
157
+ dxBuffer.push(dx);
158
+ // Special case: if we Just reached 'type' count, we can calc initial ADX
159
+ if (dxBuffer.length === type) {
160
+ // First ADX is average of the DX buffer?
161
+ // "ADX is the 14-day smoothed average of DX".
162
+ // First value is simple average of previous 14 DX values.
163
+ var sumDx = dxBuffer.reduce(function (a, b) { return a + b; }, 0);
164
+ newSmoothAdx = sumDx / type;
165
+ adx = newSmoothAdx;
166
+ }
167
+ else {
168
+ // Not enough data for ADX yet
169
+ adx = 0;
170
+ }
171
+ }
172
+ else {
173
+ // We already have ADX initialized, so we smooth it
174
+ // Note: we don't need to keep growing dxBuffer indefinitely.
175
+ // We just needed it for startup.
176
+ // Update ADX using Wilder's smoothing
177
+ newSmoothAdx = (preList.smoothAdx * (type - 1) + dx) / type;
178
+ adx = newSmoothAdx;
179
+ }
180
+ return __assign(__assign({}, preList), { pDi: pDi, // +DI
181
+ mDi: mDi, // -DI
182
+ adx: adx, smoothTr: newSmoothTr, smoothPdm: newSmoothPdm, smoothMdm: newSmoothMdm, dxBuffer: dxBuffer, smoothAdx: newSmoothAdx });
183
+ }
184
+ }
185
+ });
186
+ // Helper to get formatted results similar to ma.ts
187
+ Object.defineProperty(Dmi.prototype, "calculateDmiValues", {
188
+ enumerable: false,
189
+ configurable: true,
190
+ writable: true,
191
+ value: function (list, period) {
192
+ if (period === void 0) { period = 14; }
193
+ var res = [];
194
+ var state = this.init(list[0], period);
195
+ // First point (index 0) has 0 DMI
196
+ res.push(__assign(__assign({}, list[0]), { pDi: 0, mDi: 0, adx: 0 }));
197
+ for (var i = 1; i < list.length; i++) {
198
+ state = this.next(list[i], state, period);
199
+ res.push(__assign(__assign({}, list[i]), { pDi: state.pDi, mDi: state.mDi, adx: state.adx }));
200
+ }
201
+ return res;
202
+ }
203
+ });
204
+ return Dmi;
205
+ }());
206
+ exports.default = Dmi;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var dmi_1 = require("./dmi");
4
+ var test_data_test_1 = require("./test_data.test");
5
+ describe("test dmi methods", function () {
6
+ it("test init & next", function () {
7
+ var dmi = new dmi_1.default();
8
+ var period = 14;
9
+ // Calculate all values using loop
10
+ var results = dmi.calculateDmiValues(test_data_test_1.default, period);
11
+ var lastResult = results[results.length - 1];
12
+ // Verify consistency
13
+ // Re-run step-by-step
14
+ var state = dmi.init(test_data_test_1.default[0], period);
15
+ for (var i = 1; i < test_data_test_1.default.length; i++) {
16
+ state = dmi.next(test_data_test_1.default[i], state, period);
17
+ }
18
+ expect(state.pDi).toEqual(lastResult.pDi);
19
+ expect(state.mDi).toEqual(lastResult.mDi);
20
+ expect(state.adx).toEqual(lastResult.adx);
21
+ });
22
+ it("test values consistency (basic sanity)", function () {
23
+ // Generate a simple synthetic dataset where Trend is obvious
24
+ // Upward trend -> +DI should be high, -DI low
25
+ var upTrendData = [];
26
+ for (var i = 0; i < 50; i++) {
27
+ upTrendData.push({
28
+ c: 10 + i,
29
+ h: 11 + i,
30
+ l: 9 + i,
31
+ o: 10 + i,
32
+ v: 1000,
33
+ t: 20210101 + i,
34
+ });
35
+ }
36
+ var dmi = new dmi_1.default();
37
+ var res = dmi.calculateDmiValues(upTrendData, 14);
38
+ var last = res[res.length - 1];
39
+ // +DI should be dominant
40
+ expect(last.pDi).toBeGreaterThan(last.mDi);
41
+ // ADX should be high (strong trend)
42
+ expect(last.adx).toBeGreaterThan(20);
43
+ });
44
+ it("test flat trend", function () {
45
+ // Flat data
46
+ var flatData = [];
47
+ for (var i = 0; i < 50; i++) {
48
+ flatData.push({
49
+ c: 10,
50
+ h: 11,
51
+ l: 9,
52
+ o: 10,
53
+ v: 1000,
54
+ t: 20210101 + i,
55
+ });
56
+ }
57
+ var dmi = new dmi_1.default();
58
+ var res = dmi.calculateDmiValues(flatData, 14);
59
+ var last = res[res.length - 1];
60
+ // No directional movement
61
+ // h-ph = 0, pl-l = 0.
62
+ // +DM = 0, -DM = 0.
63
+ // +DI = 0, -DI = 0.
64
+ // ADX = 0?
65
+ // DX = 0.
66
+ expect(last.pDi).toEqual(0);
67
+ expect(last.mDi).toEqual(0);
68
+ // ADX might be 0 or close to 0
69
+ expect(last.adx).toEqual(0);
70
+ });
71
+ });
@@ -15,7 +15,7 @@ interface IchimokuType {
15
15
  init: (data: NewStockType) => IchimokuResType;
16
16
  next: (data: NewStockType, preList: IchimokuResType) => IchimokuResType;
17
17
  }
18
- export default class IchimokuCloud implements IchimokuType {
18
+ export default class Ichimoku implements IchimokuType {
19
19
  init(data: NewStockType): IchimokuResType;
20
20
  /**
21
21
  * 優化說明:
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- var IchimokuCloud = /** @class */ (function () {
4
- function IchimokuCloud() {
3
+ var Ichimoku = /** @class */ (function () {
4
+ function Ichimoku() {
5
5
  }
6
- Object.defineProperty(IchimokuCloud.prototype, "init", {
6
+ Object.defineProperty(Ichimoku.prototype, "init", {
7
7
  enumerable: false,
8
8
  configurable: true,
9
9
  writable: true,
@@ -21,7 +21,7 @@ var IchimokuCloud = /** @class */ (function () {
21
21
  * 如果你的框架 (如 React state) 強制要求 immutable,則需要改回 [...prev, data] 的寫法。
22
22
  * 下面的寫法假設可以 Mutation (這在 Class 內部運算或 Backend 處理很常見)。
23
23
  */
24
- Object.defineProperty(IchimokuCloud.prototype, "next", {
24
+ Object.defineProperty(Ichimoku.prototype, "next", {
25
25
  enumerable: false,
26
26
  configurable: true,
27
27
  writable: true,
@@ -38,7 +38,7 @@ var IchimokuCloud = /** @class */ (function () {
38
38
  }
39
39
  });
40
40
  // 核心計算邏輯
41
- Object.defineProperty(IchimokuCloud.prototype, "calcIchimoku", {
41
+ Object.defineProperty(Ichimoku.prototype, "calcIchimoku", {
42
42
  enumerable: false,
43
43
  configurable: true,
44
44
  writable: true,
@@ -66,7 +66,7 @@ var IchimokuCloud = /** @class */ (function () {
66
66
  * 1. 移除 .slice(),避免產生 Garbage Collection。
67
67
  * 2. 使用反向迴圈 (i--),通常在 JS 引擎中微幅快一點,且語意上是「從現在往回看」。
68
68
  */
69
- Object.defineProperty(IchimokuCloud.prototype, "getMidPrice", {
69
+ Object.defineProperty(Ichimoku.prototype, "getMidPrice", {
70
70
  enumerable: false,
71
71
  configurable: true,
72
72
  writable: true,
@@ -91,6 +91,6 @@ var IchimokuCloud = /** @class */ (function () {
91
91
  return (maxH + minL) / 2;
92
92
  }
93
93
  });
94
- return IchimokuCloud;
94
+ return Ichimoku;
95
95
  }());
96
- exports.default = IchimokuCloud;
96
+ exports.default = Ichimoku;
@@ -17,7 +17,7 @@ var ichimoku_1 = require("./ichimoku");
17
17
  var createStock = function (idx, override) {
18
18
  return __assign({ t: idx, o: 100, c: 100, h: 100, l: 100, v: 1000 }, override);
19
19
  };
20
- (0, vitest_1.describe)("IchimokuCloud Algo", function () {
20
+ (0, vitest_1.describe)("Ichimoku Algo", function () {
21
21
  var ichimoku;
22
22
  (0, vitest_1.beforeEach)(function () {
23
23
  ichimoku = new ichimoku_1.default();
@@ -21,6 +21,7 @@ export { default as Williams } from "./stockSkills/williams.js";
21
21
  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
+ export { default as Dmi } from "./stockSkills/dmi.js";
24
25
  export { add } from "./test/add.js";
25
26
  export { minus } from "./test/minus.js";
26
27
  export { default as calculateDivisionFactor } from "./utils/calculateDivisionFactor.js";
package/dist/esm/index.js CHANGED
@@ -24,6 +24,7 @@ export { default as Williams } from "./stockSkills/williams.js";
24
24
  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
+ export { default as Dmi } from "./stockSkills/dmi.js";
27
28
  export { add } from "./test/add.js";
28
29
  export { minus } from "./test/minus.js";
29
30
  export { default as calculateDivisionFactor } from "./utils/calculateDivisionFactor.js";
@@ -0,0 +1,28 @@
1
+ import { StockListType, StockType } from "./types";
2
+ export type DmiResType = {
3
+ dataset: StockListType;
4
+ pDi: number;
5
+ mDi: number;
6
+ adx: number;
7
+ type: number;
8
+ smoothTr: number;
9
+ smoothPdm: number;
10
+ smoothMdm: number;
11
+ dxBuffer: number[];
12
+ smoothAdx: number;
13
+ };
14
+ export default class Dmi {
15
+ init(data: StockType, type: number): DmiResType;
16
+ next(data: StockType, preList: DmiResType, type: number): DmiResType;
17
+ calculateDmiValues(list: StockListType, period?: number): {
18
+ pDi: number;
19
+ mDi: number;
20
+ adx: number;
21
+ c: number;
22
+ v: number;
23
+ l: number;
24
+ h: number;
25
+ o: number;
26
+ t: number;
27
+ }[];
28
+ }
@@ -0,0 +1,204 @@
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 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
13
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
14
+ if (ar || !(i in from)) {
15
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
16
+ ar[i] = from[i];
17
+ }
18
+ }
19
+ return to.concat(ar || Array.prototype.slice.call(from));
20
+ };
21
+ var Dmi = /** @class */ (function () {
22
+ function Dmi() {
23
+ }
24
+ Object.defineProperty(Dmi.prototype, "init", {
25
+ enumerable: false,
26
+ configurable: true,
27
+ writable: true,
28
+ value: function (data, type) {
29
+ return {
30
+ dataset: [data],
31
+ pDi: 0,
32
+ mDi: 0,
33
+ adx: 0,
34
+ type: type,
35
+ smoothTr: 0,
36
+ smoothPdm: 0,
37
+ smoothMdm: 0,
38
+ dxBuffer: [],
39
+ smoothAdx: 0,
40
+ };
41
+ }
42
+ });
43
+ Object.defineProperty(Dmi.prototype, "next", {
44
+ enumerable: false,
45
+ configurable: true,
46
+ writable: true,
47
+ value: function (data, preList, type) {
48
+ preList.dataset.push(data);
49
+ // Need type + 1 data points to have 'type' periods of change
50
+ if (preList.dataset.length < type + 1) {
51
+ return __assign(__assign({}, preList), { pDi: 0, mDi: 0, adx: 0 });
52
+ }
53
+ else {
54
+ var currentTr = 0;
55
+ var currentPdm = 0;
56
+ var currentMdm = 0;
57
+ // Logic to get TR, +DM, -DM for the NEWEST data point
58
+ // We need the newest point and the one before it.
59
+ // If we are in the initialization phase (length === type + 1), we process the whole window.
60
+ // If we are in the incremental phase (length > type + 1), we just process the last step.
61
+ var newSmoothTr = preList.smoothTr;
62
+ var newSmoothPdm = preList.smoothPdm;
63
+ var newSmoothMdm = preList.smoothMdm;
64
+ if (preList.dataset.length === type + 1) {
65
+ // Initialization: Calculate sum of first N periods (using N+1 data points)
66
+ var sumTr = 0;
67
+ var sumPdm = 0;
68
+ var sumMdm = 0;
69
+ for (var i = 1; i <= type; i++) {
70
+ var curr = preList.dataset[i];
71
+ var prev = preList.dataset[i - 1];
72
+ // TR
73
+ var hl = curr.h - curr.l;
74
+ var hpc = Math.abs(curr.h - prev.c);
75
+ var lpc = Math.abs(curr.l - prev.c);
76
+ var tr = Math.max(hl, hpc, lpc);
77
+ // DM
78
+ var hph = curr.h - prev.h;
79
+ var pll = prev.l - curr.l;
80
+ var pdm = 0;
81
+ var mdm = 0;
82
+ if (hph > pll && hph > 0) {
83
+ pdm = hph;
84
+ }
85
+ if (pll > hph && pll > 0) {
86
+ mdm = pll;
87
+ }
88
+ sumTr += tr;
89
+ sumPdm += pdm;
90
+ sumMdm += mdm;
91
+ }
92
+ // Wilder's first value is often just the Sum.
93
+ // But to make it consistent with the "Average" view for the formula:
94
+ // NextAvg = (PrevAvg * (N-1) + Curr) / N
95
+ // The first "PrevAvg" acts as the seed. The seed is usually the Simple Average.
96
+ // So we divide by type.
97
+ newSmoothTr = sumTr; // Some sources say keep Sum. But standard indicators often normalize to Average range.
98
+ // Let's check RSI implementation. RSI divides by type: gains / type.
99
+ // So we will divide by type to get the Average TR/DM.
100
+ // Wait! DMI standard often keeps the SUM for the first value?
101
+ // Wilder's book: "+DM14 is the sum of the +DM for the last 14 days".
102
+ // Then subsequent: "+DM14_today = +DM14_yesterday - (+DM14_yesterday/14) + +DM_today".
103
+ // This formula maintains the "Sum" magnitude (approx 14x the average).
104
+ // BUT, RSI implementation uses Average magnitude (0-100 range inputs usually lead to small AvgGain).
105
+ // Let's stick to the RSI pattern: Average.
106
+ // Formula: (Avg * (N-1) + Curr) / N. This maintains "Average" magnitude.
107
+ // If we used Sum logic: (Sum - Sum/N + Curr) = Sum * (1 - 1/N) + Curr.
108
+ // These are mathematically consistent in shape, just scaled by N.
109
+ // DI calculation is (Pdm / Tr) * 100. The scale cancels out!
110
+ // So using Average is safer for preventing overflow and easier to debug (per-day values).
111
+ newSmoothTr = sumTr / type;
112
+ newSmoothPdm = sumPdm / type;
113
+ newSmoothMdm = sumMdm / type;
114
+ }
115
+ else {
116
+ // Shift if needed to keep dataset size manageable, though strictly we only need last 2 points
117
+ // reusing rsi pattern:
118
+ if (preList.dataset.length > type + 1) {
119
+ preList.dataset.shift();
120
+ }
121
+ var curr = preList.dataset[preList.dataset.length - 1];
122
+ var prev = preList.dataset[preList.dataset.length - 2];
123
+ // TR
124
+ var hl = curr.h - curr.l;
125
+ var hpc = Math.abs(curr.h - prev.c);
126
+ var lpc = Math.abs(curr.l - prev.c);
127
+ var tr = Math.max(hl, hpc, lpc);
128
+ // DM
129
+ var hph = curr.h - prev.h;
130
+ var pll = prev.l - curr.l;
131
+ var pdm = 0;
132
+ var mdm = 0;
133
+ if (hph > pll && hph > 0)
134
+ pdm = hph;
135
+ if (pll > hph && pll > 0)
136
+ mdm = pll;
137
+ // Wilder's Smoothing (Average form)
138
+ newSmoothTr = (preList.smoothTr * (type - 1) + tr) / type;
139
+ newSmoothPdm = (preList.smoothPdm * (type - 1) + pdm) / type;
140
+ newSmoothMdm = (preList.smoothMdm * (type - 1) + mdm) / type;
141
+ }
142
+ // Calculate DI
143
+ // Avoid division by zero
144
+ var pDi = newSmoothTr === 0 ? 0 : (newSmoothPdm / newSmoothTr) * 100;
145
+ var mDi = newSmoothTr === 0 ? 0 : (newSmoothMdm / newSmoothTr) * 100;
146
+ // Calculate DX
147
+ var diDiff = Math.abs(pDi - mDi);
148
+ var diSum = pDi + mDi;
149
+ var dx = diSum === 0 ? 0 : (diDiff / diSum) * 100;
150
+ // ADX Logic
151
+ var dxBuffer = __spreadArray([], preList.dxBuffer, true);
152
+ var adx = preList.adx;
153
+ var newSmoothAdx = preList.smoothAdx;
154
+ if (dxBuffer.length < type) {
155
+ dxBuffer.push(dx);
156
+ // Special case: if we Just reached 'type' count, we can calc initial ADX
157
+ if (dxBuffer.length === type) {
158
+ // First ADX is average of the DX buffer?
159
+ // "ADX is the 14-day smoothed average of DX".
160
+ // First value is simple average of previous 14 DX values.
161
+ var sumDx = dxBuffer.reduce(function (a, b) { return a + b; }, 0);
162
+ newSmoothAdx = sumDx / type;
163
+ adx = newSmoothAdx;
164
+ }
165
+ else {
166
+ // Not enough data for ADX yet
167
+ adx = 0;
168
+ }
169
+ }
170
+ else {
171
+ // We already have ADX initialized, so we smooth it
172
+ // Note: we don't need to keep growing dxBuffer indefinitely.
173
+ // We just needed it for startup.
174
+ // Update ADX using Wilder's smoothing
175
+ newSmoothAdx = (preList.smoothAdx * (type - 1) + dx) / type;
176
+ adx = newSmoothAdx;
177
+ }
178
+ return __assign(__assign({}, preList), { pDi: pDi, // +DI
179
+ mDi: mDi, // -DI
180
+ adx: adx, smoothTr: newSmoothTr, smoothPdm: newSmoothPdm, smoothMdm: newSmoothMdm, dxBuffer: dxBuffer, smoothAdx: newSmoothAdx });
181
+ }
182
+ }
183
+ });
184
+ // Helper to get formatted results similar to ma.ts
185
+ Object.defineProperty(Dmi.prototype, "calculateDmiValues", {
186
+ enumerable: false,
187
+ configurable: true,
188
+ writable: true,
189
+ value: function (list, period) {
190
+ if (period === void 0) { period = 14; }
191
+ var res = [];
192
+ var state = this.init(list[0], period);
193
+ // First point (index 0) has 0 DMI
194
+ res.push(__assign(__assign({}, list[0]), { pDi: 0, mDi: 0, adx: 0 }));
195
+ for (var i = 1; i < list.length; i++) {
196
+ state = this.next(list[i], state, period);
197
+ res.push(__assign(__assign({}, list[i]), { pDi: state.pDi, mDi: state.mDi, adx: state.adx }));
198
+ }
199
+ return res;
200
+ }
201
+ });
202
+ return Dmi;
203
+ }());
204
+ export default Dmi;
@@ -0,0 +1 @@
1
+ export {};