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

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

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

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

左侧图中,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。

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线。

左侧图中,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。

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线包含关系处理的顺序

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

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

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

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

在处理过程中,如果前面两条K线合并后产生的新K线和第三条K线存在包含关系,则可将此现象称为“多条顺次包含K线的合并”。
在经过K线包含关系处理后,K线图中不能再存在包含关系,如果存在,则说明处理得不够彻底,应继续用包含关系处理规则来处理,直至K线图中不再存在包含关系;如果不存在,则按照正常K线图来分析。

操作提示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
|