Add files to chanlun_1
This commit is contained in:
+683
@@ -0,0 +1,683 @@
|
||||
"""
|
||||
分型识别模块:识别顶分型和底分型
|
||||
分型定义:至少需要3根K线,中间K线的高点(或低点)比两侧都高(或低)
|
||||
增强版:包含多维度强弱程度评估
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from typing import List, Tuple, Optional, Dict
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass
|
||||
class FractalPoint:
|
||||
"""分型点数据类"""
|
||||
index: int # 在原始数据中的位置
|
||||
timestamp: pd.Timestamp # 时间戳
|
||||
price: float # 分型价格(高点或低点)
|
||||
fractal_type: str # 'top' 或 'bottom'
|
||||
strength: int # 基础分型强度(左右确认的K线数量)
|
||||
enhanced_strength: float # 增强强度评分(0-100)
|
||||
price_dominance: float # 价格优势度(0-100)
|
||||
volume_strength: float # 成交量强度(0-100)
|
||||
trend_position: float # 趋势位置强度(0-100)
|
||||
confirmed: bool = False # 是否已确认
|
||||
|
||||
|
||||
class Fractal:
|
||||
"""分型识别类(增强版)"""
|
||||
|
||||
def __init__(self, kline_data: pd.DataFrame, min_strength: int = 1):
|
||||
"""
|
||||
初始化分型识别器
|
||||
|
||||
Args:
|
||||
kline_data: 处理包含关系后的K线数据
|
||||
min_strength: 最小分型强度(左右各需多少根K线确认)
|
||||
"""
|
||||
self.data = kline_data.copy()
|
||||
self.min_strength = max(1, min_strength) # 至少为1
|
||||
self.top_fractals = []
|
||||
self.bottom_fractals = []
|
||||
self.all_fractals = []
|
||||
|
||||
# 计算一些辅助指标
|
||||
self._calculate_auxiliary_indicators()
|
||||
|
||||
def _calculate_auxiliary_indicators(self):
|
||||
"""计算辅助技术指标"""
|
||||
# 成交量移动平均
|
||||
self.data['volume_ma'] = self.data['volume'].rolling(window=20, min_periods=1).mean()
|
||||
|
||||
# 价格振幅
|
||||
self.data['range'] = self.data['high'] - self.data['low']
|
||||
self.data['range_ma'] = self.data['range'].rolling(window=20, min_periods=1).mean()
|
||||
|
||||
# 相对位置(高点在整个区间的位置)
|
||||
window = 20
|
||||
self.data['highest'] = self.data['high'].rolling(window=window, min_periods=1).max()
|
||||
self.data['lowest'] = self.data['low'].rolling(window=window, min_periods=1).min()
|
||||
|
||||
# 趋势强度(简单移动平均斜率)
|
||||
self.data['close_ma'] = self.data['close'].rolling(window=10, min_periods=1).mean()
|
||||
self.data['trend_slope'] = self.data['close_ma'].diff(5) # 5期斜率
|
||||
|
||||
def _calculate_price_dominance(self, idx: int, fractal_type: str, strength: int) -> float:
|
||||
"""
|
||||
计算价格优势度:分型价格相对于周围价格的优势程度
|
||||
|
||||
Args:
|
||||
idx: 分型位置
|
||||
fractal_type: 分型类型
|
||||
strength: 基础强度
|
||||
|
||||
Returns:
|
||||
价格优势度(0-100)
|
||||
"""
|
||||
try:
|
||||
# 扩展检查范围
|
||||
check_range = max(strength * 2, 10)
|
||||
start_idx = max(0, idx - check_range)
|
||||
end_idx = min(len(self.data), idx + check_range + 1)
|
||||
|
||||
if fractal_type == 'top':
|
||||
center_price = self.data.iloc[idx]['high']
|
||||
range_data = self.data.iloc[start_idx:end_idx]
|
||||
max_around = range_data['high'].max()
|
||||
second_max = range_data['high'].nlargest(2).iloc[1] if len(range_data) > 1 else center_price
|
||||
|
||||
# 计算相对优势
|
||||
if max_around == center_price:
|
||||
price_gap = center_price - second_max
|
||||
avg_range = self.data.iloc[idx]['range_ma']
|
||||
dominance = min((price_gap / avg_range) * 50, 100) if avg_range > 0 else 50
|
||||
else:
|
||||
dominance = 0
|
||||
else: # bottom
|
||||
center_price = self.data.iloc[idx]['low']
|
||||
range_data = self.data.iloc[start_idx:end_idx]
|
||||
min_around = range_data['low'].min()
|
||||
second_min = range_data['low'].nsmallest(2).iloc[1] if len(range_data) > 1 else center_price
|
||||
|
||||
# 计算相对优势
|
||||
if min_around == center_price:
|
||||
price_gap = second_min - center_price
|
||||
avg_range = self.data.iloc[idx]['range_ma']
|
||||
dominance = min((price_gap / avg_range) * 50, 100) if avg_range > 0 else 50
|
||||
else:
|
||||
dominance = 0
|
||||
|
||||
return max(0, dominance)
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"计算价格优势度失败: {e}")
|
||||
return 30 # 默认值
|
||||
|
||||
def _calculate_volume_strength(self, idx: int, fractal_type: str, strength: int) -> float:
|
||||
"""
|
||||
计算成交量强度:分型形成时的成交量特征
|
||||
|
||||
Args:
|
||||
idx: 分型位置
|
||||
fractal_type: 分型类型
|
||||
strength: 基础强度
|
||||
|
||||
Returns:
|
||||
成交量强度(0-100)
|
||||
"""
|
||||
try:
|
||||
center_volume = self.data.iloc[idx]['volume']
|
||||
volume_ma = self.data.iloc[idx]['volume_ma']
|
||||
|
||||
# 基础成交量比率
|
||||
volume_ratio = center_volume / volume_ma if volume_ma > 0 else 1
|
||||
base_score = min(volume_ratio * 30, 60) # 最高60分
|
||||
|
||||
# 检查分型形成过程中的成交量模式
|
||||
pattern_score = 0
|
||||
if strength >= 2:
|
||||
# 检查左右成交量是否递减(表示力度衰竭)
|
||||
left_volumes = [self.data.iloc[idx - i]['volume'] for i in range(1, strength + 1)]
|
||||
right_volumes = [self.data.iloc[idx + i]['volume'] for i in range(1, strength + 1)]
|
||||
|
||||
# 中心成交量应该相对突出
|
||||
center_prominence = sum([1 for v in left_volumes + right_volumes if center_volume > v])
|
||||
total_compared = len(left_volumes + right_volumes)
|
||||
pattern_score = (center_prominence / total_compared) * 40 if total_compared > 0 else 20
|
||||
|
||||
total_score = base_score + pattern_score
|
||||
return max(0, min(total_score, 100))
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"计算成交量强度失败: {e}")
|
||||
return 40 # 默认值
|
||||
|
||||
def _calculate_trend_position_strength(self, idx: int, fractal_type: str) -> float:
|
||||
"""
|
||||
计算趋势位置强度:分型在整体趋势中的位置优势
|
||||
|
||||
Args:
|
||||
idx: 分型位置
|
||||
fractal_type: 分型类型
|
||||
|
||||
Returns:
|
||||
趋势位置强度(0-100)
|
||||
"""
|
||||
try:
|
||||
current_price = self.data.iloc[idx]['high' if fractal_type == 'top' else 'low']
|
||||
highest = self.data.iloc[idx]['highest']
|
||||
lowest = self.data.iloc[idx]['lowest']
|
||||
trend_slope = self.data.iloc[idx]['trend_slope']
|
||||
|
||||
# 计算在价格区间中的相对位置
|
||||
price_range = highest - lowest
|
||||
if price_range > 0:
|
||||
if fractal_type == 'top':
|
||||
# 顶分型:越接近高点越强
|
||||
position_ratio = (current_price - lowest) / price_range
|
||||
else:
|
||||
# 底分型:越接近低点越强
|
||||
position_ratio = (highest - current_price) / price_range
|
||||
else:
|
||||
position_ratio = 0.5
|
||||
|
||||
position_score = position_ratio * 60 # 位置得分最高60分
|
||||
|
||||
# 趋势方向得分
|
||||
trend_score = 0
|
||||
if trend_slope is not None and not np.isnan(trend_slope):
|
||||
if fractal_type == 'top' and trend_slope < 0:
|
||||
# 顶分型形成在下降趋势中更有效
|
||||
trend_score = min(abs(trend_slope) * 1000, 40)
|
||||
elif fractal_type == 'bottom' and trend_slope > 0:
|
||||
# 底分型形成在上升趋势中更有效
|
||||
trend_score = min(abs(trend_slope) * 1000, 40)
|
||||
else:
|
||||
trend_score = 20 # 趋势方向不匹配给予中等分数
|
||||
|
||||
total_score = position_score + trend_score
|
||||
return max(0, min(total_score, 100))
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"计算趋势位置强度失败: {e}")
|
||||
return 50 # 默认值
|
||||
|
||||
def _calculate_enhanced_strength(self, idx: int, fractal_type: str, basic_strength: int) -> Dict[str, float]:
|
||||
"""
|
||||
计算增强强度评分
|
||||
|
||||
Args:
|
||||
idx: 分型位置
|
||||
fractal_type: 分型类型
|
||||
basic_strength: 基础强度
|
||||
|
||||
Returns:
|
||||
包含各维度强度的字典
|
||||
"""
|
||||
# 计算各维度强度
|
||||
price_dominance = self._calculate_price_dominance(idx, fractal_type, basic_strength)
|
||||
volume_strength = self._calculate_volume_strength(idx, fractal_type, basic_strength)
|
||||
trend_position = self._calculate_trend_position_strength(idx, fractal_type)
|
||||
|
||||
# 基础强度转换为评分(强度越高,分数越高)
|
||||
basic_score = min(basic_strength * 20, 60) # 基础强度最高60分
|
||||
|
||||
# 计算综合强度(加权平均)
|
||||
enhanced_strength = (
|
||||
basic_score * 0.3 + # 基础强度 30%
|
||||
price_dominance * 0.4 + # 价格优势 40%
|
||||
volume_strength * 0.2 + # 成交量强度 20%
|
||||
trend_position * 0.1 # 趋势位置 10%
|
||||
)
|
||||
|
||||
return {
|
||||
'enhanced_strength': enhanced_strength,
|
||||
'price_dominance': price_dominance,
|
||||
'volume_strength': volume_strength,
|
||||
'trend_position': trend_position
|
||||
}
|
||||
|
||||
def is_top_fractal(self, idx: int, strength: int = None) -> Tuple[bool, int]:
|
||||
"""
|
||||
判断指定位置是否为顶分型
|
||||
|
||||
Args:
|
||||
idx: 检查的位置索引
|
||||
strength: 检查强度,如果为None则使用类默认值
|
||||
|
||||
Returns:
|
||||
(是否为顶分型, 实际强度)
|
||||
"""
|
||||
if strength is None:
|
||||
strength = self.min_strength
|
||||
|
||||
data_len = len(self.data)
|
||||
|
||||
# 检查边界
|
||||
if idx < strength or idx >= data_len - strength:
|
||||
return False, 0
|
||||
|
||||
center_high = self.data.iloc[idx]['high']
|
||||
|
||||
# 检查左侧K线
|
||||
left_valid = True
|
||||
for i in range(1, strength + 1):
|
||||
if self.data.iloc[idx - i]['high'] >= center_high:
|
||||
left_valid = False
|
||||
break
|
||||
|
||||
# 检查右侧K线
|
||||
right_valid = True
|
||||
for i in range(1, strength + 1):
|
||||
if self.data.iloc[idx + i]['high'] >= center_high:
|
||||
right_valid = False
|
||||
break
|
||||
|
||||
is_fractal = left_valid and right_valid
|
||||
actual_strength = strength if is_fractal else 0
|
||||
|
||||
return is_fractal, actual_strength
|
||||
|
||||
def is_bottom_fractal(self, idx: int, strength: int = None) -> Tuple[bool, int]:
|
||||
"""
|
||||
判断指定位置是否为底分型
|
||||
|
||||
Args:
|
||||
idx: 检查的位置索引
|
||||
strength: 检查强度,如果为None则使用类默认值
|
||||
|
||||
Returns:
|
||||
(是否为底分型, 实际强度)
|
||||
"""
|
||||
if strength is None:
|
||||
strength = self.min_strength
|
||||
|
||||
data_len = len(self.data)
|
||||
|
||||
# 检查边界
|
||||
if idx < strength or idx >= data_len - strength:
|
||||
return False, 0
|
||||
|
||||
center_low = self.data.iloc[idx]['low']
|
||||
|
||||
# 检查左侧K线
|
||||
left_valid = True
|
||||
for i in range(1, strength + 1):
|
||||
if self.data.iloc[idx - i]['low'] <= center_low:
|
||||
left_valid = False
|
||||
break
|
||||
|
||||
# 检查右侧K线
|
||||
right_valid = True
|
||||
for i in range(1, strength + 1):
|
||||
if self.data.iloc[idx + i]['low'] <= center_low:
|
||||
right_valid = False
|
||||
break
|
||||
|
||||
is_fractal = left_valid and right_valid
|
||||
actual_strength = strength if is_fractal else 0
|
||||
|
||||
return is_fractal, actual_strength
|
||||
|
||||
def find_max_strength_fractal(self, idx: int, fractal_type: str, max_strength: int = 5) -> Tuple[bool, int]:
|
||||
"""
|
||||
寻找指定位置的最大强度分型
|
||||
|
||||
Args:
|
||||
idx: 检查位置
|
||||
fractal_type: 'top' 或 'bottom'
|
||||
max_strength: 最大检查强度
|
||||
|
||||
Returns:
|
||||
(是否为分型, 最大强度)
|
||||
"""
|
||||
max_valid_strength = 0
|
||||
|
||||
for strength in range(self.min_strength, max_strength + 1):
|
||||
if fractal_type == 'top':
|
||||
is_valid, _ = self.is_top_fractal(idx, strength)
|
||||
else:
|
||||
is_valid, _ = self.is_bottom_fractal(idx, strength)
|
||||
|
||||
if is_valid:
|
||||
max_valid_strength = strength
|
||||
else:
|
||||
break # 一旦失败就停止,因为更高强度也不会成功
|
||||
|
||||
return max_valid_strength > 0, max_valid_strength
|
||||
|
||||
def detect_fractals(self, use_max_strength: bool = True) -> List[FractalPoint]:
|
||||
"""
|
||||
检测所有分型
|
||||
|
||||
Args:
|
||||
use_max_strength: 是否使用最大强度检测
|
||||
|
||||
Returns:
|
||||
所有分型点列表
|
||||
"""
|
||||
fractals = []
|
||||
data_len = len(self.data)
|
||||
|
||||
logger.info(f"开始检测分型,数据长度: {data_len}")
|
||||
|
||||
# 遍历所有可能的分型位置
|
||||
for idx in range(self.min_strength, data_len - self.min_strength):
|
||||
timestamp = self.data.index[idx]
|
||||
|
||||
# 检测顶分型
|
||||
if use_max_strength:
|
||||
is_top, top_strength = self.find_max_strength_fractal(idx, 'top')
|
||||
else:
|
||||
is_top, top_strength = self.is_top_fractal(idx)
|
||||
|
||||
if is_top:
|
||||
# 计算增强强度
|
||||
strength_metrics = self._calculate_enhanced_strength(idx, 'top', top_strength)
|
||||
|
||||
fractal = FractalPoint(
|
||||
index=idx,
|
||||
timestamp=timestamp,
|
||||
price=self.data.iloc[idx]['high'],
|
||||
fractal_type='top',
|
||||
strength=top_strength,
|
||||
enhanced_strength=strength_metrics['enhanced_strength'],
|
||||
price_dominance=strength_metrics['price_dominance'],
|
||||
volume_strength=strength_metrics['volume_strength'],
|
||||
trend_position=strength_metrics['trend_position'],
|
||||
confirmed=True # 简化处理,认为都已确认
|
||||
)
|
||||
fractals.append(fractal)
|
||||
self.top_fractals.append(fractal)
|
||||
|
||||
# 检测底分型
|
||||
if use_max_strength:
|
||||
is_bottom, bottom_strength = self.find_max_strength_fractal(idx, 'bottom')
|
||||
else:
|
||||
is_bottom, bottom_strength = self.is_bottom_fractal(idx)
|
||||
|
||||
if is_bottom:
|
||||
# 计算增强强度
|
||||
strength_metrics = self._calculate_enhanced_strength(idx, 'bottom', bottom_strength)
|
||||
|
||||
fractal = FractalPoint(
|
||||
index=idx,
|
||||
timestamp=timestamp,
|
||||
price=self.data.iloc[idx]['low'],
|
||||
fractal_type='bottom',
|
||||
strength=bottom_strength,
|
||||
enhanced_strength=strength_metrics['enhanced_strength'],
|
||||
price_dominance=strength_metrics['price_dominance'],
|
||||
volume_strength=strength_metrics['volume_strength'],
|
||||
trend_position=strength_metrics['trend_position'],
|
||||
confirmed=True
|
||||
)
|
||||
fractals.append(fractal)
|
||||
self.bottom_fractals.append(fractal)
|
||||
|
||||
# 按时间排序
|
||||
fractals.sort(key=lambda x: x.index)
|
||||
self.all_fractals = fractals
|
||||
|
||||
logger.info(f"检测完成:顶分型 {len(self.top_fractals)} 个,底分型 {len(self.bottom_fractals)} 个")
|
||||
return fractals
|
||||
|
||||
def filter_fractals_by_strength(self, min_strength: int) -> List[FractalPoint]:
|
||||
"""
|
||||
按强度过滤分型
|
||||
|
||||
Args:
|
||||
min_strength: 最小强度要求
|
||||
|
||||
Returns:
|
||||
过滤后的分型列表
|
||||
"""
|
||||
return [f for f in self.all_fractals if f.strength >= min_strength]
|
||||
|
||||
def get_fractal_sequence(self) -> List[FractalPoint]:
|
||||
"""
|
||||
获取交替的分型序列(顶-底-顶-底...)
|
||||
|
||||
Returns:
|
||||
交替分型序列
|
||||
"""
|
||||
if not self.all_fractals:
|
||||
return []
|
||||
|
||||
sequence = []
|
||||
last_type = None
|
||||
|
||||
for fractal in self.all_fractals:
|
||||
if fractal.fractal_type != last_type:
|
||||
sequence.append(fractal)
|
||||
last_type = fractal.fractal_type
|
||||
|
||||
return sequence
|
||||
|
||||
def validate_fractal_sequence(self, sequence: List[FractalPoint]) -> bool:
|
||||
"""
|
||||
验证分型序列的有效性
|
||||
|
||||
Args:
|
||||
sequence: 分型序列
|
||||
|
||||
Returns:
|
||||
是否有效
|
||||
"""
|
||||
if len(sequence) < 2:
|
||||
return True
|
||||
|
||||
for i in range(1, len(sequence)):
|
||||
prev_fractal = sequence[i-1]
|
||||
curr_fractal = sequence[i]
|
||||
|
||||
# 检查类型是否交替
|
||||
if prev_fractal.fractal_type == curr_fractal.fractal_type:
|
||||
return False
|
||||
|
||||
# 检查价格关系是否合理
|
||||
if prev_fractal.fractal_type == 'top':
|
||||
# 顶分型后应该是底分型,且价格应该更低
|
||||
if curr_fractal.price >= prev_fractal.price:
|
||||
return False
|
||||
else:
|
||||
# 底分型后应该是顶分型,且价格应该更高
|
||||
if curr_fractal.price <= prev_fractal.price:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def get_fractal_statistics(self) -> Dict:
|
||||
"""
|
||||
获取分型统计信息(增强版)
|
||||
|
||||
Returns:
|
||||
统计信息字典
|
||||
"""
|
||||
if not self.all_fractals:
|
||||
return {}
|
||||
|
||||
top_count = len(self.top_fractals)
|
||||
bottom_count = len(self.bottom_fractals)
|
||||
|
||||
# 基础统计
|
||||
top_strengths = [f.strength for f in self.top_fractals]
|
||||
bottom_strengths = [f.strength for f in self.bottom_fractals]
|
||||
|
||||
# 增强强度统计
|
||||
enhanced_strengths = [f.enhanced_strength for f in self.all_fractals]
|
||||
price_dominances = [f.price_dominance for f in self.all_fractals]
|
||||
volume_strengths = [f.volume_strength for f in self.all_fractals]
|
||||
trend_positions = [f.trend_position for f in self.all_fractals]
|
||||
|
||||
# 分级统计(按增强强度)
|
||||
strong_fractals = [f for f in self.all_fractals if f.enhanced_strength >= 70]
|
||||
medium_fractals = [f for f in self.all_fractals if 40 <= f.enhanced_strength < 70]
|
||||
weak_fractals = [f for f in self.all_fractals if f.enhanced_strength < 40]
|
||||
|
||||
stats = {
|
||||
'basic_info': {
|
||||
'total_fractals': len(self.all_fractals),
|
||||
'top_fractals': top_count,
|
||||
'bottom_fractals': bottom_count,
|
||||
'avg_basic_strength': np.mean([f.strength for f in self.all_fractals]),
|
||||
'max_basic_strength': max([f.strength for f in self.all_fractals]),
|
||||
},
|
||||
'enhanced_strength': {
|
||||
'avg_enhanced_strength': np.mean(enhanced_strengths),
|
||||
'max_enhanced_strength': max(enhanced_strengths),
|
||||
'min_enhanced_strength': min(enhanced_strengths),
|
||||
'strong_count': len(strong_fractals), # 强势分型数量
|
||||
'medium_count': len(medium_fractals), # 中等分型数量
|
||||
'weak_count': len(weak_fractals), # 弱势分型数量
|
||||
},
|
||||
'dimension_analysis': {
|
||||
'avg_price_dominance': np.mean(price_dominances),
|
||||
'avg_volume_strength': np.mean(volume_strengths),
|
||||
'avg_trend_position': np.mean(trend_positions),
|
||||
},
|
||||
'top_fractals_detail': {
|
||||
'count': top_count,
|
||||
'avg_basic_strength': np.mean(top_strengths) if top_strengths else 0,
|
||||
'avg_enhanced_strength': np.mean([f.enhanced_strength for f in self.top_fractals]) if self.top_fractals else 0,
|
||||
'strong_tops': len([f for f in self.top_fractals if f.enhanced_strength >= 70]),
|
||||
},
|
||||
'bottom_fractals_detail': {
|
||||
'count': bottom_count,
|
||||
'avg_basic_strength': np.mean(bottom_strengths) if bottom_strengths else 0,
|
||||
'avg_enhanced_strength': np.mean([f.enhanced_strength for f in self.bottom_fractals]) if self.bottom_fractals else 0,
|
||||
'strong_bottoms': len([f for f in self.bottom_fractals if f.enhanced_strength >= 70]),
|
||||
}
|
||||
}
|
||||
|
||||
return stats
|
||||
|
||||
def to_dataframe(self) -> pd.DataFrame:
|
||||
"""
|
||||
将分型转换为DataFrame
|
||||
|
||||
Returns:
|
||||
包含分型信息的DataFrame
|
||||
"""
|
||||
if not self.all_fractals:
|
||||
return pd.DataFrame()
|
||||
|
||||
data = []
|
||||
for fractal in self.all_fractals:
|
||||
data.append({
|
||||
'timestamp': fractal.timestamp,
|
||||
'index': fractal.index,
|
||||
'price': fractal.price,
|
||||
'type': fractal.fractal_type,
|
||||
'strength': fractal.strength,
|
||||
'enhanced_strength': fractal.enhanced_strength,
|
||||
'price_dominance': fractal.price_dominance,
|
||||
'volume_strength': fractal.volume_strength,
|
||||
'trend_position': fractal.trend_position,
|
||||
'confirmed': fractal.confirmed
|
||||
})
|
||||
|
||||
df = pd.DataFrame(data)
|
||||
df.set_index('timestamp', inplace=True)
|
||||
return df
|
||||
|
||||
def update_fractal_confirmation(self, current_idx: int):
|
||||
"""
|
||||
更新分型确认状态
|
||||
|
||||
Args:
|
||||
current_idx: 当前处理到的K线位置
|
||||
"""
|
||||
for fractal in self.all_fractals:
|
||||
if not fractal.confirmed:
|
||||
# 检查是否已经过了足够的确认期
|
||||
required_confirmation = fractal.strength
|
||||
time_passed = current_idx - fractal.index
|
||||
|
||||
if time_passed >= required_confirmation:
|
||||
fractal.confirmed = True
|
||||
|
||||
def get_confirmed_fractals(self, current_idx: int) -> List[FractalPoint]:
|
||||
"""
|
||||
获取已确认的分型列表
|
||||
|
||||
Args:
|
||||
current_idx: 当前处理到的K线位置
|
||||
|
||||
Returns:
|
||||
已确认的分型列表
|
||||
"""
|
||||
confirmed_fractals = []
|
||||
for fractal in self.all_fractals:
|
||||
required_confirmation = fractal.strength
|
||||
time_passed = current_idx - fractal.index
|
||||
|
||||
if time_passed >= required_confirmation:
|
||||
confirmed_fractals.append(fractal)
|
||||
|
||||
return confirmed_fractals
|
||||
|
||||
def detect_real_time_fractals(self, current_idx: int, lookback_periods: int = 50) -> List[FractalPoint]:
|
||||
"""
|
||||
实时分型检测(避免使用未来数据)
|
||||
|
||||
Args:
|
||||
current_idx: 当前K线位置
|
||||
lookback_periods: 回看周期数
|
||||
|
||||
Returns:
|
||||
实时可用的分型列表
|
||||
"""
|
||||
real_time_fractals = []
|
||||
data_len = len(self.data)
|
||||
|
||||
# 只检测到当前位置之前的分型
|
||||
end_idx = min(current_idx, data_len - self.min_strength)
|
||||
start_idx = max(self.min_strength, end_idx - lookback_periods)
|
||||
|
||||
for idx in range(start_idx, end_idx):
|
||||
timestamp = self.data.index[idx]
|
||||
|
||||
# 检测顶分型(但只能检测已确认的)
|
||||
is_top, top_strength = self.find_max_strength_fractal(idx, 'top')
|
||||
if is_top and current_idx - idx >= top_strength: # 已确认
|
||||
strength_metrics = self._calculate_enhanced_strength(idx, 'top', top_strength)
|
||||
|
||||
fractal = FractalPoint(
|
||||
index=idx,
|
||||
timestamp=timestamp,
|
||||
price=self.data.iloc[idx]['high'],
|
||||
fractal_type='top',
|
||||
strength=top_strength,
|
||||
enhanced_strength=strength_metrics['enhanced_strength'],
|
||||
price_dominance=strength_metrics['price_dominance'],
|
||||
volume_strength=strength_metrics['volume_strength'],
|
||||
trend_position=strength_metrics['trend_position'],
|
||||
confirmed=True
|
||||
)
|
||||
real_time_fractals.append(fractal)
|
||||
|
||||
# 检测底分型(但只能检测已确认的)
|
||||
is_bottom, bottom_strength = self.find_max_strength_fractal(idx, 'bottom')
|
||||
if is_bottom and current_idx - idx >= bottom_strength: # 已确认
|
||||
strength_metrics = self._calculate_enhanced_strength(idx, 'bottom', bottom_strength)
|
||||
|
||||
fractal = FractalPoint(
|
||||
index=idx,
|
||||
timestamp=timestamp,
|
||||
price=self.data.iloc[idx]['low'],
|
||||
fractal_type='bottom',
|
||||
strength=bottom_strength,
|
||||
enhanced_strength=strength_metrics['enhanced_strength'],
|
||||
price_dominance=strength_metrics['price_dominance'],
|
||||
volume_strength=strength_metrics['volume_strength'],
|
||||
trend_position=strength_metrics['trend_position'],
|
||||
confirmed=True
|
||||
)
|
||||
real_time_fractals.append(fractal)
|
||||
|
||||
return real_time_fractals
|
||||
Reference in New Issue
Block a user