- Added support for a detailed chart mode in plot_converging_triangles.py, allowing users to visualize all pivot points and fitting lines. - Improved pivot fitting logic to utilize multiple representative points, enhancing detection accuracy and reducing false positives. - Introduced a new real-time detection mode with flexible zone parameters for better responsiveness in stock analysis. - Updated README.md and USAGE.md to reflect new features and usage instructions. - Added multiple documentation files detailing recent improvements, including pivot point fitting and visualization enhancements. - Cleaned up and archived outdated scripts to streamline the project structure.
173 lines
5.6 KiB
Python
173 lines
5.6 KiB
Python
"""
|
||
演示分段选择枢轴点的逻辑
|
||
|
||
展示如何将枢轴点按时间分为3段,并在每段中选择最具代表性的点
|
||
"""
|
||
|
||
import numpy as np
|
||
import sys
|
||
import os
|
||
|
||
sys.path.append(os.path.join(os.path.dirname(__file__), "..", "src"))
|
||
|
||
def demo_segmentation(pivot_indices, pivot_values, mode="upper"):
|
||
"""
|
||
演示分段选择逻辑
|
||
|
||
Args:
|
||
pivot_indices: 枢轴点的时间索引 (X坐标)
|
||
pivot_values: 枢轴点的价格值 (Y坐标)
|
||
mode: "upper" 或 "lower"
|
||
"""
|
||
print("\n" + "="*70)
|
||
print(f"分段选择演示 - {mode.upper()} 模式")
|
||
print("="*70)
|
||
|
||
# 按时间排序
|
||
sort_idx = np.argsort(pivot_indices)
|
||
x_sorted = pivot_indices[sort_idx]
|
||
y_sorted = pivot_values[sort_idx]
|
||
n = len(x_sorted)
|
||
|
||
print(f"\n[步骤1] 按时间排序所有枢轴点")
|
||
print(f" 枢轴点总数: {n}")
|
||
print(f" 时间索引 (X): {x_sorted}")
|
||
print(f" 价格值 (Y): {y_sorted}")
|
||
|
||
# 判断是否需要分段
|
||
if n <= 4:
|
||
print(f"\n[步骤2] 点数 <= 4,直接使用所有点(不分段)")
|
||
selected_mask = np.ones(n, dtype=bool)
|
||
selected_x = x_sorted
|
||
selected_y = y_sorted
|
||
print(f" 选中索引: {list(range(n))}")
|
||
print(f" 选中点数: {n}")
|
||
return selected_x, selected_y
|
||
|
||
# 分段逻辑
|
||
print(f"\n[步骤2] 点数 > 4,进行分段选择")
|
||
segment_size = n // 3
|
||
print(f" 每段大小: {n} // 3 = {segment_size}")
|
||
|
||
segments = [
|
||
range(0, min(segment_size, n)),
|
||
range(segment_size, min(2 * segment_size, n)),
|
||
range(2 * segment_size, n),
|
||
]
|
||
|
||
print(f"\n[步骤3] 分3段,并在每段中选择代表性点")
|
||
print(f" 选择规则: {mode.upper()} 模式 -> 每段选{'最高点' if mode == 'upper' else '最低点'}")
|
||
|
||
selected_mask = np.zeros(n, dtype=bool)
|
||
selected_details = []
|
||
|
||
for seg_num, seg in enumerate(segments, 1):
|
||
if len(seg) == 0:
|
||
continue
|
||
|
||
seg_list = list(seg)
|
||
seg_x = x_sorted[seg_list]
|
||
seg_y = y_sorted[seg_list]
|
||
|
||
print(f"\n 第{seg_num}段:")
|
||
print(f" 索引范围: [{seg.start}, {seg.stop})")
|
||
print(f" 包含点数: {len(seg_list)}")
|
||
print(f" 时间索引: {seg_x}")
|
||
print(f" 价格值: {seg_y}")
|
||
|
||
if mode == "upper":
|
||
best_idx_in_seg = np.argmax(seg_y)
|
||
print(f" 最高价格: {seg_y[best_idx_in_seg]:.2f}")
|
||
else:
|
||
best_idx_in_seg = np.argmin(seg_y)
|
||
print(f" 最低价格: {seg_y[best_idx_in_seg]:.2f}")
|
||
|
||
selected_global_idx = seg_list[best_idx_in_seg]
|
||
selected_mask[selected_global_idx] = True
|
||
|
||
print(f" → 选中: 索引{selected_global_idx} (时间={x_sorted[selected_global_idx]}, 价格={y_sorted[selected_global_idx]:.2f})")
|
||
selected_details.append({
|
||
'seg': seg_num,
|
||
'idx': selected_global_idx,
|
||
'x': x_sorted[selected_global_idx],
|
||
'y': y_sorted[selected_global_idx]
|
||
})
|
||
|
||
selected_x = x_sorted[selected_mask]
|
||
selected_y = y_sorted[selected_mask]
|
||
|
||
print(f"\n[步骤4] 选中的枢轴点总结")
|
||
print(f" 选中点数: {len(selected_x)}/{n}")
|
||
print(f" 选中时间: {selected_x}")
|
||
print(f" 选中价格: {selected_y}")
|
||
|
||
print(f"\n[步骤5] 线性回归拟合")
|
||
if len(selected_x) >= 2:
|
||
a, b = np.polyfit(selected_x, selected_y, deg=1)
|
||
print(f" 拟合直线: y = {a:.6f} * x + {b:.2f}")
|
||
print(f" 斜率: {a:.6f} ({'下降' if a < 0 else '上升' if a > 0 else '水平'})")
|
||
else:
|
||
print(f" 点数不足,无法拟合")
|
||
|
||
return selected_x, selected_y
|
||
|
||
|
||
def main():
|
||
print("\n" + "="*70)
|
||
print("分段选择枢轴点 - 原理演示")
|
||
print("="*70)
|
||
|
||
# 示例1: 6个高点枢轴点 (模拟SZ002343的情况)
|
||
print("\n" + "█"*70)
|
||
print("示例1: 6个高点枢轴点 - 上沿拟合")
|
||
print("█"*70)
|
||
|
||
# 假设的6个高点枢轴点 (时间索引, 价格)
|
||
ph_indices = np.array([40, 80, 120, 160, 200, 230])
|
||
ph_values = np.array([9.8, 9.5, 10.0, 9.7, 9.2, 8.9])
|
||
|
||
demo_segmentation(ph_indices, ph_values, mode="upper")
|
||
|
||
# 示例2: 4个低点枢轴点
|
||
print("\n\n" + "█"*70)
|
||
print("示例2: 4个低点枢轴点 - 下沿拟合")
|
||
print("█"*70)
|
||
|
||
pl_indices = np.array([60, 140, 200, 235])
|
||
pl_values = np.array([5.2, 6.5, 7.4, 6.8])
|
||
|
||
demo_segmentation(pl_indices, pl_values, mode="lower")
|
||
|
||
# 示例3: 8个高点枢轴点(更多点的情况)
|
||
print("\n\n" + "█"*70)
|
||
print("示例3: 8个高点枢轴点 - 上沿拟合")
|
||
print("█"*70)
|
||
|
||
ph_indices_large = np.array([20, 50, 80, 110, 140, 170, 200, 230])
|
||
ph_values_large = np.array([42.5, 41.8, 42.0, 41.2, 40.5, 40.0, 39.5, 39.0])
|
||
|
||
demo_segmentation(ph_indices_large, ph_values_large, mode="upper")
|
||
|
||
print("\n" + "="*70)
|
||
print("总结")
|
||
print("="*70)
|
||
print("""
|
||
分段选择的核心思想:
|
||
1. 将时间轴均匀分为3段 (前1/3、中1/3、后1/3)
|
||
2. 在每段中选择最具代表性的点:
|
||
- 上沿:选该段的最高点(形成下边界)
|
||
- 下沿:选该段的最低点(形成上边界)
|
||
3. 用选中的3个点进行线性回归,拟合趋势线
|
||
|
||
优点:
|
||
✓ 时间均衡:确保前、中、后都有点参与拟合
|
||
✓ 代表性强:每段选最极值点,确保线是真正的边界
|
||
✓ 稳定性好:多点回归比两点连线更稳健
|
||
✓ 覆盖性好:确保趋势线能包络所有枢轴点
|
||
""")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|
||
|