在看我这篇文章之前,先看看关于KDJ的相关资料和背景。下面的链接可以参考。
http://www.shenmeshi.com/Business/Business_20070523005553.html
简单的说,KDJ 有四个要计算的东西。RSV ,K, D, J
RSV: 中文翻译过来就是 未成熟值,这个值实际上也不神秘。
它其实就是著名的威廉指数。计算公式如下:
设:周期为 Period
RSV[i] = (close[i] - low[i, Period]) / (high[i, Period] - low[i, Period])
这个计算也是这个指标的核心部分,K D J 这三个参数都依赖与 RSV.
我举个例子,关于如果计算 RSV
假设,下面是一个日线
9 8 7 6 5 4 3 2 1 0 (i) 表示离今天的天数
3 1 2 1 2 3 4 1 2 4 (price) 表示价格
最右边的就是今天的价格,为 4元
我设置 周期为 Period = 3
low[0, 3] = min(price[0], price[1], price[2]) 往前数3天,包括今天,然后求价格的最小值
low[0, 3] = min(4, 2 , 1) = 1
同样:
high[0, 3] = max (4, 2, 1) = 4
close[i] 就是当天收盘价格 close[0] = 4
带入上面的公式就可以求出 RSV
RSV[i] = (4 - 1)/ (4 - 1) * 100 = 100
这个RSV 是和超买超买相关的一个值。
有了这RSV,其他的就很容易计算
K[i] = (2/3) * K[i + 1] + (1/3) * RSV[i] 注意,如果i 表示今天,那么 i+ 1 就表示昨天
D[i] = (2/3) * D[i + 1] + (1/3) * K[i]
J[i] = 3D[i] - 2K[i]
你会发现这样一个事实,那就是如果 RSV[i] 大了 20, 那么只有 1/3 被传递到 K[i]
只有 1/9 被传递到 D[i], 所以,后面的K , D 的变化节奏会比 RSV 慢一些。
//
+------------------------------------------------------------------+
//
| KDJ.mq4 |
//
|
http://www.metaquotes.net
|
//
+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_minimum
0
#property indicator_maximum
100
#property indicator_buffers
8
#property indicator_level1
20
#property indicator_level2
80
#property indicator_level3
50
#property indicator_color1 MediumSlateBlue
#property indicator_color2
0x00ff00
#property indicator_color3 Red
#property indicator_color4 Yellow
//
---- input parameters
extern
int
KdjPeriod
=
30
;
//
---- buffers
double
RSV[],K[],D[],J[];
//
+------------------------------------------------------------------+
//
| Custom indicator initialization function |
//
+------------------------------------------------------------------+
int
init()
{
string
short_name;
short_name
=
"
KDJ(
"
+
KdjPeriod
+
"
)
"
+
"
King Wang
"
;
IndicatorShortName(short_name);
SetIndexLabel(
0
,
"
RSV:
"
);
SetIndexLabel(
1
,
"
K
"
);
SetIndexLabel(
2
,
"
D:
"
);
SetIndexLabel(
3
,
"
J
"
);
IndicatorDigits(Digits
-
2
);
SetIndexStyle(
0
,DRAW_LINE);
SetIndexBuffer(
0
,RSV);
SetIndexStyle(
1
,DRAW_LINE);
SetIndexBuffer(
1
,K);
SetIndexStyle(
2
,DRAW_LINE);
SetIndexBuffer(
2
,D);
SetIndexStyle(
3
,DRAW_LINE);
SetIndexBuffer(
3
,J);
return
(
0
);
}
//
+------------------------------------------------------------------+
//
| Custom indicator deinitialization function |
//
+------------------------------------------------------------------+
int
deinit()
{
return
(
0
);
}
//
+------------------------------------------------------------------+
//
| Custom indicator iteration function |
//
+------------------------------------------------------------------+
int
start()
{
int
counted_bars
=
IndicatorCounted();
if
(counted_bars
<
0
) {
Alert(
"
IndicatorCounted error.
"
);
return
;
}
int
i;
if
(Bars
<=
KdjPeriod)
return
(
0
);
int
limit
=
Bars
-
counted_bars
-
1
;
i
=
limit;
double MaxHigh=0,MinLow=0;
while
(i
>=
0
)
{
MaxHigh
=
High[iHighest(NULL,
0
,MODE_HIGH, KdjPeriod, i)];
MinLow
=
Low[iLowest(NULL,
0
,MODE_LOW, KdjPeriod, i)];
RSV[i]
=
(Close[i]
-
MinLow)
/
(MaxHigh
-
MinLow)
*
100
;
i
--
;
}
i
=
limit;
while
(i
>=
0
)
{
if
(i
==
Bars
-
1
) {
//
第一个点
K[i]
=
RSV[i];
i
--
;
continue
;
}
K[i]
=
(
2
*
K[i
+
1
]
+
RSV[i])
/
3
;
i
--
;
}
i
=
limit;
while
(i
>=
0
)
{
if
(i
==
Bars
-
1
) {
//
第一个点
D[i]
=
RSV[i];
i
--
;
continue
;
}
D[i]
=
(
2
*
D[i
+
1
]
+
K[i])
/
3
;
i
--
;
}
i
=
limit;
while
(i
>=
0
)
{
J[i]
=
3
*
D[i]
-
2
*
K[i];
if
(J[i]
<
0
) J[i]
=
0
;
if
(J[i]
>
100
) J[i]
=
100
;
i
--
;
}
return
(
0
);
}