草根之明

管理及技术博客

0%

缠论形态学之K线

K线的包含关系

K线的包含关系,是指一条K线的高低点完全在另一条K线高低点范围之内,那么这两条K线之间的关系就是包含关系

image-20220410161608318

在K线形态中,有7种包含关系排列

image-20220410162047346

对于不属于包含关系的3条相邻的K线,可以将其分为4种:上升K线、下降K线、顶分型、底分型

image-20220410162343467

K线的包含关系处理

向上处理

假设K线1和K线2无包含关系,K线2和K线3存在包含关系,K线2比K线1高,则进行向上包含关系处理(简称向上处理)。

image-20220416091159720

左侧图中,K线A1和K线A2不属于包含关系,K线A2和K线A3属于包含关系,K线A2比K线A1高,进行向上处理。在处理中,取K线A2和K线A3的最高点为高点,取低点中的较高者为低点,然后将两条K线合并为新的K线A4。

右侧图中,K线B2比K线B1高,进行向上处理,即对K线B2和K线B3进行向上处理,两者合并为新的K线B4。

image-20220416091604751

K线B的高点比K线A的高点要高,且K线B与K线C为包含关系,应进行向上处理;K线E的高点比K线D的高点要高,且K线E与K线F为包含关系,应进行向上处理。

向下处理

假设K线1和K线2无包含关系,K线2和K线3存在包含关系,K线2比K线1低,进行向下包含关系处理(简称向下处理)

处理规则为:将存在包含关系的两条K线的最低点视为新K线的低点,将两条K线的高点中的较低者为新K线的高点,这样就把两条K线合并为一条新的K线。

image-20220416091706145

左侧图中,K线A1和K线A2不属于包含关系,K线A2和K线A3属于包含关系,K线A2比K线A1低,进行向下处理。在处理中,取K线A2和K线A3的最低点为低点,取K线A2和K线A3的高点中的较低者为高点,然后将两条K线合并为新的K线A4。

右侧图中,K线B2比K线B1低,进行向下处理,即对K线B2和K线B3进行向下处理,两者合并为新的K线B4。

image-20220416092029849

K线B的高点比K线A的高点低,且K线B与K线C为包含关系,应进行向下处理;K线E的高点比K线D的高点低,且K线E与K线F为包含关系,应进行向下处理。

在缠论中关于K线合并方向是这么描述的:“假设,第n条K线满足第n条与第n+1条的包含关系,而第n条与第n-1条不是包含关系,那么,如果第n条K线的高点大于第n-1条K线的高点,则称第n-1、n、n+1条K线是向上的;如果第n条K线的低点小于第n-1条K线的低点,则称第n-1、n、n+1条K线是向下的。”

K线包含关系处理的顺序

image-20220416092655343

(1)确定合并方向。在图中,K线A与K线B之间不存在包含关系,K线B与K线C之间存在包含关系,判断K线B与K线C的合并方向:如果K线B的最高点高于K线A的最高点,进行向上处理;如果K线B的最高点低于K线A的最高点,则进行向下处理。在该图中,明显要进行向上处理。

image-20220416092803914

(2)处理K线B与K线C之间的包含关系,形成新的K线E,如图所示。判断K线E和K线D之间是否存在包含关系。

image-20220416092918798

(3)K线E的高低点都处于K线D的高低点范围之内,两者之间存在包含关系,应进一步处理。新K线E的高点比K线A高,应进行向上处理,两条K线合并后形成新K线F

image-20220416093014773

(4)如图所示,在经过K线包含关系处理后,图中只剩下K线A与K线F

image-20220416093146597

在处理过程中,如果前面两条K线合并后产生的新K线和第三条K线存在包含关系,则可将此现象称为“多条顺次包含K线的合并”。

在经过K线包含关系处理后,K线图中不能再存在包含关系,如果存在,则说明处理得不够彻底,应继续用包含关系处理规则来处理,直至K线图中不再存在包含关系;如果不存在,则按照正常K线图来分析。

image-20220416093319760

操作提示1:K线A与K线B之间存在包含关系,K线A的高点明显比前一条K线M的高点低,则K线A与K线B应向下处理;取A、B两条K线高点中的较低者为高点,取两条K线低点的最低者为低点,按照包含关系处理规则,将其合并为一条新K线C。

操作提示2:判断新K线C与K线D的关系,K线C的高低点在K线D的高低点范围内,两者为包含关系。由于K线C的高点比K线M的高点低,则K线C与K线D取向下处理,以两条K线高点中的较低者为高点,以两条K线低点的最低者为低点,按照包含关系处理规则,将其合并为一条新K线F。

