算法代碼傳到這github
demo:StockChart
五鸳惯、KDJ
通過一個(gè)特定的周期(常為9日、9周等)內(nèi)出現(xiàn)過的最高價(jià)韩玩、最低價(jià)及最后一個(gè)計(jì)算周期的收盤價(jià)及這三者之間的比例關(guān)系蔬胯,來計(jì)算最后一個(gè)計(jì)算周期的未成熟隨機(jī)值RSV,然后根據(jù)平滑移動(dòng)平均線的方法來計(jì)算K值重贺、D值與J值
計(jì)算方式 (摘抄自百度百科)
KDJ的計(jì)算比較復(fù)雜暑脆,首先要計(jì)算周期(n日、n周等)的RSV值跛锌,即未成熟值,然后再計(jì)算K值届惋、D值髓帽、J值等。以n日KDJ數(shù)值的計(jì)算為例脑豹,其計(jì)算公式為
n日RSV=(Cn-Ln)/(Hn-Ln)×100
公式中郑藏,Cn為第n日收盤價(jià);Ln為n日內(nèi)的最低價(jià)晨缴;Hn為n日內(nèi)的最高價(jià)。
其次峡捡,計(jì)算K值與D值:
當(dāng)日K值=2/3×前一日K值+1/3×當(dāng)日RSV
當(dāng)日D值=2/3×前一日D值+1/3×當(dāng)日K值
若無前一日K 值與D值击碗,則可分別用50來代替筑悴。
J值=3當(dāng)日K值-2當(dāng)日D值
以9日為周期的KD線為例,即未成熟隨機(jī)值稍途,計(jì)算公式為
9日RSV=(C-L9)÷(H9-L9)×100
公式中阁吝,C為第9日的收盤價(jià);L9為9日內(nèi)的最低價(jià)械拍;H9為9日內(nèi)的最高價(jià)突勇。
K值=2/3×第8日K值+1/3×第9日RSV
D值=2/3×第8日D值+1/3×第9日K值
J值=3第9日K值-2第9日D值
/**
* kdj 9,3,3
* N:=9; P1:=3; P2:=3;
* RSV:=(CLOSE-L(LOW,N))/(H(HIGH,N)-L(LOW,N))*100;
* K:SMA(RSV,P1,1);
* D:SMA(K,P2,1);
* J:3*K-2*D;
* @param entries 數(shù)據(jù)集合
* @param n 指標(biāo)周期 9
* @param m 權(quán)重 1
* @param P1 參數(shù)值為3
* @param P2 參數(shù)值為3
* @return
*/
public static List[] getKDJ(List<CandleEntry> entries, int n, int P1, int P2, int m) {
List<Entry> kValue = new ArrayList();
List<Entry> dValue = new ArrayList();
List<Entry> jValue = new ArrayList();
List<Entry> maxs = getPeriodHighest(entries, n);
List<Entry> mins = getPeriodLowest(entries, n);
//確保和 傳入的list size一致,
int size = entries.size() - maxs.size();
for (int i = 0; i < size; i++) {
maxs.add(0, new Entry());
mins.add(0, new Entry());
}
float rsv = 0;
float lastK = 50;
float lastD = 50;
for (int i = n - 1; i < entries.size(); i++) {
float x = entries.get(i).getX();
if (i >= maxs.size())
break;
if (i >= mins.size())
break;
float div = maxs.get(i).getY() - mins.get(i).getY();
if (div == 0) {
//使用上一次的
} else {
rsv = ((entries.get(i).getClose() - mins.get(i).getY())
/ (div)) * 100;
}
float k = countSMA(rsv, P1, m, lastK);
float d = countSMA(k, P2, m, lastD);
float j = 3 * k - 2 * d;
lastK = k;
lastD = d;
kValue.add(new Entry(x, k));
dValue.add(new Entry(x, d));
jValue.add(new Entry(x, j));
}
return new List[]{kValue, dValue, jValue};
}
/**
* SMA(C,N,M) = (M*C+(N-M)*Y')/N
* C=今天收盤價(jià)-昨天收盤價(jià) N=就是周期比如 6或者12或者24坷虑, M=權(quán)重甲馋,一般取1
*
* @param c 今天收盤價(jià)-昨天收盤價(jià)
* @param n 周期
* @param m 1
* @param sma 上一個(gè)周期的sma
* @return
*/
private static float countSMA(float c, float n, float m, float sma) {
return (m * c + (n - m) * sma) / n;
}
/**
* n周期內(nèi)最低值集合
* @param entries
* @param n
* @return
*/
private static List<Entry> getPeriodLowest(List<CandleEntry> entries, int n) {
List<Entry> result = new ArrayList<>();
float minValue = 0;
for (int i = n - 1; i < entries.size(); i++) {
float x = entries.get(i).getX();
for (int j = i - n + 1; j <= i; j++) {
if (j == i - n + 1) {
minValue = entries.get(j).getLow();
} else {
minValue = Math.min(minValue, entries.get(j).getLow());
}
}
result.add(new Entry(x, minValue));
}
return result;
}
/**
* N周期內(nèi)最高值集合
* @param entries
* @param n
* @return
*/
private static List<Entry> getPeriodHighest(List<CandleEntry> entries, int n) {
List<Entry> result = new ArrayList<>();
float maxValue = entries.get(0).getHigh();
for (int i = n - 1; i < entries.size(); i++) {
float x = entries.get(i).getX();
for (int j = i - n + 1; j <= i; j++) {
if (j == i - n + 1) {
maxValue = entries.get(j).getHigh();
} else {
maxValue = Math.max(maxValue, entries.get(j).getHigh());
}
}
result.add(new Entry(x, maxValue));
}
return result;
}
六、RSI
相對強(qiáng)弱指數(shù)RSI是根據(jù)一定時(shí)期內(nèi)上漲點(diǎn)數(shù)和漲跌點(diǎn)數(shù)之和的比率制作出的一種技術(shù)曲線迄损。能夠反映出市場在一定時(shí)期內(nèi)的景氣程度定躏。
計(jì)算方式
RSI:= SMA(MAX(Close-LastClose,0),N,1)/SMA(ABS(Close-LastClose),N,1)*100
(看下面的算法似乎很簡單,但是個(gè)人覺得這個(gè)指標(biāo)計(jì)算反而是比較難纏的一個(gè)芹敌。痊远。。)
/**
* RSI(n)
* RSI(N):= SMA(MAX(Close-LastClose,0),N,1)/SMA(ABS(Close-LastClose),N,1)*100
*
* @param entries
* @param n
* @param m 加權(quán) 1
* @return
*/
public static List<Entry> getRSI(List<CandleEntry> entries, int n, int m) {
List<Entry> result = new ArrayList();
float preIn = 0;
float preAll = 0;
for (int i = 1; i < entries.size(); i++) {
float diff = entries.get(i).getClose() - entries.get(i - 1).getClose();
preIn = countSMA(Math.max(diff, 0), n, m, preIn);
preAll = countSMA(Math.abs(diff), n, m, preAll);
if (i >= n) {
float x = entries.get(i).getX();
result.add(new Entry(x, preIn / preAll * 100));
}
}
return result;
}