refactor: 缠论引擎包化与 Web 分层(ECR-001)
将根目录引擎迁入 chanlun/ 并保留兼容 shim;拆分 TF_DF 与 web 服务; 前端模块化;strategies 改用 chanlun 导入;补充 ESS 文档与 golden 回归。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
import sys, os
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
分型强度检测使用示例
|
||||
该文件展示如何使用ChanKLC类中新增的分型强度检测功能
|
||||
"""
|
||||
|
||||
from chanlun.core.ChanKLC import ChanKLC
|
||||
from chanlun.core.ChanEnum import Chan_FX_TYPE
|
||||
import ChanKLU
|
||||
|
||||
|
||||
def demo_fx_strength_detection():
|
||||
"""
|
||||
演示分型强度检测功能
|
||||
"""
|
||||
print("=== 分型强度检测功能演示 ===\n")
|
||||
|
||||
# 假设我们有一个已经确定为分型的KLC对象
|
||||
# 这里仅为演示,实际使用中KLC对象应该通过正常流程创建
|
||||
|
||||
print("1. 分型强度计算方法:")
|
||||
print(" - calculate_fx_strength(): 返回0-100的强度分数")
|
||||
print(" - get_fx_strength_level(): 返回强度等级描述")
|
||||
print(" - is_strong_fx(threshold): 判断是否为强分型")
|
||||
print()
|
||||
|
||||
print("2. 强度评分维度 (总分100分):")
|
||||
print(" - 价格差异强度: 40分 (与相邻K线的价格差异)")
|
||||
print(" - 突破历史点位: 20分 (是否突破重要高低点)")
|
||||
print(" - 成交量确认: 15分 (分型形成时的成交量)")
|
||||
print(" - RSI背离确认: 15分 (价格与RSI的背离)")
|
||||
print(" - MACD背离确认: 10分 (价格与MACD的背离)")
|
||||
print()
|
||||
|
||||
print("3. 强度等级分类:")
|
||||
print(" - 极强: 80-100分")
|
||||
print(" - 强: 60-79分")
|
||||
print(" - 中等: 40-59分")
|
||||
print(" - 弱: 20-39分")
|
||||
print(" - 极弱: 0-19分")
|
||||
print()
|
||||
|
||||
print("4. 在特征数据中的应用:")
|
||||
print(" 分型强度会自动集成到get_feature_data()方法返回的特征中:")
|
||||
print(" - klc_fx_strength: 强度分数")
|
||||
print(" - klc_fx_strength_level: 强度等级")
|
||||
print(" - klc_is_strong_fx: 是否为强分型(布尔值)")
|
||||
print(" - klc_fx_strength_extreme: 是否为极强分型")
|
||||
print(" - klc_fx_strength_strong: 是否为强分型")
|
||||
print(" - klc_fx_strength_medium: 是否为中等分型")
|
||||
print(" - klc_fx_strength_weak: 是否为弱分型")
|
||||
print(" - klc_fx_strength_very_weak: 是否为极弱分型")
|
||||
print()
|
||||
|
||||
|
||||
def analyze_fx_strength(klc):
|
||||
"""
|
||||
分析单个KLC的分型强度
|
||||
|
||||
Args:
|
||||
klc: ChanKLC对象
|
||||
"""
|
||||
if klc.fx == Chan_FX_TYPE.UNKNOWN:
|
||||
print(f"时间: {klc.start_time} - 无分型")
|
||||
return
|
||||
|
||||
fx_type = "顶分型" if klc.fx == Chan_FX_TYPE.TOP else "底分型"
|
||||
strength = klc.calculate_fx_strength()
|
||||
strength_level = klc.get_fx_strength_level()
|
||||
is_strong = klc.is_strong_fx()
|
||||
|
||||
print(f"时间: {klc.start_time}")
|
||||
print(f"分型类型: {fx_type}")
|
||||
print(f"强度分数: {strength}")
|
||||
print(f"强度等级: {strength_level}")
|
||||
print(f"是否强分型: {'是' if is_strong else '否'}")
|
||||
print("-" * 30)
|
||||
|
||||
|
||||
def filter_strong_fractals(klc_list, min_strength=60):
|
||||
"""
|
||||
筛选强分型
|
||||
|
||||
Args:
|
||||
klc_list: KLC对象列表
|
||||
min_strength: 最小强度阈值
|
||||
|
||||
Returns:
|
||||
强分型列表
|
||||
"""
|
||||
strong_fractals = []
|
||||
|
||||
for klc in klc_list:
|
||||
if klc.fx != Chan_FX_TYPE.UNKNOWN and klc.is_strong_fx(min_strength):
|
||||
strong_fractals.append(klc)
|
||||
|
||||
return strong_fractals
|
||||
|
||||
|
||||
def get_fractal_statistics(klc_list):
|
||||
"""
|
||||
获取分型强度统计信息
|
||||
|
||||
Args:
|
||||
klc_list: KLC对象列表
|
||||
|
||||
Returns:
|
||||
统计信息字典
|
||||
"""
|
||||
stats = {
|
||||
'total_fractals': 0,
|
||||
'top_fractals': 0,
|
||||
'bottom_fractals': 0,
|
||||
'extreme_strength': 0, # 极强
|
||||
'strong_strength': 0, # 强
|
||||
'medium_strength': 0, # 中等
|
||||
'weak_strength': 0, # 弱
|
||||
'very_weak_strength': 0,# 极弱
|
||||
'avg_strength': 0
|
||||
}
|
||||
|
||||
strengths = []
|
||||
|
||||
for klc in klc_list:
|
||||
if klc.fx != Chan_FX_TYPE.UNKNOWN:
|
||||
stats['total_fractals'] += 1
|
||||
|
||||
if klc.fx == Chan_FX_TYPE.TOP:
|
||||
stats['top_fractals'] += 1
|
||||
else:
|
||||
stats['bottom_fractals'] += 1
|
||||
|
||||
strength = klc.calculate_fx_strength()
|
||||
strengths.append(strength)
|
||||
|
||||
if strength >= 80:
|
||||
stats['extreme_strength'] += 1
|
||||
elif strength >= 60:
|
||||
stats['strong_strength'] += 1
|
||||
elif strength >= 40:
|
||||
stats['medium_strength'] += 1
|
||||
elif strength >= 20:
|
||||
stats['weak_strength'] += 1
|
||||
else:
|
||||
stats['very_weak_strength'] += 1
|
||||
|
||||
if strengths:
|
||||
stats['avg_strength'] = sum(strengths) / len(strengths)
|
||||
|
||||
return stats
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo_fx_strength_detection()
|
||||
|
||||
print("=== 使用建议 ===")
|
||||
print("1. 在交易策略中,可以只关注强度>=60的分型")
|
||||
print("2. 极强分型(>=80分)通常是重要的转折点")
|
||||
print("3. 结合成交量和技术指标背离的分型更可靠")
|
||||
print("4. 可以用分型强度来设置止损和止盈位置")
|
||||
print("5. 分型强度可以作为机器学习模型的重要特征")
|
||||
@@ -0,0 +1,222 @@
|
||||
import sys, os
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
实时K线分型强弱判断示例
|
||||
解决KLC滞后问题,提供即时的分型信号
|
||||
"""
|
||||
|
||||
from chanlun.core.ChanKLU import ChanKLU
|
||||
from chanlun.core.ChanEnum import Chan_FX_TYPE
|
||||
import pandas as pd
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
class RealtimeFxAnalyzer:
|
||||
"""实时分型分析器"""
|
||||
|
||||
def __init__(self):
|
||||
self.klu_list = []
|
||||
self.latest_signals = []
|
||||
|
||||
def add_kline(self, time, open_price, high, low, close, volume, indicators=None):
|
||||
"""
|
||||
添加新的K线数据并进行实时分析
|
||||
|
||||
Args:
|
||||
time: 时间
|
||||
open_price, high, low, close, volume: K线数据
|
||||
indicators: 技术指标字典 {'macd': xx, 'rsi': xx, 'ma5': xx, ...}
|
||||
"""
|
||||
# 创建新的KLU对象
|
||||
new_klu = ChanKLU(time, open_price, high, low, close, volume)
|
||||
|
||||
# 设置技术指标
|
||||
if indicators:
|
||||
new_klu.set_indicators(indicators)
|
||||
|
||||
# 设置索引
|
||||
new_klu.set_idx(len(self.klu_list))
|
||||
|
||||
# 建立前后关系链
|
||||
if len(self.klu_list) >= 1:
|
||||
prev_klu = self.klu_list[-1]
|
||||
new_klu.set_pre(prev_klu)
|
||||
prev_klu.set_next(new_klu)
|
||||
|
||||
# 如果有足够的数据,设置前一根K线的next关系
|
||||
if len(self.klu_list) >= 2:
|
||||
prev_prev_klu = self.klu_list[-2]
|
||||
prev_prev_klu.set_next(self.klu_list[-1])
|
||||
|
||||
self.klu_list.append(new_klu)
|
||||
|
||||
# 实时分析最近的K线分型
|
||||
self._analyze_recent_fractals()
|
||||
|
||||
return new_klu
|
||||
|
||||
def _analyze_recent_fractals(self):
|
||||
"""分析最近的分型情况"""
|
||||
if len(self.klu_list) < 3:
|
||||
return
|
||||
|
||||
# 检查倒数第二根K线的分型(因为需要左右两根K线确认)
|
||||
target_idx = len(self.klu_list) - 2
|
||||
if target_idx >= 1:
|
||||
target_klu = self.klu_list[target_idx]
|
||||
|
||||
# 进行实时分型分析
|
||||
target_klu.update_realtime_analysis()
|
||||
|
||||
# 如果发现分型,记录信号
|
||||
if target_klu.fx_confirmed:
|
||||
signal = target_klu.get_fx_signal()
|
||||
signal_info = {
|
||||
'time': target_klu.time,
|
||||
'price': target_klu.close,
|
||||
'signal_type': signal[0],
|
||||
'strength': signal[1],
|
||||
'suggestion': signal[2],
|
||||
'fx_type': target_klu.fx_type
|
||||
}
|
||||
|
||||
self.latest_signals.append(signal_info)
|
||||
|
||||
# 保持最近20个信号
|
||||
if len(self.latest_signals) > 20:
|
||||
self.latest_signals.pop(0)
|
||||
|
||||
print(f"🔔 分型信号: {signal_info['time']} - {signal_info['signal_type']} "
|
||||
f"(强度: {signal_info['strength']}) - {signal_info['suggestion']}")
|
||||
|
||||
def get_latest_signal(self):
|
||||
"""获取最新的分型信号"""
|
||||
return self.latest_signals[-1] if self.latest_signals else None
|
||||
|
||||
def get_current_fx_status(self):
|
||||
"""获取当前分型状态统计"""
|
||||
if len(self.klu_list) < 10:
|
||||
return {"status": "数据不足"}
|
||||
|
||||
recent_10 = self.klu_list[-10:]
|
||||
|
||||
top_fx_count = sum(1 for klu in recent_10 if klu.fx_type == Chan_FX_TYPE.TOP)
|
||||
bottom_fx_count = sum(1 for klu in recent_10 if klu.fx_type == Chan_FX_TYPE.BOTTOM)
|
||||
|
||||
strong_fx_count = sum(1 for klu in recent_10 if klu.fx_strength >= 65)
|
||||
|
||||
return {
|
||||
"最近10根K线": len(recent_10),
|
||||
"顶分型数量": top_fx_count,
|
||||
"底分型数量": bottom_fx_count,
|
||||
"强分型数量": strong_fx_count,
|
||||
"最新K线时间": recent_10[-1].time,
|
||||
"最新信号": self.get_latest_signal()
|
||||
}
|
||||
|
||||
def simulate_realtime_trading():
|
||||
"""模拟实时交易场景"""
|
||||
|
||||
print("=== 实时K线分型分析示例 ===\n")
|
||||
|
||||
# 创建分析器
|
||||
analyzer = RealtimeFxAnalyzer()
|
||||
|
||||
# 模拟实时K线数据流
|
||||
base_time = datetime.now()
|
||||
base_price = 100.0
|
||||
|
||||
print("开始接收K线数据...\n")
|
||||
|
||||
for i in range(20):
|
||||
# 模拟价格波动
|
||||
if i < 5: # 上涨阶段
|
||||
price_change = 0.5
|
||||
elif i < 10: # 下跌阶段
|
||||
price_change = -0.8
|
||||
elif i < 15: # 震荡阶段
|
||||
price_change = 0.3 * ((-1) ** i)
|
||||
else: # 再次上涨
|
||||
price_change = 0.6
|
||||
|
||||
current_price = base_price + price_change
|
||||
|
||||
# 构造K线数据
|
||||
open_price = base_price
|
||||
high = max(open_price, current_price) + abs(price_change) * 0.2
|
||||
low = min(open_price, current_price) - abs(price_change) * 0.2
|
||||
close = current_price
|
||||
volume = 1000 + i * 50
|
||||
|
||||
# 模拟技术指标
|
||||
indicators = {
|
||||
'ma5': base_price + (i - 10) * 0.1,
|
||||
'ma10': base_price + (i - 10) * 0.05,
|
||||
'rsi': 50 + (i % 7 - 3) * 10,
|
||||
'macd': (i % 6 - 3) * 0.01,
|
||||
'macdhist': (i % 4 - 2) * 0.005,
|
||||
'volume_ratio': 1.0 + (i % 3 - 1) * 0.2
|
||||
}
|
||||
|
||||
# 添加K线数据
|
||||
kline_time = base_time + timedelta(minutes=i)
|
||||
analyzer.add_kline(
|
||||
time=kline_time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
open_price=open_price,
|
||||
high=high,
|
||||
low=low,
|
||||
close=close,
|
||||
volume=volume,
|
||||
indicators=indicators
|
||||
)
|
||||
|
||||
base_price = current_price
|
||||
|
||||
# 每5根K线显示一次状态
|
||||
if (i + 1) % 5 == 0:
|
||||
status = analyzer.get_current_fx_status()
|
||||
print(f"\n--- 第{i+1}根K线后的状态 ---")
|
||||
for key, value in status.items():
|
||||
if key != "最新信号":
|
||||
print(f"{key}: {value}")
|
||||
|
||||
if "最新信号" in status and status["最新信号"]:
|
||||
signal = status["最新信号"]
|
||||
print(f"最新信号: {signal['signal_type']} (强度: {signal['strength']})")
|
||||
print()
|
||||
|
||||
print("\n=== 所有分型信号汇总 ===")
|
||||
for signal in analyzer.latest_signals:
|
||||
print(f"{signal['time']} | {signal['signal_type']} | 强度: {signal['strength']} | {signal['suggestion']}")
|
||||
|
||||
def compare_latency():
|
||||
"""对比KLC和KLU方法的延迟差异"""
|
||||
|
||||
print("\n=== 延迟对比分析 ===")
|
||||
print("假设场景:连续包含关系的K线序列")
|
||||
print("原始K线: K1, K2(包含K1), K3(包含K2), K4(突破), K5, K6")
|
||||
print()
|
||||
|
||||
print("KLC方法:")
|
||||
print("- 需要等待K4确认包含关系结束")
|
||||
print("- KLC1 = [K1+K2+K3], 在K4完成时才确定")
|
||||
print("- 分型检测: 需要等待KLC1, KLC2, KLC3")
|
||||
print("- 实际延迟: 可能6-8根原始K线")
|
||||
print()
|
||||
|
||||
print("KLU实时方法:")
|
||||
print("- 每根K线完成时立即检测")
|
||||
print("- K3完成时就能检测K2的分型状态")
|
||||
print("- 实际延迟: 最多1根K线")
|
||||
print()
|
||||
|
||||
print("延迟改善: 从6-8根K线缩短到1根K线")
|
||||
print("时间价值: 在5分钟K线下,可节省25-40分钟的反应时间")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 运行模拟
|
||||
simulate_realtime_trading()
|
||||
|
||||
# 显示延迟对比
|
||||
compare_latency()
|
||||
Reference in New Issue
Block a user