在看我这篇文章之前,先看看关于KDJ的相关资料和背景。下面的链接可以参考。
简单的说,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 |
// +------------------------------------------------------------------+
// | 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;
#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 );
}
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 );
}