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:
+2
-141
@@ -1,141 +1,2 @@
|
||||
from ChanEnum import Chan_MACD_STATE, Chan_MACDUNITTF_DIR, Chan_MACDHISTSET_DIR, Chan_MACDUNITTF_DIV, Chan_MACDUNITTF_TYPE
|
||||
|
||||
|
||||
class ChanMACDUnitTF():
|
||||
def __init__(self, index, start_time, start_klu, pre_unittf, unittf_dir, start_type, start_histset):
|
||||
self.index = index
|
||||
self.start_time = start_time
|
||||
self.end_time = None
|
||||
self.start_klu = start_klu
|
||||
self.end_klu = None
|
||||
self.klu_list = []
|
||||
self.klu_list.append(start_klu)
|
||||
self.histset_list = []
|
||||
self.histset_list.append(start_histset)
|
||||
self.div_count = 0
|
||||
start_histset.set_middle_klu(start_klu)
|
||||
self.next = None
|
||||
self.pre = pre_unittf
|
||||
self.unittf_dir = unittf_dir
|
||||
self.start_type = start_type
|
||||
self.end_type = None
|
||||
self.peak_klu = None
|
||||
self.div_type = Chan_MACDUNITTF_DIV.UNDIV
|
||||
self.div_peak_list = []
|
||||
self.is_end = False
|
||||
def set_next(self, next_unittf):
|
||||
self.next = next_unittf
|
||||
def set_pre(self, pre_unittf):
|
||||
self.pre = pre_unittf
|
||||
def add_histset(self, histset):
|
||||
self.histset_list.append(histset)
|
||||
def add_klu(self, klu):
|
||||
self.klu_list.append(klu)
|
||||
self.cal_peak_div()
|
||||
self.cal_macd_state()
|
||||
def cal_peak_div(self):
|
||||
self.div_count = 0
|
||||
self.div_peak_list = []
|
||||
self.peak_klu = None
|
||||
if len(self.histset_list) == 0:
|
||||
return
|
||||
if len(self.histset_list) == 1:
|
||||
self.div_type = self.histset_list[0].unittf_div
|
||||
self.peak_klu = self.histset_list[0].peak_klu
|
||||
else:
|
||||
|
||||
for index in range(0, len(self.histset_list)):
|
||||
histset = self.histset_list[index]
|
||||
if self.same_dir(histset):
|
||||
#if histset.peak_klu:
|
||||
#print("Unittf: ", self.start_klu.time, len(self.histset_list), histset.peak_klu.time)
|
||||
if self.peak_klu:
|
||||
if histset.peak_klu:
|
||||
if abs(histset.peak_klu.macdhist) >= abs(self.peak_klu.macdhist):
|
||||
self.peak_klu = histset.peak_klu
|
||||
self.div_type = Chan_MACDUNITTF_DIV.UNDIV
|
||||
self.div_count = 0
|
||||
else:
|
||||
self.div_type = Chan_MACDUNITTF_DIV.DISCRETE
|
||||
self.div_count += 1
|
||||
self.div_peak_list.append(histset.peak_klu)
|
||||
#print("Unittf: ", self.start_klu.time)
|
||||
if histset.peak_klu.macd > 0 and histset.histset_dir == Chan_MACDHISTSET_DIR.ABOVE:
|
||||
histset.peak_klu.set_separate_div(self.div_count)
|
||||
elif histset.peak_klu.macd < 0 and histset.histset_dir == Chan_MACDHISTSET_DIR.UNDER:
|
||||
histset.peak_klu.set_separate_div(self.div_count)
|
||||
else:
|
||||
if histset.peak_klu:
|
||||
self.peak_klu = histset.peak_klu
|
||||
def cal_macd_state(self):
|
||||
if len(self.klu_list) > 0:
|
||||
last_klu = self.klu_list[0]
|
||||
macd_peak_klu = None
|
||||
signal_peak_klu = None
|
||||
for index in range(1, len(self.klu_list)):
|
||||
klu = self.klu_list[index]
|
||||
if klu.macd == 0 and klu.signal == 0 and klu.macdhist == 0:
|
||||
continue
|
||||
if self.start_type == Chan_MACDUNITTF_TYPE.CROSS0 or self.start_type == Chan_MACDUNITTF_TYPE.NEAR0:
|
||||
if self.unittf_dir == Chan_MACDUNITTF_DIR.ABOVE:
|
||||
if macd_peak_klu is None:
|
||||
if last_klu.macd < klu.macd:
|
||||
if last_klu.signal < last_klu.macdhist:
|
||||
last_klu.set_macd_state(Chan_MACD_STATE.UP)
|
||||
else:
|
||||
last_klu.set_macd_state(Chan_MACD_STATE.HIGH)
|
||||
else:
|
||||
macd_peak_klu = last_klu
|
||||
last_klu.set_macd_state(Chan_MACD_STATE.PEAK)
|
||||
elif klu.macd > macd_peak_klu.macd:
|
||||
macd_peak_klu = None
|
||||
last_klu.set_macd_state(Chan_MACD_STATE.HIGH)
|
||||
elif last_klu.signal < klu.signal:
|
||||
last_klu.set_macd_state(Chan_MACD_STATE.HIGH_EMPTY)
|
||||
elif signal_peak_klu is None:
|
||||
signal_peak_klu = last_klu
|
||||
last_klu.set_macd_state(Chan_MACD_STATE.HIGH_EMPTY)
|
||||
elif klu.signal > signal_peak_klu.signal:
|
||||
signal_peak_klu = None
|
||||
last_klu.set_macd_state(Chan_MACD_STATE.HIGH)
|
||||
elif last_klu.macd < last_klu.signal:
|
||||
last_klu.set_macd_state(Chan_MACD_STATE.RETURN_ZERO)
|
||||
if self.return_zero(last_klu, klu):
|
||||
self.end_type = Chan_MACDUNITTF_TYPE.NEAR0
|
||||
self.is_end = True
|
||||
self.end_klu = klu
|
||||
self.end_time = klu.time
|
||||
klu.set_macd_state(Chan_MACD_STATE.NEAR0)
|
||||
#print(self.index, last_klu.time, last_klu.macd, last_klu.signal, last_klu.macd_state, klu.macd_state)
|
||||
break
|
||||
#print(self.index, last_klu.time, last_klu.macd, last_klu.signal, last_klu.macd_state)
|
||||
last_klu = klu
|
||||
|
||||
def return_zero(self, last_klu, klu):
|
||||
return_zero = False
|
||||
if last_klu.close < last_klu.ema52 and klu.close > klu.ema52:
|
||||
return_zero = True
|
||||
return_zero = False
|
||||
return return_zero
|
||||
def same_dir(self, histset):
|
||||
if self.unittf_dir == Chan_MACDUNITTF_DIR.ABOVE:
|
||||
return histset.histset_dir == Chan_MACDHISTSET_DIR.ABOVE
|
||||
else:
|
||||
return histset.histset_dir == Chan_MACDHISTSET_DIR.UNDER
|
||||
def set_end_klu(self, end_klu, end_type):
|
||||
self.end_type = end_type
|
||||
self.end_klu = end_klu
|
||||
self.end_time = end_klu.time
|
||||
self.is_end = True
|
||||
self.cal_macd_state()
|
||||
div_time = ""
|
||||
for div in self.div_peak_list:
|
||||
div_time += f"{div.time}, "
|
||||
histset_time = ""
|
||||
for histset in self.histset_list:
|
||||
histset_time += f"{histset.start_time}, "
|
||||
|
||||
#if self.peak_klu and self.div_type == Chan_MACDUNITTF_DIV.DISCRETE:
|
||||
#print("Cross Div: ", self.start_klu.time, self.peak_klu.time, self.div_count, self.div_type, self.unittf_dir, div_time, len(self.histset_list))
|
||||
|
||||
|
||||
"""兼容 shim — 请优先 from chanlun import ..."""
|
||||
from chanlun.indicators.ChanMACDUnitTF import * # noqa: F403
|
||||
|
||||
Reference in New Issue
Block a user