diff --git a/ChanBIZS.py b/ChanBIZS.py index cffdf87..459a6c9 100644 --- a/ChanBIZS.py +++ b/ChanBIZS.py @@ -21,11 +21,11 @@ class ChanBIZS(): self.sure_time = None self.end_klc = None self.zs_type = Chan_ZS_TYPE.NORMAL - def set_end_bi(self, end_bi, sure_bi): + def set_end_bi(self, end_bi, sure_time): self.end_bi = end_bi self.set_end_time(end_bi.end_klc.end_time) self.is_sure = True - self.sure_time = sure_bi.sure_time + self.sure_time = sure_time #print(self.start_time, self.is_sure, len(self.bi_list), self.dir, self.zs_type) def set_end_time(self, end_time): self.end_time = end_time @@ -41,7 +41,10 @@ class ChanBIZS(): if bi: self.bi_list.append(bi) self.classify_zs() - + def set_pre(self, pre): + self.pre = pre + def set_next(self, next): + self.next = next def classify_zs(self): """ 根据中枢内笔的高低点变化趋势,对中枢进行分类 diff --git a/ChanKLC.py b/ChanKLC.py index 1643752..7d09b97 100644 --- a/ChanKLC.py +++ b/ChanKLC.py @@ -370,7 +370,7 @@ class ChanKLC(): else: high = last_top.high low = self.low - last_top.fx_box = Chan_FX_Box.Chan_FX_Box(last_top.pre.end_time, self.end_time, high, low) + last_top.fx_box = Chan_FX_Box.Chan_FX_Box(last_top.pre.start_time, self.end_time, high, low) #print(self.end_time, "fx_confirmed new box top") elif self.in_fx == False and last_bottom.fx_confirmed == False: pre = last_bottom.pre @@ -382,7 +382,7 @@ class ChanKLC(): else: high = self.high low = last_bottom.low - last_bottom.fx_box = Chan_FX_Box.Chan_FX_Box(last_bottom.pre.end_time, self.end_time, high, low) + last_bottom.fx_box = Chan_FX_Box.Chan_FX_Box(last_bottom.pre.start_time, self.end_time, high, low) #print(self.end_time, "fx_confirmed new box bottom") def add_klu(self, klu): self.klu_list.append(klu) diff --git a/ChanKLU.py b/ChanKLU.py index 4be0cda..eeb32b3 100644 --- a/ChanKLU.py +++ b/ChanKLU.py @@ -233,14 +233,18 @@ class ChanKLU: self.near0_return = 0 elif self.close > self.ema52 and self.high > self.ema52 and self.low < self.ema52: self.near0_return = 0 + # 向上穿越EMA52 7 if self.close > self.ema52 and self.open < self.ema52: - self.near0_return = 7 + self.near0_return = 0 + # 向下穿越EMA52 8 elif self.close < self.ema52 and self.open > self.ema52: - self.near0_return = 8 + self.near0_return = 0 if self.pre.near0_return == 7: + # 向上穿越后的一根价格再EMA52上方 9 if self.low > self.ema52 and self.close > self.open: self.near0_return = 9 if self.pre.near0_return == 8: + # 向下穿越后的一根价格再EMA52下方 10 if self.high < self.ema52 and self.close < self.open: self.near0_return = 10 # CROSS0 仅以 Signal 穿越零轴判定 diff --git a/ChanLun.py b/ChanLun.py index 1e12ba9..2bb5d6b 100644 --- a/ChanLun.py +++ b/ChanLun.py @@ -163,6 +163,9 @@ class ChanLun(): return self.tf_df.get_zs_list(bi_list, seg_list) def cal_bi_zs(self, seg_list): return self.tf_df.cal_bi_zs(seg_list) + def cal_bi_zs_list(self, bi_list): + #return self.tf_df.cal_bi_zs(bi_list) + return self.tf_df.cal_bi_zs_list(bi_list) def get_decimal(self, value): return Decimal("{:.2f}".format(value)) def get_klc_list(self, klu_list): diff --git a/ChanSEG.py b/ChanSEG.py index 4412085..230931d 100644 --- a/ChanSEG.py +++ b/ChanSEG.py @@ -113,7 +113,7 @@ class ChanSEG(): else: if bi.index > last_zs.bi_list[-1].index and bi.dir == Chan_BI_DIR.DOWN and bi.is_sure: if bi.low > last_zs.zg or bi.high < last_zs.zd: - last_zs.set_end_bi(last_zs.bi_list[-1], bi) + last_zs.set_end_bi(last_zs.bi_list[-1], last_zs.bi_list[-1].sure_time) if bi.next and bi.next.next and bi.next.next.is_sure and bi.next.next.index <= self.bi_list[-1].index and bi.check_bi_zs_overlap() and bi.dir == Chan_BI_DIR.DOWN: zg = min(bi.high, bi.next.high, bi.next.next.high) zd = max(bi.low, bi.next.low, bi.next.next.low) @@ -133,7 +133,7 @@ class ChanSEG(): last_zs.add_bi(bi) if index == len(self.bi_list) - 1 and last_zs and not last_zs.is_sure: #print(bi.start_time, "BI", last_zs.is_sure) - last_zs.set_end_bi(last_zs.bi_list[-1], last_zs.bi_list[-1]) + last_zs.set_end_bi(last_zs.bi_list[-1], last_zs.bi_list[-1].sure_time) else: for index in range(1, len(self.bi_list)): bi = self.bi_list[index] @@ -155,7 +155,7 @@ class ChanSEG(): else: if bi.index > last_zs.bi_list[-1].index and bi.dir == Chan_BI_DIR.UP and bi.is_sure: if bi.low > last_zs.zg or bi.high < last_zs.zd: - last_zs.set_end_bi(last_zs.bi_list[-1], bi) + last_zs.set_end_bi(last_zs.bi_list[-1], last_zs.bi_list[-1].sure_time) if bi.next and bi.next.next and bi.next.next.is_sure and bi.next.next.index <= self.bi_list[-1].index and bi.check_bi_zs_overlap() and bi.dir == Chan_BI_DIR.UP: zg = min(bi.high, bi.next.high, bi.next.next.high) zd = max(bi.low, bi.next.low, bi.next.next.low) @@ -175,7 +175,7 @@ class ChanSEG(): last_zs.add_bi(bi) if index == len(self.bi_list) - 1 and last_zs and not last_zs.is_sure: #print(bi.start_time, "BI", last_zs.is_sure) - last_zs.set_end_bi(last_zs.bi_list[-1], last_zs.bi_list[-1]) + last_zs.set_end_bi(last_zs.bi_list[-1], last_zs.bi_list[-1].sure_time) #print(self.start_time, len(zs_list)) #print(self.bi_list[-1].end_time, "end_bi") diff --git a/TF_DF.py b/TF_DF.py index 8d75610..e130cbb 100644 --- a/TF_DF.py +++ b/TF_DF.py @@ -7,6 +7,7 @@ from ChanBI import ChanBI from ChanSBI import ChanSBI from ChanSEG import ChanSEG from ChanZS import ChanZS, ChanZS_Big +from ChanBIZS import ChanBIZS from ChanBSP import ChanBSP import talib.abstract as ta import pandas as pd @@ -72,8 +73,8 @@ class TF_DF(): return self.klc_list[-2] return None def add_indicators(self, df): - fast = 12 - slow = 26 + fast = 26 + slow = 52 period = 9 macd = ta.MACD(df, fastperiod=fast, slowperiod=slow, signalperiod=period) bb365 = ta.BBANDS(df, timeperiod=365, nbdevup=3.0, nbdevdn=3.0, matype=0) @@ -175,6 +176,23 @@ class TF_DF(): klu_state_list.append("0") return klu_state_list def check_fx(self, klc): + if klc.pre and klc.next: + if klc.high > klc.pre.high and klc.high > klc.next.high and klc.low > klc.pre.low and klc.low > klc.next.low: + if klc.pre.pre and klc.next.next: + if klc.high > klc.pre.pre.high and klc.high > klc.next.next.high: + #if (klc.close > klc.ema52 or klc.next.close > klc.next.ema52) and klc.macd > 0: + klc.set_fx(Chan_FX_TYPE.TOP) + #print(klc.start_time, klc.end_time,klc.next.start_time, klc.next.end_time, klc.macd, klc.state, klc.fx, "TOP") + return Chan_FX_TYPE.TOP + elif klc.low < klc.pre.low and klc.low < klc.next.low and klc.high < klc.pre.high and klc.high < klc.next.high: + #if (klc.close < klc.ema52 or klc.next.close < klc.next.ema52) and klc.macd < 0: + if klc.pre.pre and klc.next.next: + if klc.low < klc.pre.pre.low and klc.low < klc.next.next.low: + klc.set_fx(Chan_FX_TYPE.BOTTOM) + #print(klc.start_time, klc.end_time,klc.next.start_time, klc.next.end_time, klc.macd, klc.state, klc.fx, "BOTTOM") + return Chan_FX_TYPE.BOTTOM + return Chan_FX_TYPE.UNKNOWN + def check_fx1(self, klc): if klc.pre and klc.next: if klc.high > klc.pre.high and klc.high > klc.next.high and klc.low > klc.pre.low and klc.low > klc.next.low: #if (klc.close > klc.ema52 or klc.next.close > klc.next.ema52) and klc.macd > 0: @@ -903,7 +921,7 @@ class TF_DF(): last_seg_bi = bi_list[i] break """ - self.cal_bi_zs(seg_list) + #self.cal_bi_zs(seg_list) return seg_list def cal_bi_list(self, klc_list): @@ -917,11 +935,11 @@ class TF_DF(): klc.check_klc_state(last_fx_klc) klc.check_fx_confirmed(last_top, last_bottom) fx = self.check_fx(klc) - if fx == Chan_FX_TYPE.TOP and False: + if fx == Chan_FX_TYPE.TOP: if last_bottom: if self.check_top_fx(last_bottom, klc) == False: fx = Chan_FX_TYPE.UNKNOWN - if fx == Chan_FX_TYPE.BOTTOM and False: + if fx == Chan_FX_TYPE.BOTTOM: if last_top: if self.check_bottom_fx(last_top, klc) == False: #print(klc.end_time, last_top.end_time, "---") @@ -1250,7 +1268,137 @@ class TF_DF(): for seg in seg_list: zs_list = seg.cal_bi_zs() if len(zs_list) > 0: - bi_zs_list.append(zs_list) + bi_zs_list = list(bi_zs_list) + list(zs_list) + return bi_zs_list + def cal_bi_zs_list(self, bi_list): + """ + 根据缠论笔中枢定义计算中枢(参照 get_zs_list 线段中枢判断规则) + 从第4根笔开始(索引3),每3根笔为一组检查 + 上涨中枢:后中枢 zd > 前中枢 zg(不重叠上移) + 下跌中枢:后中枢 zg < 前中枢 zd(不重叠下移) + 中枢可按两笔一组继续扩展到5根、7根... + """ + bi_zs_list = [] + if len(bi_list) < 3: + return bi_zs_list + + last_zs = None + start_idx = 3 + + while start_idx < len(bi_list): + if start_idx + 2 >= len(bi_list): + break + + bi1 = bi_list[start_idx] + bi2 = bi_list[start_idx + 1] + bi3 = bi_list[start_idx + 2] + + if not (bi1.is_sure and bi2.is_sure and bi3.is_sure): + start_idx += 1 + continue + + zg = min(bi1.high, bi2.high, bi3.high) + zd = max(bi1.low, bi2.low, bi3.low) + + if zg <= zd: + start_idx += 1 + continue + + valid = False + if last_zs is None: + if bi1.dir == Chan_BI_DIR.DOWN: + zs_dir = Chan_ZS_DIR.UP + valid = (bi2.dir == Chan_BI_DIR.UP and bi3.dir == Chan_BI_DIR.DOWN) + else: + zs_dir = Chan_ZS_DIR.DOWN + valid = (bi2.dir == Chan_BI_DIR.DOWN and bi3.dir == Chan_BI_DIR.UP) + else: + is_up_zs = zg > last_zs.zg + is_down_zs = zd < last_zs.zd + + if is_up_zs: + zs_dir = Chan_ZS_DIR.UP + valid = (bi1.dir == Chan_BI_DIR.DOWN and bi2.dir == Chan_BI_DIR.UP and bi3.dir == Chan_BI_DIR.DOWN) + elif is_down_zs: + zs_dir = Chan_ZS_DIR.DOWN + valid = (bi1.dir == Chan_BI_DIR.UP and bi2.dir == Chan_BI_DIR.DOWN and bi3.dir == Chan_BI_DIR.UP) + + if not valid: + start_idx += 1 + continue + gg = max(bi1.high, bi2.high, bi3.high) + dd = min(bi1.low, bi2.low, bi3.low) + zs = ChanBIZS(bi1, len(bi_zs_list), zs_dir) + zs.set_zg(zg) + zs.set_zd(zd) + zs.set_gg(gg) + zs.set_dd(dd) + zs.is_sure = False + zs.bi_list = [bi1, bi2, bi3] + + added_after_leave = [] + leave_index = start_idx + 4 + while leave_index < len(bi_list): + b = bi_list[leave_index] + if not b.is_sure: + break + if b.high >= zs.zd and b.low <= zs.zg: + added_after_leave.append(b.pre) + added_after_leave.append(b) + else: + break + leave_index += 2 + + if added_after_leave: + bis_for_zs = list(zs.bi_list) + list(added_after_leave) + bi_highs = [bi.high for bi in bis_for_zs] + bi_lows = [bi.low for bi in bis_for_zs] + zs.set_gg(max(bi_highs)) + zs.set_dd(min(bi_lows)) + zs.bi_list = bis_for_zs + bi = bis_for_zs[-1] + if bi.end_klc: + zs.set_end_bi(bi, bi.sure_time) + + start_idx = start_idx + len(added_after_leave) + else: + zs.set_end_bi(bi3, bi3.sure_time) + + if last_zs: + last_zs.set_next(zs) + zs.set_pre(last_zs) + + bi_zs_list.append(zs) + last_zs = zs + + start_idx += 4 + + if last_zs: + last_zs.is_sure = bi_list[-1].is_sure + + if last_zs and not last_zs.is_sure: + if last_zs.bi_list and len(last_zs.bi_list) > 0: + last_bi_of_zs = last_zs.bi_list[-1] + last_bi_idx = -1 + for i, bi in enumerate(bi_list): + if bi == last_bi_of_zs: + last_bi_idx = i + break + + has_leave = False + if last_bi_idx >= 0 and last_bi_idx + 1 < len(bi_list): + for i in range(last_bi_idx + 1, len(bi_list)): + bi = bi_list[i] + if bi.is_sure: + leave = (bi.low > last_zs.zg and bi.high > last_zs.zg) or \ + (bi.high < last_zs.zd and bi.low < last_zs.zd) + if leave: + has_leave = True + break + + if has_leave: + if last_bi_of_zs.end_klc: + last_zs.set_end_bi(last_bi_of_zs, last_bi_of_zs.sure_time) return bi_zs_list def find_all_bsp(self, bi_list, bi_zs_list): """ @@ -1566,9 +1714,9 @@ class TF_DF(): bsp_list.append(bsp) return bsp_list - def calculate_zs(self, bi_list, seg_list): - return self.get_zs_list(bi_list, seg_list) - def get_zs_list(self, bi_list, seg_list): + def calculate_zs(self, seg_list): + return self.get_zs_list(seg_list) + def get_zs_list(self, seg_list): """ 根据缠论线段中枢定义计算中枢 从第4根线段开始(索引3),每3根线段为一组检查 diff --git a/web/app.py b/web/app.py index b459607..70ac6f7 100644 --- a/web/app.py +++ b/web/app.py @@ -33,7 +33,7 @@ class TRADE_POINT_TYPE: SELL3 = -3 # 三类卖点 app = Flask(__name__) - +macd_factor = 2 # 初始化交易所 exchange = ccxt.binance({ 'enableRateLimit': True, @@ -421,8 +421,8 @@ def get_a_stock_kl_data(symbol, timeframe, limit=100000, start_time=None, end_ti return None def add_indicators(df): - fast = 12*1 - slow = 26*1 + fast = 12*macd_factor + slow = 26*macd_factor period = 9*1 macd = ta.MACD(df, fastperiod=fast, slowperiod=slow, signalperiod=period) @@ -509,8 +509,8 @@ def add_indicators(df): def calculate_macd(df): """计算MACD指标""" - exp1 = df['close'].ewm(span=26, adjust=False).mean() - exp2 = df['close'].ewm(span=52, adjust=False).mean() + exp1 = df['close'].ewm(span=12*macd_factor, adjust=False).mean() + exp2 = df['close'].ewm(span=26*macd_factor, adjust=False).mean() macd = exp1 - exp2 signal = macd.ewm(span=9, adjust=False).mean() histogram = macd - signal @@ -534,13 +534,11 @@ def analyze_chan(df, symbol=None, timeframe=None): #for index in range(0, 10): #print(bi_list[index].start_time, bi_list[index].start_klc.end_time, bi_list[index].dir) seg_list = chan.get_seg_list(bi_list) - zs_list = chan.calculate_zs(bi_list, seg_list) + zs_list = chan.calculate_zs(seg_list) # 计算笔中枢(BI中枢)并拍平成列表 - try: - bi_zs_nested = chan.cal_bi_zs(seg_list) - bi_zs_list = [zs for group in bi_zs_nested for zs in (group or [])] if bi_zs_nested else [] - except Exception: - bi_zs_list = [] + + #bi_zs_list = chan.cal_bi_zs_list(bi_list) + bi_zs_list = chan.cal_bi_zs(seg_list) bsp_list = [] if len(bi_zs_list) > 0: bsp_list = chan.find_all_bsp(bi_list, bi_zs_list)