add fx strentth
This commit is contained in:
+378
-1
@@ -1130,4 +1130,381 @@ class ChanKLC():
|
||||
else:
|
||||
features['klc_star_pattern'] = 0
|
||||
|
||||
return features
|
||||
# ===== 分型强度特征 =====
|
||||
# 添加分型强度相关特征
|
||||
features['klc_fx_strength'] = self.calculate_fx_strength()
|
||||
features['klc_fx_strength_level'] = self.get_fx_strength_level()
|
||||
features['klc_is_strong_fx'] = 1 if self.is_strong_fx() else 0
|
||||
|
||||
# 分型强度分类特征
|
||||
fx_strength = features['klc_fx_strength']
|
||||
features['klc_fx_strength_extreme'] = 1 if fx_strength >= 80 else 0 # 极强分型
|
||||
features['klc_fx_strength_strong'] = 1 if 60 <= fx_strength < 80 else 0 # 强分型
|
||||
features['klc_fx_strength_medium'] = 1 if 40 <= fx_strength < 60 else 0 # 中等分型
|
||||
features['klc_fx_strength_weak'] = 1 if 20 <= fx_strength < 40 else 0 # 弱分型
|
||||
features['klc_fx_strength_very_weak'] = 1 if fx_strength < 20 else 0 # 极弱分型
|
||||
|
||||
return features
|
||||
|
||||
def calculate_fx_strength(self):
|
||||
"""
|
||||
基于专业缠论理论的分型强度评估体系
|
||||
返回值:0-100的强度分数,数值越大表示分型越强
|
||||
|
||||
评分卡系统(总分29分,转换为100分制):
|
||||
- 振幅比例:25%权重,最高5分
|
||||
- 量能配合:20%权重,最高5分
|
||||
- 均线位置:15%权重,最高5分
|
||||
- 形成速度:10%权重,最高4分
|
||||
- 次级别确认:30%权重,最高10分
|
||||
"""
|
||||
if self.fx == Chan_FX_TYPE.UNKNOWN or not self.pre or not self.next:
|
||||
return 0
|
||||
|
||||
# ===== 一、基础要素确认(先决条件) =====
|
||||
if not self._verify_basic_fx_structure():
|
||||
return 0
|
||||
|
||||
total_score = 0
|
||||
max_score = 29 # 5+5+5+4+10
|
||||
|
||||
# ===== 二、振幅比例评估 (25%权重,最高5分) =====
|
||||
amplitude_score = self._calculate_amplitude_score()
|
||||
total_score += amplitude_score
|
||||
|
||||
# ===== 三、量能配合评估 (20%权重,最高5分) =====
|
||||
volume_score = self._calculate_volume_score()
|
||||
total_score += volume_score
|
||||
|
||||
# ===== 四、均线位置评估 (15%权重,最高5分) =====
|
||||
ma_score = self._calculate_ma_position_score()
|
||||
total_score += ma_score
|
||||
|
||||
# ===== 五、形成速度评估 (10%权重,最高4分) =====
|
||||
speed_score = self._calculate_formation_speed_score()
|
||||
total_score += speed_score
|
||||
|
||||
# ===== 六、次级别确认评估 (30%权重,最高10分) =====
|
||||
confirmation_score = self._calculate_confirmation_score()
|
||||
total_score += confirmation_score
|
||||
|
||||
# 转换为100分制
|
||||
final_score = (total_score / max_score) * 100
|
||||
|
||||
return round(final_score, 2)
|
||||
|
||||
def _verify_basic_fx_structure(self):
|
||||
"""
|
||||
验证基础分型要素(先决条件)
|
||||
只验证最核心的分型定义,避免过度严格
|
||||
"""
|
||||
if not self.pre or not self.next:
|
||||
return False
|
||||
|
||||
if self.fx == Chan_FX_TYPE.TOP:
|
||||
# 顶分型核心要素:中间K线高点必须严格高于两侧
|
||||
if not (self.high > self.pre.high and self.high > self.next.high):
|
||||
return False
|
||||
|
||||
elif self.fx == Chan_FX_TYPE.BOTTOM:
|
||||
# 底分型核心要素:中间K线低点必须严格低于两侧
|
||||
if not (self.low < self.pre.low and self.low < self.next.low):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _calculate_amplitude_score(self):
|
||||
"""
|
||||
计算振幅比例得分 (最高5分)
|
||||
强势分型:分型区间振幅>近期平均振幅的150% = 5分
|
||||
标准分型:介于80%-150%之间 = 3分
|
||||
弱势分型:<80% = 1分
|
||||
"""
|
||||
score = 0
|
||||
|
||||
# 计算分型区间振幅
|
||||
if self.fx == Chan_FX_TYPE.TOP:
|
||||
fx_amplitude = self.high - min(self.pre.low, self.next.low)
|
||||
# 加分项:右侧K线低点低于左侧K线低点(经典缠论强势特征)
|
||||
if self.next.low < self.pre.low:
|
||||
score += 1
|
||||
else: # BOTTOM
|
||||
fx_amplitude = max(self.pre.high, self.next.high) - self.low
|
||||
# 加分项:右侧K线高点高于左侧K线高点(经典缠论强势特征)
|
||||
if self.next.high > self.pre.high:
|
||||
score += 1
|
||||
|
||||
# 计算近期平均振幅(前10根K线的ATR)
|
||||
avg_amplitude = self._calculate_recent_atr(lookback=10)
|
||||
|
||||
if avg_amplitude <= 0:
|
||||
return max(1, score) # 确保至少有基础分
|
||||
|
||||
amplitude_ratio = fx_amplitude / avg_amplitude
|
||||
|
||||
if amplitude_ratio >= 1.5: # >150%
|
||||
score += 4 # 基础4分 + 可能的经典形态1分 = 最高5分
|
||||
elif amplitude_ratio >= 1.0: # 100%-150%
|
||||
score += 2 + int((amplitude_ratio - 1.0) * 4) # 2-4分线性插值
|
||||
elif amplitude_ratio >= 0.8: # 80%-100%
|
||||
score += 1 + int((amplitude_ratio - 0.8) * 5) # 1-2分线性插值
|
||||
else: # <80%
|
||||
score += 1
|
||||
|
||||
return min(5, score)
|
||||
|
||||
def _calculate_volume_score(self):
|
||||
"""
|
||||
计算量能配合得分 (最高5分)
|
||||
顶分型:第二根K线放量滞涨为强烈信号
|
||||
底分型:第三根K线放量回升为有效确认
|
||||
"""
|
||||
# 计算前5根K线平均成交量
|
||||
avg_volume = self._calculate_average_volume(lookback=5)
|
||||
|
||||
if avg_volume <= 0:
|
||||
return 1
|
||||
|
||||
if self.fx == Chan_FX_TYPE.TOP:
|
||||
# 顶分型:检查第二根K线(当前)是否放量滞涨
|
||||
volume_ratio = self.volume / avg_volume
|
||||
|
||||
# 判断是否滞涨:收盘价位于K线下半部分
|
||||
price_position = (self.close - self.low) / (self.high - self.low) if self.high > self.low else 0.5
|
||||
|
||||
if volume_ratio >= 2.0 and price_position <= 0.4: # 放量+滞涨
|
||||
return 5
|
||||
elif volume_ratio >= 1.5 and price_position <= 0.5:
|
||||
return 4
|
||||
elif volume_ratio >= 1.2:
|
||||
return 3
|
||||
else:
|
||||
return 1
|
||||
|
||||
else: # BOTTOM
|
||||
# 底分型:检查第三根K线是否放量回升
|
||||
next_volume_ratio = self.next.volume / avg_volume if hasattr(self.next, 'volume') else 1
|
||||
|
||||
# 判断是否回升:第三根K线收盘价相对位置较高
|
||||
if self.next.high > self.next.low:
|
||||
next_price_position = (self.next.close - self.next.low) / (self.next.high - self.next.low)
|
||||
else:
|
||||
next_price_position = 0.5
|
||||
|
||||
if next_volume_ratio >= 2.0 and next_price_position >= 0.6: # 放量+回升
|
||||
return 5
|
||||
elif next_volume_ratio >= 1.5 and next_price_position >= 0.5:
|
||||
return 4
|
||||
elif next_volume_ratio >= 1.2:
|
||||
return 3
|
||||
else:
|
||||
return 1
|
||||
|
||||
def _calculate_ma_position_score(self):
|
||||
"""
|
||||
计算均线位置得分 (最高5分)
|
||||
强势顶分型需在5/10均线乖离率>5%时出现
|
||||
有效底分型常伴随MACD底背离
|
||||
"""
|
||||
score = 0
|
||||
|
||||
# 获取均线数据
|
||||
klu_features = self.cal_klu_features()
|
||||
|
||||
if self.fx == Chan_FX_TYPE.TOP:
|
||||
# 顶分型:检查与5日和10日均线的乖离率
|
||||
ma5_bias = 0
|
||||
ma10_bias = 0
|
||||
|
||||
if 'klu_ma5' in klu_features and klu_features['klu_ma5'] > 0:
|
||||
ma5_bias = (self.close - klu_features['klu_ma5']) / klu_features['klu_ma5']
|
||||
|
||||
if 'klu_ma10' in klu_features and klu_features['klu_ma10'] > 0:
|
||||
ma10_bias = (self.close - klu_features['klu_ma10']) / klu_features['klu_ma10']
|
||||
|
||||
# 乖离率>5%为强势信号
|
||||
if ma5_bias > 0.05 or ma10_bias > 0.05:
|
||||
score += 3
|
||||
elif ma5_bias > 0.03 or ma10_bias > 0.03:
|
||||
score += 2
|
||||
elif ma5_bias > 0 or ma10_bias > 0:
|
||||
score += 1
|
||||
|
||||
else: # BOTTOM
|
||||
# 底分型:检查MACD背离和均线支撑
|
||||
# 简化处理:检查价格是否在均线附近或下方
|
||||
ma5_support = False
|
||||
ma10_support = False
|
||||
|
||||
if 'klu_ma5' in klu_features and klu_features['klu_ma5'] > 0:
|
||||
ma5_bias = (self.close - klu_features['klu_ma5']) / klu_features['klu_ma5']
|
||||
if ma5_bias >= -0.05: # 在5日均线附近或上方
|
||||
ma5_support = True
|
||||
|
||||
if 'klu_ma10' in klu_features and klu_features['klu_ma10'] > 0:
|
||||
ma10_bias = (self.close - klu_features['klu_ma10']) / klu_features['klu_ma10']
|
||||
if ma10_bias >= -0.05: # 在10日均线附近或上方
|
||||
ma10_support = True
|
||||
|
||||
if ma5_support and ma10_support:
|
||||
score += 3
|
||||
elif ma5_support or ma10_support:
|
||||
score += 2
|
||||
else:
|
||||
score += 1
|
||||
|
||||
# 检查MACD状态
|
||||
if hasattr(self, 'macdhist'):
|
||||
if self.fx == Chan_FX_TYPE.BOTTOM and self.macdhist > 0:
|
||||
score += 2 # MACD金叉附近的底分型加分
|
||||
elif self.fx == Chan_FX_TYPE.TOP and self.macdhist < 0:
|
||||
score += 2 # MACD死叉附近的顶分型加分
|
||||
|
||||
return min(5, score)
|
||||
|
||||
def _calculate_formation_speed_score(self):
|
||||
"""
|
||||
计算形成速度得分 (最高4分)
|
||||
强势特征:分型形成时间小于对应级别平均周期的1/3
|
||||
弱势特征:形成时间超过平均周期2倍
|
||||
"""
|
||||
# 简化处理:基于分型K线的收敛程度
|
||||
# 分型区间内的价格收敛速度越快,形成速度越快
|
||||
|
||||
if self.fx == Chan_FX_TYPE.TOP:
|
||||
# 顶分型:检查左右两根K线相对于中间K线的收敛程度
|
||||
left_convergence = (self.high - self.pre.high) / self.high if self.high > 0 else 0
|
||||
right_convergence = (self.high - self.next.high) / self.high if self.high > 0 else 0
|
||||
else: # BOTTOM
|
||||
left_convergence = (self.pre.low - self.low) / self.low if self.low > 0 else 0
|
||||
right_convergence = (self.next.low - self.low) / self.low if self.low > 0 else 0
|
||||
|
||||
avg_convergence = (left_convergence + right_convergence) / 2
|
||||
|
||||
if avg_convergence >= 0.03: # 快速形成
|
||||
return 4
|
||||
elif avg_convergence >= 0.02:
|
||||
return 3
|
||||
elif avg_convergence >= 0.01:
|
||||
return 2
|
||||
else:
|
||||
return 1
|
||||
|
||||
def _calculate_confirmation_score(self):
|
||||
"""
|
||||
计算次级别确认得分 (最高10分)
|
||||
- 笔破坏检测:真实强势分型会破坏前一笔的趋势
|
||||
- 观察分型后3根K线能否站稳分型区间1/2以上
|
||||
- 结合技术指标确认
|
||||
"""
|
||||
score = 0
|
||||
|
||||
# 1. 检查分型后确认(如果有next的next数据)
|
||||
if hasattr(self.next, 'next'):
|
||||
next2 = self.next.next
|
||||
if next2:
|
||||
if self.fx == Chan_FX_TYPE.TOP:
|
||||
# 顶分型:检查后续2根K线是否持续走弱
|
||||
fx_mid_level = (self.high + min(self.pre.low, self.next.low)) / 2
|
||||
if self.next.close < fx_mid_level and next2.close < fx_mid_level:
|
||||
score += 5 # 强确认
|
||||
elif self.next.close < fx_mid_level:
|
||||
score += 3 # 中等确认
|
||||
else: # BOTTOM
|
||||
# 底分型:检查后续2根K线是否持续走强
|
||||
fx_mid_level = (max(self.pre.high, self.next.high) + self.low) / 2
|
||||
if self.next.close > fx_mid_level and next2.close > fx_mid_level:
|
||||
score += 5 # 强确认
|
||||
elif self.next.close > fx_mid_level:
|
||||
score += 3 # 中等确认
|
||||
|
||||
# 2. 技术指标确认
|
||||
if hasattr(self, 'rsi'):
|
||||
if self.fx == Chan_FX_TYPE.TOP and self.rsi > 70:
|
||||
score += 2 # 超买区顶分型
|
||||
elif self.fx == Chan_FX_TYPE.BOTTOM and self.rsi < 30:
|
||||
score += 2 # 超卖区底分型
|
||||
|
||||
# 3. 分型强度自身确认(K线形态)
|
||||
if self.fx == Chan_FX_TYPE.TOP:
|
||||
# 长上影线确认
|
||||
upper_shadow = self.high - max(self.open, self.close)
|
||||
candle_range = self.high - self.low
|
||||
if candle_range > 0 and upper_shadow / candle_range > 0.5:
|
||||
score += 2
|
||||
else: # BOTTOM
|
||||
# 长下影线确认
|
||||
lower_shadow = min(self.open, self.close) - self.low
|
||||
candle_range = self.high - self.low
|
||||
if candle_range > 0 and lower_shadow / candle_range > 0.5:
|
||||
score += 2
|
||||
|
||||
# 4. 与前一个分型的关系
|
||||
if self.pre and hasattr(self.pre, 'fx') and self.pre.fx != Chan_FX_TYPE.UNKNOWN:
|
||||
# 检查是否形成有效的笔结构
|
||||
if self.fx != self.pre.fx: # 分型类型相反
|
||||
score += 1
|
||||
|
||||
return min(10, score)
|
||||
|
||||
def _calculate_recent_atr(self, lookback=10):
|
||||
"""
|
||||
计算近期ATR(平均真实波动范围)
|
||||
"""
|
||||
tr_values = []
|
||||
temp = self
|
||||
|
||||
for i in range(lookback):
|
||||
if temp and temp.pre:
|
||||
tr = max(
|
||||
temp.high - temp.low,
|
||||
abs(temp.high - temp.pre.close),
|
||||
abs(temp.low - temp.pre.close)
|
||||
)
|
||||
tr_values.append(tr)
|
||||
temp = temp.pre
|
||||
else:
|
||||
break
|
||||
|
||||
return sum(tr_values) / len(tr_values) if tr_values else 0
|
||||
|
||||
def _calculate_average_volume(self, lookback=5):
|
||||
"""
|
||||
计算平均成交量
|
||||
"""
|
||||
volumes = []
|
||||
temp = self.pre # 从前一根K线开始计算
|
||||
|
||||
for i in range(lookback):
|
||||
if temp:
|
||||
volumes.append(temp.volume)
|
||||
temp = temp.pre
|
||||
else:
|
||||
break
|
||||
|
||||
return sum(volumes) / len(volumes) if volumes else 0
|
||||
|
||||
def get_fx_strength_level(self):
|
||||
"""
|
||||
获取分型强度等级
|
||||
根据专业评分标准:≥80分为有效强势分型,≤40分建议忽略
|
||||
"""
|
||||
strength = self.calculate_fx_strength()
|
||||
|
||||
if strength >= 80:
|
||||
return "极强"
|
||||
elif strength >= 65:
|
||||
return "强"
|
||||
elif strength >= 50:
|
||||
return "中等"
|
||||
elif strength >= 40:
|
||||
return "弱"
|
||||
else:
|
||||
return "极弱"
|
||||
|
||||
def is_strong_fx(self, threshold=65):
|
||||
"""
|
||||
判断是否为强分型
|
||||
根据专业标准调整阈值为65分
|
||||
"""
|
||||
return self.calculate_fx_strength() >= threshold
|
||||
Reference in New Issue
Block a user