Files
Chan/algorithm_comparison_test.py
T

223 lines
8.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
KLU与KLC分型强度算法一致性测试
验证两种算法在相同数据下是否产生一致的结果
"""
from ChanKLU import ChanKLU
from ChanKLC import ChanKLC
from ChanEnum import Chan_FX_TYPE, Chan_KLINE_DIR
import pandas as pd
from datetime import datetime, timedelta
def create_test_data():
"""创建测试用的K线数据"""
test_cases = [
# 测试用例1:标准顶分型
{
'name': '标准顶分型',
'data': [
{'open': 100, 'high': 102, 'low': 99, 'close': 101, 'volume': 1000}, # K1
{'open': 101, 'high': 105, 'low': 100, 'close': 103, 'volume': 1500}, # K2 (顶分型中心)
{'open': 103, 'high': 104, 'low': 98, 'close': 99, 'volume': 1200}, # K3
]
},
# 测试用例2:标准底分型
{
'name': '标准底分型',
'data': [
{'open': 100, 'high': 102, 'low': 99, 'close': 101, 'volume': 1000}, # K1
{'open': 101, 'high': 103, 'low': 95, 'close': 97, 'volume': 1500}, # K2 (底分型中心)
{'open': 97, 'high': 104, 'low': 96, 'close': 102, 'volume': 1200}, # K3
]
},
# 测试用例3:强势顶分型(放量+下影线)
{
'name': '强势顶分型',
'data': [
{'open': 100, 'high': 102, 'low': 99, 'close': 101, 'volume': 1000}, # K1
{'open': 101, 'high': 108, 'low': 100, 'close': 102, 'volume': 2500}, # K2 (强顶分型)
{'open': 102, 'high': 103, 'low': 95, 'close': 96, 'volume': 1800}, # K3 (大阴线确认)
]
}
]
return test_cases
def setup_klu_chain(data_list):
"""设置KLU链"""
klus = []
base_time = datetime.now()
for i, data in enumerate(data_list):
time_str = (base_time + timedelta(minutes=i)).strftime("%Y-%m-%d %H:%M:%S")
klu = ChanKLU(time_str, data['open'], data['high'], data['low'], data['close'], data['volume'])
klu.set_idx(i)
# 设置基础技术指标
indicators = {
'ma5': data['close'] + (i-1) * 0.1,
'ma10': data['close'] + (i-1) * 0.05,
'rsi': 50 + (i % 3 - 1) * 15,
'macd': (i % 3 - 1) * 0.01,
'macdhist': (i % 2) * 0.005,
'volume_ratio': 1.0 + (i % 2) * 0.3
}
klu.set_indicators(indicators)
klus.append(klu)
# 建立前后关系
for i in range(len(klus)):
if i > 0:
klus[i].set_pre(klus[i-1])
if i < len(klus) - 1:
klus[i].set_next(klus[i+1])
return klus
def setup_klc_chain(data_list):
"""设置KLC链(基于KLU"""
klus = setup_klu_chain(data_list)
klcs = []
# 为简化测试,假设每个KLU对应一个KLC(无包含关系处理)
for i, klu in enumerate(klus):
klc = ChanKLC(klu, i, Chan_KLINE_DIR.UP)
klc.set_end_klu(klu)
klcs.append(klc)
# 建立前后关系
for i in range(len(klcs)):
if i > 0:
klcs[i].set_pre(klcs[i-1])
if i < len(klcs) - 1:
klcs[i].set_next(klcs[i+1])
# 设置分型类型
if len(klcs) >= 3:
middle_klc = klcs[1]
if (middle_klc.high > klcs[0].high and middle_klc.high > klcs[2].high):
middle_klc.set_fx(Chan_FX_TYPE.TOP)
elif (middle_klc.low < klcs[0].low and middle_klc.low < klcs[2].low):
middle_klc.set_fx(Chan_FX_TYPE.BOTTOM)
return klcs
def compare_algorithms(test_cases):
"""对比KLU和KLC算法"""
print("=" * 80)
print("KLU与KLC分型强度算法一致性测试")
print("=" * 80)
for case in test_cases:
print(f"\n🔍 测试用例: {case['name']}")
print("-" * 50)
# 准备数据
klus = setup_klu_chain(case['data'])
klcs = setup_klc_chain(case['data'])
if len(klus) >= 3 and len(klcs) >= 3:
middle_klu = klus[1]
middle_klc = klcs[1]
# KLU分析
middle_klu.update_realtime_analysis()
klu_fx_type = middle_klu.fx_type
klu_strength = middle_klu.fx_strength
klu_confirmed = middle_klu.fx_confirmed
# KLC分析
klc_fx_type = middle_klc.fx
klc_strength_raw = middle_klc.cal_fx_strength() # -3到3
klc_strength_converted = int((klc_strength_raw + 3) * 100 / 6) # 转换为0-100
# 输出对比结果
print(f"K线数据: {case['data'][1]}")
print(f"\nKLU算法结果:")
print(f" 分型类型: {klu_fx_type}")
print(f" 分型强度: {klu_strength}")
print(f" 是否确认: {klu_confirmed}")
print(f"\nKLC算法结果:")
print(f" 分型类型: {klc_fx_type}")
print(f" 分型强度(原始): {klc_strength_raw}")
print(f" 分型强度(转换): {klc_strength_converted}")
# 一致性检查
type_consistent = (klu_fx_type == klc_fx_type)
strength_diff = abs(klu_strength - klc_strength_converted)
strength_consistent = strength_diff <= 10 # 允许10分以内的差异
print(f"\n一致性检查:")
print(f" 分型类型一致: {'✅' if type_consistent else '❌'}")
print(f" 强度差异: {strength_diff}{'✅' if strength_consistent else '❌'}")
if not type_consistent or not strength_consistent:
print(f" ⚠️ 算法结果不一致!")
else:
print(f" ✅ 算法结果一致")
else:
print("❌ 数据不足,无法进行对比")
def detailed_strength_analysis():
"""详细的强度分析对比"""
print("\n" + "=" * 80)
print("详细强度分析对比")
print("=" * 80)
# 创建一个明确的强分型案例
strong_top_data = [
{'open': 100, 'high': 101, 'low': 99, 'close': 100, 'volume': 1000},
{'open': 100, 'high': 110, 'low': 99, 'close': 102, 'volume': 3000}, # 强顶分型
{'open': 102, 'high': 103, 'low': 92, 'close': 93, 'volume': 2000}, # 强确认
{'open': 93, 'high': 94, 'low': 90, 'close': 91, 'volume': 1500}, # 继续下跌
{'open': 91, 'high': 92, 'low': 88, 'close': 89, 'volume': 1200}, # 进一步确认
]
klus = setup_klu_chain(strong_top_data)
if len(klus) >= 5:
target_klu = klus[1] # 目标分型K线
print(f"分析目标: 第2根K线 (索引1)")
print(f"K线数据: {strong_top_data[1]}")
# 更新分析
target_klu.update_realtime_analysis()
print(f"\n分型检测结果:")
print(f" 分型类型: {target_klu.fx_type}")
print(f" 分型确认: {target_klu.fx_confirmed}")
print(f" 最终强度: {target_klu.fx_strength}")
# 显示中间计算过程(需要重新调用以获取详细信息)
if target_klu.fx_confirmed:
print(f"\n强度计算过程:")
is_bi_end = target_klu._check_if_bi_ending_fx()
post_confirmation = target_klu._check_post_fx_confirmation()
fx_quality = target_klu._check_fx_quality()
print(f" 笔终结判断: {is_bi_end}")
print(f" 后续确认: {post_confirmation}")
print(f" 分型质量: {fx_quality}")
raw_score = is_bi_end + post_confirmation + fx_quality
final_raw = max(-3, min(3, raw_score))
converted_score = int((final_raw + 3) * 100 / 6)
print(f" 原始总分: {raw_score} -> {final_raw}")
print(f" 转换分数: {converted_score}")
if __name__ == "__main__":
# 运行测试
test_cases = create_test_data()
compare_algorithms(test_cases)
# 详细分析
detailed_strength_analysis()
print("\n" + "=" * 80)
print("测试完成!")
print("=" * 80)