add macd判断背离,使用分型和隐形形态实现第二类买卖点
This commit is contained in:
+267
-3
@@ -18,8 +18,9 @@ import numpy as np
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from ChanLun import ChanLun
|
||||
from ChanEnum import Chan_BI_DIR, Chan_SEG_DIR, Chan_KLC_FX, Chan_FX_TYPE
|
||||
from ChanEnum import Chan_BI_DIR, Chan_SEG_DIR, Chan_KLC_FX, Chan_FX_TYPE, Chan_MACDSEG_DIR, Chan_MACDHISTSET_DIR
|
||||
from cn_stock_data import ChinaStockData
|
||||
from ChanMACD import ChanMACD
|
||||
|
||||
# 添加买卖点枚举类型
|
||||
class TRADE_POINT_TYPE:
|
||||
@@ -363,6 +364,58 @@ def analyze_chan(df):
|
||||
bi.cal_macd_div()
|
||||
#print(bi.start_time, bi.macd_hist, bi.macd_div)
|
||||
|
||||
# 添加ChanMACD分析
|
||||
chan_macd = None
|
||||
chan_macd_data = {}
|
||||
try:
|
||||
# 直接使用ChanLun的get_klu_list方法获取KLU列表
|
||||
klu_list = chan.get_klu_list(df)
|
||||
|
||||
if klu_list and len(klu_list) > 0:
|
||||
print(f"获取到KLU列表,长度: {len(klu_list)}")
|
||||
chan_macd = ChanMACD(klu_list)
|
||||
chan_macd_data = {
|
||||
'seg_list': chan_macd.seg_list,
|
||||
'unittf_list': chan_macd.unittf_list,
|
||||
'histset_list': chan_macd.histset_list,
|
||||
'high_position_list': chan_macd.high_position_list,
|
||||
'high_empty_list': chan_macd.high_empty_list,
|
||||
'low_position_list': getattr(chan_macd, 'low_position_list', []),
|
||||
'low_empty_list': getattr(chan_macd, 'low_empty_list', []),
|
||||
'return_zero_list': chan_macd.return_zero_list,
|
||||
'cross0_up_list': chan_macd.cross0_up_list,
|
||||
'cross0_down_list': chan_macd.cross0_down_list
|
||||
}
|
||||
print(f"ChanMACD分析完成: seg={len(chan_macd.seg_list)}, unittf={len(chan_macd.unittf_list)}, histset={len(chan_macd.histset_list)}")
|
||||
else:
|
||||
print("未能获取KLU列表或列表为空")
|
||||
chan_macd_data = {
|
||||
'seg_list': [],
|
||||
'unittf_list': [],
|
||||
'histset_list': [],
|
||||
'high_position_list': [],
|
||||
'high_empty_list': [],
|
||||
'return_zero_list': [],
|
||||
'cross0_up_list': [],
|
||||
'cross0_down_list': []
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"ChanMACD分析出错: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
chan_macd_data = {
|
||||
'seg_list': [],
|
||||
'unittf_list': [],
|
||||
'histset_list': [],
|
||||
'high_position_list': [],
|
||||
'high_empty_list': [],
|
||||
'low_position_list': [],
|
||||
'low_empty_list': [],
|
||||
'return_zero_list': [],
|
||||
'cross0_up_list': [],
|
||||
'cross0_down_list': []
|
||||
}
|
||||
|
||||
# 获取原始K线数据用于KLU分型分析
|
||||
klu_list = []
|
||||
try:
|
||||
@@ -490,7 +543,8 @@ def analyze_chan(df):
|
||||
'zs_list': zs_list,
|
||||
'trade_points': buy_sell_points,
|
||||
'klc_fx_info': klc_fx_info, # KLC分型信息
|
||||
'klu_fx_info': klu_fx_info # 添加KLU分型信息
|
||||
'klu_fx_info': klu_fx_info, # 添加KLU分型信息
|
||||
'chan_macd': chan_macd_data # 添加ChanMACD分析数据
|
||||
}
|
||||
|
||||
def generate_replay_data(df, client_tz, symbol=None, element_timeframe=None, start_time=None, end_time=None):
|
||||
@@ -981,6 +1035,211 @@ def format_time_safely(time_obj, client_tz):
|
||||
# 已经是datetime对象
|
||||
return time_obj.astimezone(client_tz).isoformat()
|
||||
|
||||
def serialize_chan_macd_data(chan_macd_data, client_tz):
|
||||
"""序列化ChanMACD数据为JSON可序列化格式"""
|
||||
serialized_data = {
|
||||
'seg_list': [],
|
||||
'unittf_list': [],
|
||||
'histset_list': [],
|
||||
# 状态标记数据
|
||||
'high_position_list': [],
|
||||
'high_empty_list': [],
|
||||
'low_position_list': [],
|
||||
'low_empty_list': [],
|
||||
'return_zero_list': [],
|
||||
'cross0_up_list': [],
|
||||
'cross0_down_list': []
|
||||
}
|
||||
|
||||
# 序列化seg_list
|
||||
for seg in chan_macd_data.get('seg_list', []):
|
||||
try:
|
||||
seg_data = {
|
||||
'start_time': format_time_safely(seg.start_time, client_tz),
|
||||
'end_time': format_time_safely(seg.end_time, client_tz) if seg.end_time else None,
|
||||
'seg_dir': 'ABOVE' if seg.seg_dir == Chan_MACDSEG_DIR.ABOVE else 'UNDER',
|
||||
'klu_count': len(seg.klu_list) if hasattr(seg, 'klu_list') else 0,
|
||||
'unittf_count': len(seg.unittf_list) if hasattr(seg, 'unittf_list') else 0,
|
||||
'histset_count': len(seg.hist_set) if hasattr(seg, 'hist_set') else 0
|
||||
}
|
||||
serialized_data['seg_list'].append(seg_data)
|
||||
except Exception as e:
|
||||
print(f"序列化seg出错: {e}")
|
||||
continue
|
||||
|
||||
# 序列化unittf_list(兼容新结构与枚举类型)
|
||||
for unittf in chan_macd_data.get('unittf_list', []):
|
||||
try:
|
||||
dir_value = getattr(unittf, 'uinttf_dir', None)
|
||||
dir_name = getattr(dir_value, 'name', dir_value if isinstance(dir_value, str) else None)
|
||||
start_t = getattr(unittf, 'start_type', None)
|
||||
start_type = getattr(start_t, 'name', start_t)
|
||||
end_t = getattr(unittf, 'end_type', None)
|
||||
end_type = getattr(end_t, 'name', end_t)
|
||||
peak_abs = getattr(unittf, 'peak_abs', None)
|
||||
if peak_abs is None:
|
||||
peak_abs = getattr(unittf, 'peak_hist', None)
|
||||
length = getattr(unittf, 'length', None)
|
||||
if length is None:
|
||||
length = len(unittf.klu_list) if hasattr(unittf, 'klu_list') else None
|
||||
|
||||
unittf_data = {
|
||||
'start_time': format_time_safely(getattr(unittf, 'start_time', None), client_tz),
|
||||
'end_time': format_time_safely(getattr(unittf, 'end_time', None), client_tz) if getattr(unittf, 'end_time', None) else None,
|
||||
'dir': dir_name, # 'ABOVE' | 'UNDER' | None
|
||||
'start_type': start_type, # e.g. 'START' | 'CROSS0' | 'NEAR0_UP' | 'NEAR0_DOWN'
|
||||
'end_type': end_type,
|
||||
'invalid': getattr(unittf, 'invalid', False),
|
||||
'peak_abs': peak_abs,
|
||||
'length': length,
|
||||
'klu_count': len(unittf.klu_list) if hasattr(unittf, 'klu_list') else 0,
|
||||
'histset_count': len(unittf.histset_list) if hasattr(unittf, 'histset_list') else 0
|
||||
}
|
||||
serialized_data['unittf_list'].append(unittf_data)
|
||||
except Exception as e:
|
||||
print(f"序列化unittf出错: {e}")
|
||||
continue
|
||||
|
||||
# 序列化histset_list
|
||||
for histset in chan_macd_data.get('histset_list', []):
|
||||
try:
|
||||
histset_data = {
|
||||
'start_time': format_time_safely(getattr(histset, 'start_time', None), client_tz),
|
||||
'end_time': format_time_safely(getattr(histset, 'end_time', None), client_tz),
|
||||
'histset_dir': 'ABOVE' if histset.histset_dir == Chan_MACDHISTSET_DIR.ABOVE else 'UNDER',
|
||||
'klu_count': len(histset.klu_list) if hasattr(histset, 'klu_list') else 0
|
||||
}
|
||||
serialized_data['histset_list'].append(histset_data)
|
||||
except Exception as e:
|
||||
print(f"序列化histset出错: {e}")
|
||||
continue
|
||||
|
||||
# 序列化状态标记数据
|
||||
# 序列化高位列表
|
||||
for high_pos in chan_macd_data.get('high_position_list', []):
|
||||
try:
|
||||
high_pos_data = {
|
||||
'time': format_time_safely(high_pos['time'], client_tz),
|
||||
'end_time': format_time_safely(high_pos.get('end_time'), client_tz) if high_pos.get('end_time') else None,
|
||||
'type': high_pos.get('type', 'start'),
|
||||
'macd': high_pos.get('macd'),
|
||||
'signal': high_pos.get('signal'),
|
||||
'macdhist': high_pos.get('macdhist'),
|
||||
'end_macd': high_pos.get('end_macd'),
|
||||
'end_signal': high_pos.get('end_signal'),
|
||||
'end_macdhist': high_pos.get('end_macdhist')
|
||||
}
|
||||
serialized_data['high_position_list'].append(high_pos_data)
|
||||
except Exception as e:
|
||||
print(f"序列化high_position出错: {e}")
|
||||
continue
|
||||
|
||||
# 序列化高位空列表
|
||||
for high_empty in chan_macd_data.get('high_empty_list', []):
|
||||
try:
|
||||
high_empty_data = {
|
||||
'time': format_time_safely(high_empty['time'], client_tz),
|
||||
'end_time': format_time_safely(high_empty.get('end_time'), client_tz) if high_empty.get('end_time') else None,
|
||||
'type': high_empty.get('type', 'start'),
|
||||
'macd': high_empty.get('macd'),
|
||||
'signal': high_empty.get('signal'),
|
||||
'macdhist': high_empty.get('macdhist'),
|
||||
'end_macd': high_empty.get('end_macd'),
|
||||
'end_signal': high_empty.get('end_signal'),
|
||||
'end_macdhist': high_empty.get('end_macdhist')
|
||||
}
|
||||
serialized_data['high_empty_list'].append(high_empty_data)
|
||||
except Exception as e:
|
||||
print(f"序列化high_empty出错: {e}")
|
||||
continue
|
||||
|
||||
# 序列化低位与低位空
|
||||
for low_pos in chan_macd_data.get('low_position_list', []):
|
||||
try:
|
||||
low_pos_data = {
|
||||
'time': format_time_safely(low_pos['time'], client_tz),
|
||||
'end_time': format_time_safely(low_pos.get('end_time'), client_tz) if low_pos.get('end_time') else None,
|
||||
'type': low_pos.get('type', 'start'),
|
||||
'macd': low_pos.get('macd'),
|
||||
'signal': low_pos.get('signal'),
|
||||
'macdhist': low_pos.get('macdhist'),
|
||||
'end_macd': low_pos.get('end_macd'),
|
||||
'end_signal': low_pos.get('end_signal'),
|
||||
'end_macdhist': low_pos.get('end_macdhist')
|
||||
}
|
||||
serialized_data['low_position_list'].append(low_pos_data)
|
||||
except Exception as e:
|
||||
print(f"序列化low_position出错: {e}")
|
||||
continue
|
||||
|
||||
for low_empty in chan_macd_data.get('low_empty_list', []):
|
||||
try:
|
||||
low_empty_data = {
|
||||
'time': format_time_safely(low_empty['time'], client_tz),
|
||||
'end_time': format_time_safely(low_empty.get('end_time'), client_tz) if low_empty.get('end_time') else None,
|
||||
'type': low_empty.get('type', 'start'),
|
||||
'macd': low_empty.get('macd'),
|
||||
'signal': low_empty.get('signal'),
|
||||
'macdhist': low_empty.get('macdhist'),
|
||||
'end_macd': low_empty.get('end_macd'),
|
||||
'end_signal': low_empty.get('end_signal'),
|
||||
'end_macdhist': low_empty.get('end_macdhist')
|
||||
}
|
||||
serialized_data['low_empty_list'].append(low_empty_data)
|
||||
except Exception as e:
|
||||
print(f"序列化low_empty出错: {e}")
|
||||
continue
|
||||
|
||||
# 序列化归零轴列表
|
||||
for return_zero in chan_macd_data.get('return_zero_list', []):
|
||||
try:
|
||||
return_zero_data = {
|
||||
'time': format_time_safely(return_zero['time'], client_tz),
|
||||
'end_time': format_time_safely(return_zero.get('end_time'), client_tz) if return_zero.get('end_time') else None,
|
||||
'type': return_zero.get('type', 'start'),
|
||||
'macd': return_zero.get('macd'),
|
||||
'signal': return_zero.get('signal'),
|
||||
'macdhist': return_zero.get('macdhist'),
|
||||
'end_macd': return_zero.get('end_macd'),
|
||||
'end_signal': return_zero.get('end_signal'),
|
||||
'end_macdhist': return_zero.get('end_macdhist')
|
||||
}
|
||||
serialized_data['return_zero_list'].append(return_zero_data)
|
||||
except Exception as e:
|
||||
print(f"序列化return_zero出错: {e}")
|
||||
continue
|
||||
|
||||
# 序列化穿越零轴列表
|
||||
for cross0_up in chan_macd_data.get('cross0_up_list', []):
|
||||
try:
|
||||
cross0_up_data = {
|
||||
'time': format_time_safely(cross0_up['time'], client_tz),
|
||||
'type': cross0_up.get('type', 'start'),
|
||||
'macd': cross0_up.get('macd'),
|
||||
'signal': cross0_up.get('signal'),
|
||||
'macdhist': cross0_up.get('macdhist')
|
||||
}
|
||||
serialized_data['cross0_up_list'].append(cross0_up_data)
|
||||
except Exception as e:
|
||||
print(f"序列化cross0_up出错: {e}")
|
||||
continue
|
||||
|
||||
for cross0_down in chan_macd_data.get('cross0_down_list', []):
|
||||
try:
|
||||
cross0_down_data = {
|
||||
'time': format_time_safely(cross0_down['time'], client_tz),
|
||||
'type': cross0_down.get('type', 'start'),
|
||||
'macd': cross0_down.get('macd'),
|
||||
'signal': cross0_down.get('signal'),
|
||||
'macdhist': cross0_down.get('macdhist')
|
||||
}
|
||||
serialized_data['cross0_down_list'].append(cross0_down_data)
|
||||
except Exception as e:
|
||||
print(f"序列化cross0_down出错: {e}")
|
||||
continue
|
||||
|
||||
return serialized_data
|
||||
|
||||
def is_smaller_timeframe(tf1, tf2):
|
||||
"""判断时间周期tf1是否小于tf2"""
|
||||
# 定义时间周期的分钟数映射
|
||||
@@ -1439,7 +1698,9 @@ def analyze():
|
||||
'fx_strength_level': str(point['fx_strength_level']), # 分型强度等级
|
||||
'is_strong_fx': bool(point['is_strong_fx']), # 是否为强分型
|
||||
'fx_confirmed': bool(point['fx_confirmed']) # 分型是否确认
|
||||
} for point in analysis_result['klu_fx_info']]
|
||||
} for point in analysis_result['klu_fx_info']],
|
||||
# 添加ChanMACD分析数据
|
||||
'chan_macd': serialize_chan_macd_data(analysis_result.get('chan_macd', {}), client_tz)
|
||||
})
|
||||
|
||||
# 如果生成了回放数据,添加到返回结果中
|
||||
@@ -1563,6 +1824,9 @@ def analyze():
|
||||
'fx_confirmed': bool(point['fx_confirmed']) # 分型是否确认
|
||||
} for point in element_analysis['klu_fx_info']]
|
||||
|
||||
# 添加次周期ChanMACD分析数据
|
||||
result['element_chan_macd'] = serialize_chan_macd_data(element_analysis.get('chan_macd', {}), client_tz)
|
||||
|
||||
pass
|
||||
|
||||
return jsonify(result)
|
||||
|
||||
Reference in New Issue
Block a user