stock-indicator
Version:
Stock Indicator Library
64 lines (57 loc) • 1.6 kB
text/typescript
import {
TMixed,
checkArrayOfNumbers,
checkNumber,
funRound,
funSMA,
} from "../common";
/**
* - KDJ 随机指标
* @param {number[]} CLOSE - 收盘价序列
* @param {number[]} HIGH - 最高价序列
* @param {number[]} LOW - 最低价序列
* @param {number} N - 周期,default: 9
* @param {number} M1 - 平滑参数,default: 3
* @param {number} M2 - 平滑参数,default: 3
* @returns {{ K: TMixed[]; D: TMixed[]; J: TMixed[] }}
*/
export function KDJ(
CLOSE: number[],
HIGH: number[],
LOW: number[],
N: number = 9,
M1: number = 3,
M2: number = 3
): { K: TMixed[]; D: TMixed[]; J: TMixed[] } {
// - check input parameters
checkArrayOfNumbers(CLOSE, "CLOSE");
checkArrayOfNumbers(HIGH, "HIGH");
checkArrayOfNumbers(LOW, "LOW");
checkNumber(N, 1, CLOSE, "N", "CLOSE");
checkNumber(M1, 1, N, "M1", "N");
checkNumber(M2, 1, N, "M2", "N");
// - calculate KDJ
const llv = LOW.reduce((prev: number[], cur, i) => {
return [
...prev,
Math.min(...LOW.slice(Math.max(0, i - N + 1), i + 1).map((v) => v ?? 0)),
];
}, []);
const hhv = HIGH.reduce((prev: number[], cur, i) => {
return [
...prev,
Math.max(...HIGH.slice(Math.max(0, i - N + 1), i + 1).map((v) => v ?? 0)),
];
}, []);
const RSV = CLOSE.map(
(v, i) => (((v ?? 0) - llv[i]) / (hhv[i] - llv[i])) * 100
);
const K = funSMA(RSV, M1, 1);
const D = funSMA(K, M2, 1);
const J = K.map((v, i) => funRound(3 * (v ?? 0) - 2 * (D[i] ?? 0), 3));
return {
K: K.map((v) => funRound(v, 3)),
D: D.map((v) => funRound(v, 3)),
J,
};
}