操作总结:在实战中,处理K线的包含关系时,一定以顺序为原则,一步步进行处理,直到K线图中无包含关系。当然,为了减少工作量,可只处理K线图中处于重要位置的K线的包含关系。多条K线间存在顺次包含关系时,也要严格遵守顺序原则。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def k_to_chanlun(self, dailies_df):
# K线处理成缠论所需K线
res_list = []
for i in range(0, len(dailies_df) - 1):
res_dict = dailies_df.iloc[i].to_dict()
if res_dict['open'] > res_dict['close']:
open_ = res_dict['high']
close_ = res_dict['low']
direction_ = 'down'
else:
open_ = res_dict['low']
close_ = res_dict['high']
direction_ = 'up'

rawbar = RawBar(ts_code=res_dict['ts_code'], trade_date=res_dict['trade_date'], freq=Freq.D,
open=res_dict['open'], close=res_dict['close'], high=res_dict['high'],
low=res_dict['low'], vol=res_dict['vol'], pre_close=res_dict['pre_close'],
change=res_dict['change'], pct_chg=res_dict['pct_chg'], amount=res_dict['amount'])

res_list.append(NewBar(ts_code=res_dict['ts_code'], trade_date=res_dict['trade_date'], freq=Freq.D,
high=res_dict['high'], low=res_dict['low'], open=open_, close=close_,
direction=direction_, vol=res_dict['vol'], elements=[rawbar]))
return res_list
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# 缠论K线转换为包含关系的缠论k线
def update_chanlun_k(self, stock_list):
new_bar = []
for i in range(0, len(stock_list) - 2):
n1 = i
n2 = i + 1
k1 = stock_list[n1] if len(new_bar) < 2 else new_bar[-2]
k2 = stock_list[n2] if len(new_bar) < 2 else new_bar[-1]
k3 = stock_list[n2]
if len(new_bar) == 0:
# 判断 k1 和 k2 之间是否存在包含关系,有则去除并跳过
res = self._is_include(k1, k2)
new_bar.extend(res)
else:
# 判断 k2 和 k3 之间是否存在包含关系,有则处理; 其中k1和k2为没有包含关系的K线
has_include, k3 = self._remove_include(k1, k2, k3)
if has_include:
new_bar[-1] = k3
else:
new_bar.append(k3)
self.bars_ubi = new_bar

# 判断 k1 和 k2 之间是否存在包含关系,有则跳过
def _is_include(self, k1, k2):
if (k1.high <= k2.high and k1.low >= k2.low) or \
(k1.high >= k2.high and k1.low <= k2.low):
# 开始两根k线有包含关系,但无法判断方向,处理为去掉
return []
return [k1, k2]

# 判断 k2 和 k3 之间是否存在包含关系,有则处理; 其中k1和k2为没有包含关系的K线
def _remove_include(self, k1, k2, k3):
# 判断 k2 和 k3 之间是否存在包含关系,有则处理; 其中k1和k2为没有包含关系的K线
# 判断 是向上包含还是向下包含
if k1.high < k2.high:
direction = Direction.Up
elif k1.high > k2.high:
direction = Direction.Down
else:
raise ValueError

# 判断 k2 和 k3 之间是否存在包含关系,有则处理
if (k2.high <= k3.high and k2.low >= k3.low) or (k2.high >= k3.high and k2.low <= k3.low):
if direction == Direction.Up:
high = max(k2.high, k3.high)
low = max(k2.low, k3.low)
trade_date = k2.trade_date if k2.high > k3.high else k3.trade_date
elif direction == Direction.Down:
high = min(k2.high, k3.high)
low = min(k2.low, k3.low)
trade_date = k2.trade_date if k2.low < k3.low else k3.trade_date
else:
raise ValueError

if k3.open > k3.close:
open_ = high
close_ = low
else:
open_ = low
close_ = high
vol_ = k2.vol + k3.vol
# 这里有一个隐藏Bug,len(k2.elements) 在一些及其特殊的场景下会有超大的数量,具体问题还没找到;
# 临时解决方案是直接限定len(k2.elements)<=100
elements_ = [x for x in k2.elements[:100] if x.trade_date != k3.trade_date] + [k3]
k4 = NewBar(ts_code=k3.ts_code, trade_date=trade_date, freq=Freq.D, high=high, low=low, open=open_,
close=close_, direction=direction, vol=vol_, elements=elements_)
return True, k4
else:
return False, k3