From e84108cb80d7819f0407319aaf3fe0995eb5d2a7 Mon Sep 17 00:00:00 2001 From: Porter Date: Sat, 20 Sep 2025 10:00:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=B0=E7=9A=84=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=BB=93=E6=9E=84=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChanLun.py | 13 +- TF_DF.py | 890 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 893 insertions(+), 10 deletions(-) create mode 100644 TF_DF.py diff --git a/ChanLun.py b/ChanLun.py index 756ceb5..aa432ce 100644 --- a/ChanLun.py +++ b/ChanLun.py @@ -32,18 +32,11 @@ class ChanLun(): time8h = 480 time12h = 720 time1d = 1440 - def create_all_data(self, dataframe, ticker_indicator): - all_data = dict() - all_data['1m'] = dataframe + timeframes = [time1, time3, time5, time15] + def init_data(self, dataframe, ticker_indicator): for timeframe in self.timeframes: - df = resample_to_interval(dataframe, ticker_indicator*self.times[timeframe]) - all_data[timeframe] = df - return all_data + klu_list, klc_list, bi_list = self.get_list_by_time(dataframe, ticker_indicator, timeframe) def calculate_bsp(self, dataframe, ticker_indicator): - klu1, klc1, bi1 = self.get_list_by_time(dataframe, self.time1) - klu3, klc3, bi3 = self.get_list_by_time(dataframe, self.time3) - klu5, klc5, bi5 = self.get_list_by_time(dataframe, self.time5) - klu15, klc15, bi15 = self.get_list_by_time(dataframe, self.time15) return dataframe def get_list_by_time(self, dataframe, ticker_indicator, time): diff --git a/TF_DF.py b/TF_DF.py new file mode 100644 index 0000000..28e849c --- /dev/null +++ b/TF_DF.py @@ -0,0 +1,890 @@ +from datetime import timedelta +from pandas import DataFrame +from ChanEnum import Chan_FX_TYPE, Chan_KLINE_DIR, Chan_BI_DIR, Chan_SEG_DIR, Chan_ZS_DIR, Chan_BSP_DIR, Chan_BSP_TYPE, Chan_KLC_FX +from ChanKLU import ChanKLU +from ChanKLC import ChanKLC +from ChanBI import ChanBI +from ChanSBI import ChanSBI +from ChanSEG import ChanSEG +from ChanZS import ChanZS +from ChanBSP import ChanBSP +import talib.abstract as ta +import pandas as pd +import matplotlib.pyplot as plt +from matplotlib.dates import DateFormatter, date2num +import matplotlib.patches as patches +from technical.util import resample_to_interval +from decimal import Decimal +import xgboost as xgb +import numpy as np +from ChanMACD import ChanMACD + +class TF_DF(): + def __init__(self, timeframe, df, ticker_indicator): + self.timeframe = timeframe + self.dataframe = resample_to_interval(df, ticker_indicator*timeframe) + self.ticker_indicator = ticker_indicator + self.klu_list = [] + self.klc_list = [] + self.bi_list = [] + self.zs_list = [] + self.bsp_list = [] + self.seg_list = [] + self.init_TF_DF() + def init_TF_DF(self): + self.klu_list = self.cal_kl_data(self.dataframe) + self.klc_list = self.cal_klc_list(self.klu_list) + self.bi_list = self.cal_bi_list(self.klc_list) + self.seg_list = self.cal_seg_list(self.bi_list) + self.zs_list = self.cal_zs_list(self.bi_list, self.seg_list) + return True + def check_fx(self, klc): + if klc.pre and klc.next: + if klc.high > klc.pre.high and klc.high > klc.next.high: + if klc.pre.pre and klc.high > klc.pre.pre.high and klc.next.next and klc.high > klc.next.next.high: + if klc.pre.pre.pre and klc.high > klc.pre.pre.pre.high and klc.next.next.next and klc.high > klc.next.next.next.high: + if klc.macd > 0 and klc.macd > klc.signal and klc.signal > klc.macdhist: + klc.set_fx(Chan_FX_TYPE.TOP) + #print(klc.start_time, klc.end_time,klc.next.start_time, klc.next.end_time,klc.fx, "TOP") + return Chan_FX_TYPE.TOP + elif klc.low < klc.pre.low and klc.low < klc.next.low: + if klc.pre.pre and klc.low < klc.pre.pre.low and klc.next.next and klc.low < klc.next.next.low: + if klc.pre.pre.pre and klc.low < klc.pre.pre.pre.low and klc.next.next.next and klc.low < klc.next.next.next.low: + if klc.macd < 0 and klc.macd < klc.signal and klc.signal < klc.macdhist: + klc.set_fx(Chan_FX_TYPE.BOTTOM) + #print(klc.start_time, klc.end_time,klc.next.start_time, klc.next.end_time,klc.fx, "BOTTOM") + return Chan_FX_TYPE.BOTTOM + return Chan_FX_TYPE.UNKNOWN + + def cal_kl_data(self, dataframe:DataFrame): + fields = "time,open,high,low,close,volume" + klu_list = [] + last_klu = None + for i in range(0, len(dataframe)): + item = dataframe.iloc[i] + date = item['date'] + o = item['open'] + h = item['high'] + l = item['low'] + c = item['close'] + v = item['volume'] + #time_obj = date.fromtimestamp(date) + #date = date + timedelta(hours=8) + time_str = date.strftime('%Y-%m-%d %H:%M:%S') + item_data = [ + time_str, + o, + h, + l, + c, + v + ] + #klu = KLU(self.create_item_dict(item_data, GetColumnNameFromFieldList(fields))) + klu = ChanKLU(time_str, o, h, l, c, v) + #print(klu.time, klu.open, klu.high, klu.low, klu.close, klu.volume) + klu.set_idx(i) + klu_list.append(klu) + if last_klu: + last_klu.set_next(klu) + klu.set_pre(last_klu) + last_klu = klu + if 'macd' in item: + klu.set_indicators(item) + return klu_list + + def cal_klc_list(self, klu_list): + klc_list = [] + last_klu = None + macd = ChanMACD(klu_list) + klu_list = macd.cal_macd_state() + for klu in klu_list: + if len(klc_list) > 0: + last_klc = klc_list[-1] + included = last_klc.check_klu_included(klu) + if not included: + ddir = Chan_KLINE_DIR.DOWN + if last_klc.high < klu.high: + ddir = Chan_KLINE_DIR.UP + klc = ChanKLC(klu, index=len(klc_list), ddir=ddir) + klc_list.append(klc) + last_klc.set_next(klc) + klc.set_pre(last_klc) + last_klc.set_end_klu(last_klu) + klc.set_pre_fx() + else: + last_klc.add_klu(klu) + else: + ddir = Chan_KLINE_DIR.UP + if klu.open > klu.close: + ddir = Chan_KLINE_DIR.DOWN + klc = ChanKLC(klu, 0, ddir) + klc_list.append(klc) + last_klu = klu + return klc_list + + def cal_seg_list(self, bi_list): + seg_list = [] + up_bi_list = [] + down_bi_list = [] + last_up_bi = None + last_down_bi = None + last_up_sbi = None + last_down_sbi = None + last_seg = None + up_sbi_list = [] + down_sbi_list = [] + look_for_bottom = False + look_for_top = False + for bi in bi_list: + #print(len(up_sbi_list), len(down_sbi_list)) + if len(seg_list) > 0: + # Last seg is up + if last_seg.dir == Chan_SEG_DIR.UP: + if bi.dir == Chan_BI_DIR.DOWN: + if len(down_sbi_list) > 1: + # Check down sbi inclusion + included = last_down_sbi.check_bi_included(bi) + if not included: + down_sbi = ChanSBI(bi, len(down_sbi_list), bi.dir) + last_down_sbi.set_next(down_sbi) + last_down_sbi.set_end_bi(last_down_bi) + down_sbi.set_pre(last_down_sbi) + down_sbi_list.append(down_sbi) + fx = last_down_sbi.check_fx() + # Found top + if fx == Chan_FX_TYPE.TOP: + if look_for_top: + seg_list[-2].set_sure(bi) + look_for_top = False + #print(bi.start_time, look_for_top, "UP 1") + # Has gap and search for bottom fx + if last_down_sbi.has_fx_gap: + look_for_bottom = True + last_seg.pre_set_end_bi(bi_list[last_down_sbi.start_bi.index - 1]) + seg = ChanSEG(last_down_sbi.start_bi, len(seg_list), Chan_SEG_DIR.DOWN) + seg_list.append(seg) + last_seg.set_next(seg) + seg.set_pre(last_seg) + last_seg = seg + up_sbi_list = [] + last_up_sbi = ChanSBI(last_up_bi, len(up_sbi_list), last_up_bi.dir) + up_sbi_list.append(last_up_sbi) + #up_sbi_list.append(last_up_sbi) + #print(last_up_bi.start_time, last_up_sbi.start_bi.start_time, "Reset up sbi list 1") + #print(bi.start_time, look_for_top, "UP 2") + # No gap end SEG + else: + if look_for_bottom: + look_for_bottom = False + last_seg.set_start_bi(last_down_sbi.start_bi) + seg_list[-2].set_end_bi(bi_list[last_down_sbi.start_bi.index - 1], bi) + up_sbi_list = [] + last_up_sbi = ChanSBI(last_up_bi, len(up_sbi_list), last_up_bi.dir) + up_sbi_list.append(last_up_sbi) + last_seg.add_bi(bi) + #up_sbi_list.append(last_up_sbi) + #print(last_up_bi.start_time, last_up_sbi.start_bi.start_time, "Reset up sbi list 2") + #print(bi.start_time, look_for_top, "UP 3") + else: + last_seg.set_end_bi(bi_list[last_down_sbi.start_bi.index - 1], bi) + seg = ChanSEG(last_down_sbi.start_bi, len(seg_list), Chan_SEG_DIR.DOWN) + seg_list.append(seg) + last_seg.set_next(seg) + seg.set_pre(last_seg) + last_seg = seg + #print(last_down_sbi.end_bi.start_time, "Normal UP SEG", last_up_sbi.start_bi.start_time, bi.start_time) + #l_up_sbi = up_sbi_list[-1] + up_sbi_list = [] + last_up_sbi = ChanSBI(last_up_bi, len(up_sbi_list), last_up_bi.dir) + up_sbi_list.append(last_up_sbi) + #up_sbi_list.append(last_up_sbi) + #print(last_up_bi.start_time, last_up_sbi.start_bi.start_time, "Reset up sbi list 3") + last_down_sbi = down_sbi + last_seg.add_bi(bi) + else: + if len(down_sbi_list) == 1: + included = last_down_sbi.check_bi_included(bi) + if not included: + down_sbi = ChanSBI(bi, len(down_sbi_list), bi.dir) + last_down_sbi.set_next(down_sbi) + last_down_sbi.set_end_bi(last_down_bi) + down_sbi.set_pre(last_down_sbi) + down_sbi_list.append(down_sbi) + last_down_sbi = down_sbi + #print(bi.start_time, look_for_top, "UP 4") + last_seg.add_bi(bi) + + else: + last_down_sbi = ChanSBI(bi, len(down_sbi_list), bi.dir) + down_sbi_list.append(last_down_sbi) + last_seg.add_bi(bi) + #print(bi.start_time, look_for_top, "UP 5") + else: + if last_up_sbi: + included = last_up_sbi.check_bi_included(bi) + if not included: + up_sbi = ChanSBI(bi, len(up_sbi_list), bi.dir) + last_up_sbi.set_next(up_sbi) + last_up_sbi.set_end_bi(last_up_bi) + up_sbi.set_pre(last_up_sbi) + up_sbi_list.append(up_sbi) + last_up_sbi = up_sbi + #print(bi.start_time, look_for_top, "UP 6") + last_seg.add_bi(bi) + + # Last seg is down + else: + if bi.dir == Chan_BI_DIR.UP: + if len(up_sbi_list) > 1: + # Check down sbi inclusion + included = last_up_sbi.check_bi_included(bi) + if not included: + up_sbi = ChanSBI(bi, len(up_sbi_list), bi.dir) + last_up_sbi.set_next(up_sbi) + last_up_sbi.set_end_bi(last_up_bi) + up_sbi.set_pre(last_up_sbi) + up_sbi_list.append(up_sbi) + fx = last_up_sbi.check_fx() + # Found bottom + if fx == Chan_FX_TYPE.BOTTOM: + if look_for_bottom: + seg_list[-2].set_sure(bi) + look_for_bottom = False + #print(bi.start_time, look_for_top, "DOWN 1") + # Has gap and search for bottom fx + if last_up_sbi.has_fx_gap: + look_for_top = True + last_seg.pre_set_end_bi(bi_list[last_up_sbi.start_bi.index - 1]) + seg = ChanSEG(last_up_sbi.start_bi, len(seg_list), Chan_SEG_DIR.UP) + seg_list.append(seg) + last_seg.set_next(seg) + seg.set_pre(last_seg) + last_seg = seg + down_sbi_list = [] + last_down_sbi = ChanSBI(last_down_bi, len(down_sbi_list), last_down_bi.dir) + down_sbi_list.append(last_down_sbi) + #down_sbi_list.append(last_down_sbi) + #print(last_down_bi.start_time, last_down_sbi.start_bi.start_time, "Reset down sbi list 1") + #print(bi.start_time, look_for_top, "DOWN 2") + # No gap end SEG + else: + if look_for_top: + look_for_top = False + last_seg.set_start_bi(last_up_sbi.start_bi) + seg_list[-2].set_end_bi(bi_list[last_up_sbi.start_bi.index - 1], bi) + down_sbi_list = [] + last_down_sbi = ChanSBI(last_down_bi, len(down_sbi_list), last_down_bi.dir) + down_sbi_list.append(last_down_sbi) + last_seg.add_bi(bi) + #down_sbi_list.append(last_down_sbi) + #print(last_down_bi.start_time, last_down_sbi.start_bi.start_time, "Reset down sbi list 2") + #print(bi.start_time, look_for_top, "DOWN 3") + else: + last_seg.set_end_bi(bi_list[last_up_sbi.start_bi.index - 1], bi) + seg = ChanSEG(last_up_sbi.start_bi, len(seg_list), Chan_SEG_DIR.UP) + #print(last_up_sbi.start_bi.start_time) + last_seg.set_next(seg) + seg.set_pre(last_seg) + seg_list.append(seg) + last_seg = seg + #print(last_up_sbi.end_bi.start_time, "Normal DOWN SEG", last_down_sbi.start_bi.start_time, bi.start_time) + down_sbi_list = [] + last_down_sbi = ChanSBI(last_down_bi, len(down_sbi_list), last_down_bi.dir) + down_sbi_list.append(last_down_sbi) + #down_sbi_list.append(last_down_sbi) + #print(last_down_bi.start_time, last_down_sbi.start_bi.start_time, "Reset down sbi list 3") + last_up_sbi = up_sbi + last_seg.add_bi(bi) + else: + if len(up_sbi_list) == 1: + #last_up_sbi = up_sbi_list[-1] + included = last_up_sbi.check_bi_included(bi) + if not included: + up_sbi = ChanSBI(bi, len(up_sbi_list), bi.dir) + last_up_sbi.set_next(up_sbi) + last_up_sbi.set_end_bi(last_up_bi) + up_sbi.set_pre(last_up_sbi) + up_sbi_list.append(up_sbi) + last_up_sbi = up_sbi + last_seg.add_bi(bi) + #print(bi.start_time, look_for_top, "DOWN 4") + else: + last_up_sbi = ChanSBI(bi, len(up_sbi_list), bi.dir) + up_sbi_list.append(last_up_sbi) + last_seg.add_bi(bi) + #print(bi.start_time, look_for_top, "DOWN 5") + else: + if last_down_sbi: + included = last_down_sbi.check_bi_included(bi) + if not included: + down_sbi = ChanSBI(bi, len(down_sbi_list), bi.dir) + last_down_sbi.set_next(down_sbi) + last_down_sbi.set_end_bi(last_down_bi) + down_sbi.set_pre(last_down_sbi) + down_sbi_list.append(down_sbi) + last_down_sbi = down_sbi + last_seg.add_bi(bi) + #print(bi.start_time, look_for_top, look_for_bottom, "DOWN 6") + # len(seg_list) = 0 + else: + if bi.check_overlap(): + if bi.dir == Chan_BI_DIR.UP: + seg = ChanSEG(bi, len(seg_list), Chan_SEG_DIR.UP) + last_up_bi = bi + last_up_sbi = ChanSBI(bi, len(up_sbi_list), bi.dir) + seg_list.append(seg) + last_seg = seg + #print(bi.start_time, 'Create first UP SEG') + else: + seg = ChanSEG(bi, len(seg_list), Chan_SEG_DIR.DOWN) + last_down_bi = bi + last_down_sbi = ChanSBI(bi, len(down_sbi_list), bi.dir) + seg_list.append(seg) + last_seg = seg + #print(bi.start_time, 'Create first DOWN SEG') + if bi.dir == Chan_BI_DIR.UP: + last_up_bi = bi + up_bi_list.append(bi) + else: + last_down_bi = bi + down_bi_list.append(bi) + """ + if len(seg_list) > 1: + seg = seg_list[-1] + last_seg = seg_list[-2] + last_seg_bi = last_seg.bi_list[-3] + bi_index = seg.start_bi.index + for i in range(bi_index, len(bi_list) - 1): + # last seg is down + if seg.dir == Chan_SEG_DIR.UP: + if bi_list[i].dir == Chan_BI_DIR.UP: + last_seg_peak = last_seg_bi.high + if bi_list[i].high > last_seg_peak: + # The confirmed + print("Last UP seg is broken, create a new seg. 1") + seg.pre_set_end_bi(bi_list[i]) + seg = ChanSEG(bi_list[i+1], len(seg_list), Chan_SEG_DIR.DOWN) + seg_list.append(seg) + last_seg = seg_list[-2] + if len(last_seg.bi_list) > 3: + last_seg_bi = last_seg.bi_list[-3] + + else: + if bi_list[i].dir == Chan_BI_DIR.DOWN: + last_seg_peak = last_seg_bi.low + if bi_list[i].low < last_seg_peak: + print("Last DOWN seg is broken, create a new seg. 1") + seg.pre_set_end_bi(bi_list[i]) + seg = ChanSEG(bi_list[i+1], len(seg_list), Chan_SEG_DIR.UP) + seg_list.append(seg) + last_seg = seg_list[-2] + if len(last_seg.bi_list) > 3: + last_seg_bi = last_seg.bi_list[-3] + else: + if len(seg_list) == 1: + last_seg = seg_list[-1] + bi_index = last_seg.bi_list[0].index + for i in range(bi_index, len(bi_list) - 1): + if i > bi_index + 2: + last_seg_peak = bi_list[i-2].high + # last seg is down + if last_seg.dir == Chan_SEG_DIR.DOWN: + if bi_list[i].dir == Chan_BI_DIR.UP: + if bi_list[i].high > last_seg_peak: + print("Last seg is broken, create a new seg. 2") + last_seg.pre_set_end_bi(bi_list[i-1]) + seg = ChanSEG(bi_list[i], len(seg_list), Chan_SEG_DIR.UP) + seg_list.append(seg) + last_seg = seg + last_seg_bi = bi_list[i] + break + """ + return seg_list + + def cal_bi_list(self, klc_list): + bi_list = [] + last_top = None + last_bottom = None + for klc in klc_list: + fx = self.check_fx(klc) + + # Do nothing + if fx == Chan_FX_TYPE.UNKNOWN: + continue + if len(bi_list) > 0 and klc.end_klu: + last_bi = bi_list[-1] + #print(klc.start_time, last_bi.start_time, last_bi.end_time, last_bi.dir, last_bi.high, last_bi.low, last_bottom.end_time, "last bi") + if last_top and last_bi.dir == Chan_BI_DIR.DOWN: + if last_bottom and klc.high > last_bi.high: + last_bi.set_end_klc(last_bottom, klc) + bi = ChanBI(last_bottom, len(bi_list), Chan_BI_DIR.UP) + #klc.set_klc_fx_type(Chan_KLC_FX.BOTTOM7) + #klc.bb_out = True + last_bi.set_next(bi) + bi.set_pre(last_bi) + for klc_index in range(last_bi.end_klc.index, len(klc_list)): + bi.add_klc(klc_list[klc_index]) + bi_list.append(bi) + last_top = klc + klc.set_bi(bi) + #print(klc.start_time, bi.start_time, bi.end_time, bi.dir, bi.high, bi.low, bi.is_sure) + else: + if last_bottom and last_bi.dir == Chan_BI_DIR.UP: + if last_top and klc.low < last_bi.low: + last_bi.set_end_klc(last_top, klc) + bi = ChanBI(last_top, len(bi_list), Chan_BI_DIR.DOWN) + #klc.set_klc_fx_type(Chan_KLC_FX.TOP6) + #klc.bb_out = True + last_bi.set_next(bi) + bi.set_pre(last_bi) + for klc_index in range(last_bi.end_klc.index, len(klc_list)): + bi.add_klc(klc_list[klc_index]) + bi_list.append(bi) + last_bottom = klc + klc.set_bi(bi) + #print(klc.start_time, bi.start_time, bi.end_time, bi.dir, bi.high, bi.low, bi.is_sure) + else: + if fx == Chan_FX_TYPE.TOP: + if last_top: + if last_bottom: + #print(klc.start_time, last_bottom.start_time, last_top.start_time) + if last_bottom.index < last_top.index: + # Second top lower to be second sell point + if last_top.high > klc.high: + #klc.set_fx(Chan_FX_TYPE.TT) + #klc.set_state("20") + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + #klc.set_klc_fx_type(Chan_KLC_FX.TOP3) + klc.set_last_top_klu(last_top) + #print(klc.start_time, klc.fx, "二类卖点Sell 1") + else: + # A new top found + #last_top.set_fx(Chan_FX_TYPE.UNKNOWN) + last_top = klc + #print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Change 1") + klc.set_klc_fx_type(Chan_KLC_FX.TOP1) + #print(klc.end_time, klc.fx, "一类卖点Sell 1") + #klc.set_fx(fx) + #klc.set_state("10") + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + else: + # 不满足结合律的分型 + if last_bottom.index + 4 > klc.index: + if last_top.high > klc.high: + #print(klc.start_time, klc.fx, "二类卖点Sell 1") + #klc.set_fx(Chan_FX_TYPE.PTOP) + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + # New TOP Found replace last top + else: + if last_top.index + 4 < klc.index and len(bi_list) > 1: + pre_last_bi = bi_list[-2] + last_bi = bi_list[-1] + if pre_last_bi.is_sure and not last_bi.is_sure and pre_last_bi.dir == Chan_BI_DIR.UP and False: + pre_last_bi.update_bi(klc) + bi_list.remove(last_bi) + pre_last_bi.set_next(None) + #last_top.set_fx(Chan_FX_TYPE.PTOP) + last_top = klc + last_bottom = pre_last_bi.start_klc + #print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Bottom Change 1") + klc.set_klc_fx_type(Chan_KLC_FX.TOP2) + #print(klc.start_time, last_bi.start_klc.start_time, "New TOP Found reset last bi") + #klc.set_state("10") + #print(klc.start_time, klc.fx, "笔卖点Sell 1") + ###klc.set_klc_fx_type(Chan_KLC_FX.TOP2) # when bi is down but the fx is top + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + else: + klc.set_fx(Chan_FX_TYPE.PTOP) + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + #print(klc.start_time, klc.fx, "无效分型") + # 满足结合律 + else: + # New Temp TOP and last bottom confirmed ***** confirm last down bi(last bottom and last top) + last_bi = bi_list[-1] + if not last_bi.is_sure: + last_bi.set_end_klc(last_bottom, klc) + bi = ChanBI(last_bottom, len(bi_list), Chan_BI_DIR.UP) + #klc.set_klc_fx_type(Chan_KLC_FX.BOTTOM7) + #klc.bb_out = True + last_bi.set_next(bi) + bi.set_pre(last_bi) + bi.add_klc(klc) + bi_list.append(bi) + last_top = klc + #print(klc.end_time, klc.fx, bi_list[-1].dir, "Last Top Change 2") + klc.set_klc_fx_type(Chan_KLC_FX.TOP2) + #klc.set_state('30') + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + #print(klc.start_time, last_bottom.start_time, "Normal TOP Found, Confirm down bi 4") + #print(klc.start_time, klc.fx, "笔卖点Sell 2") + # last bottom = None + else: + if last_top.high < klc.high: + last_bi = bi_list[-1] + last_bi.set_start_klc(klc, Chan_BI_DIR.DOWN) + #last_top.set_fx(Chan_FX_TYPE.UNKNOWN) + last_top = klc + #print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Change 3") + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + #print(klc.start_time, klc.fx, "笔卖点Sell 3") + else: + klc.set_fx(Chan_FX_TYPE.TT) + #klc.set_state('20') + #print(klc.start_time, klc.fx, "二类卖点Sell 2") + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + else: + if last_bottom: + # 不满足结合律的分型 + if last_bottom.index + 4 > klc.index: + #klc.set_fx(Chan_FX_TYPE.PTOP) + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + #print(klc.start_time, klc.fx, "中枢卖点Sell 1") + else: + # First temp top and last bottom confirmed + last_top = klc + #print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Change 4") + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + #print(klc.start_time, klc.fx, "一类卖点Sell 1") + # Last top = None, last bottom = None, create first down bi + else: + # First temp top + last_top = klc + bi = ChanBI(klc, len(bi_list), Chan_BI_DIR.DOWN) + #klc.set_klc_fx_type(Chan_KLC_FX.TOP6) + #klc.bb_out = True + bi_list.append(bi) + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + #print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Change 5") + #print(klc.start_time, 'Create first top') + #print(klc.start_time, klc.fx, "笔卖点Sell 1") + #klc.fx = Bottom ======================== + else: + if last_bottom: + if last_top: + # Bottom after top and find a new bottom + if last_top.index < last_bottom.index: + # Second bottom uppper to be second buy point and confirm last bi + if last_bottom.low < klc.low: + #klc.set_fx(Chan_FX_TYPE.BB) + #klc.set_state("-20") + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + #klc.set_klc_fx_type(Chan_KLC_FX.BOTTOM3) + klc.set_last_bottom_klc(last_bottom) + #print(last_bottom.start_time, last_bottom.end_time, "--------------------------------1") + #print(klc.start_time, klc.fx, "二类买点Buy 1") + else: + # A new bottom found + #last_bottom.set_fx(Chan_FX_TYPE.UNKNOWN) + last_bottom = klc + #print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 1") + klc.set_klc_fx_type(Chan_KLC_FX.BOTTOM1) + #print(klc.start_time, klc.fx, "一类买点Buy 1") + #klc.set_state("-10") + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + else: + # 不满足结合律的分型 + if last_top.index + 4 > klc.index: + if last_bottom.low < klc.low: + #klc.set_fx(Chan_FX_TYPE.PBOTTOM) + #klc.set_fx(Chan_FX_TYPE.BB) + #klc.set_state("-100") + #print(klc.start_time, klc.fx, "中枢买点Buy 1") + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + # Found new bottom + else: + if last_bottom.index + 4 < klc.index and len(bi_list) > 1: + pre_last_bi = bi_list[-2] + last_bi = bi_list[-1] + if pre_last_bi.is_sure and not last_bi.is_sure and pre_last_bi.dir == Chan_BI_DIR.DOWN and False: + pre_last_bi.update_bi(klc) + bi_list.remove(last_bi) + pre_last_bi.set_next(None) + #last_bottom.set_fx(Chan_FX_TYPE.PBOTTOM) + last_bottom = klc + last_top = pre_last_bi.start_klc + #print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Bottom Change 2") + klc.set_klc_fx_type(Chan_KLC_FX.BOTTOM2) + #print(klc.start_time, last_bi.start_klc.start_time, "New BOTTOM Found reset last bi") + #klc.set_state("-10") + #print(klc.start_time, klc.fx, "笔买点Buy 1") + ###klc.set_klc_fx_type(Chan_KLC_FX.BOTTOM2) # when bi is up but the fx is bottom + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + else: + #klc.set_fx(Chan_FX_TYPE.UNKNOWN) + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + #print(klc.start_time, klc.fx, "无效分型") + # 满足结合律的分型 + else: + # New Temp Bottom and last top confirmed ***** confirm last up bi(last bottom and last top) + last_bi = bi_list[-1] + if not last_bi.is_sure: + last_bi.set_end_klc(last_top, klc) + bi = ChanBI(last_top, len(bi_list), Chan_BI_DIR.DOWN) + #klc.set_klc_fx_type(Chan_KLC_FX.TOP6) + #klc.bb_out = True + last_bi.set_next(bi) + bi.set_pre(last_bi) + bi.add_klc(klc) + bi_list.append(bi) + last_bottom = klc + #print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 2") + klc.set_klc_fx_type(Chan_KLC_FX.BOTTOM2) + #klc.set_state('-30') + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + #print(klc.start_time, klc.fx, "笔买点Buy 2") + #print(klc.start_time, last_top.start_time, "Normal Bottom Found, Confirm up bi 6") + # last_top = None + else: + if last_bottom.low > klc.low: + last_bi = bi_list[-1] + last_bi.set_start_klc(klc, Chan_BI_DIR.UP) + #last_bottom.set_fx(Chan_FX_TYPE.UNKNOWN) + last_bottom = klc + #print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 3") + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + #print(klc.start_time, klc.fx, "笔买点Buy 3") + else: + klc.set_fx(Chan_FX_TYPE.BB) + #klc.set_state('-20') + #print(klc.start_time, klc.fx, "二类买点Buy 2") + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + # last_bottom = None + else: + if last_top: + # 不满足结合律的分型 + if last_top.index + 4 > klc.index: + #klc.set_fx(Chan_FX_TYPE.PBOTTOM) + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + #print(klc.start_time, klc.fx, "中枢买点Buy 1") + else: + # First temp bottom and last top confirmed + last_bottom = klc + #print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 4") + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + #print(klc.start_time, klc.fx, "一类买点Buy 1") + # Last top = None, last bottom = None, create first up bi + else: + # First temp bottom and no top yet + last_bottom = klc + bi = ChanBI(klc, len(bi_list), Chan_BI_DIR.UP) + #klc.set_klc_fx_type(Chan_KLC_FX.BOTTOM7) + #klc.bb_out = True + bi_list.append(bi) + bi_list[-1].add_klc(klc) + klc.set_bi(bi_list[-1]) + #print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 5") + #print(klc.start_time, klc.fx, "笔买点Buy 4") + #if klc.fx != Chan_FX_TYPE.UNKNOWN: + #print(klc.start_time, klc.fx, klc.index) + """ + for klc in klc_list: + if klc.fx == Chan_FX_TYPE.TOP: + klc.state = "10" + #print(klc.time, klc.state) + if klc.fx == Chan_FX_TYPE.BOTTOM: + klc.state = "-10" + #print(klc.time, klc.state) + """ + #for index in range(0, 10): + #print(bi_list[index].start_time, bi_list[index].start_klc.start_time, bi_list[index].dir) + return bi_list + + def get_decimal(self, value): + return Decimal("{:.2f}".format(value)) + + def cal_zs_list(self, bi_list, seg_list): + zs_list = [] + bsp_list = [] + if len(seg_list) > 3: + last_zs = None + first_bi_out = None + in_again = False + bi_out_count = 0 + zs_count = 0 + for seg in seg_list: + # No zs or Last ZS is completed + if len(zs_list) == 0 or (last_zs and last_zs.is_sure): + # Has three completed segments + if seg.next and seg.next.next: + if seg.next.next.is_sure: + zg = min(seg.high, seg.next.high, seg.next.next.high) + zd = max(seg.low, seg.next.low, seg.next.next.low) + gg = max(seg.high, seg.next.high, seg.next.next.high) + dd = min(seg.low, seg.next.low, seg.next.next.low) + ddir = Chan_ZS_DIR.UP + ddir = None + if last_zs: + if zg < last_zs.zd: + ddir = Chan_ZS_DIR.DOWN + else: + if zd > last_zs.zg: + ddir = Chan_ZS_DIR.UP + else: + ddir = None + else: + if seg.dir == Chan_SEG_DIR.UP: + ddir = Chan_ZS_DIR.DOWN + else: + ddir = Chan_ZS_DIR.UP + if (seg.dir == Chan_SEG_DIR.DOWN and ddir == Chan_ZS_DIR.DOWN) or (seg.dir == Chan_SEG_DIR.UP and ddir == Chan_ZS_DIR.UP): + ddir = None + if ddir and zg > zd: + # New ZS + zs = ChanZS(seg, len(zs_list), ddir) + zs.set_zg(zg) + zs.set_zd(zd) + zs.set_gg(gg) + zs.set_dd(dd) + if last_zs: + last_zs.set_next(zs) + zs.set_pre(last_zs) + zs_list.append(zs) + if last_zs and last_zs.dir == zs.dir: + zs_count += 1 + else: + zs_count = 1 + last_zs = zs + # Last ZS is not completed + else: + # Last ZS is not completed + if last_zs and not last_zs.is_sure: + if first_bi_out: + # SEG is not in ZS + if seg.is_sure: + if ((seg.low > last_zs.zg and seg.high > last_zs.zg) or (seg.high < last_zs.zd and seg.low < last_zs.zd)): + last_zs.set_end_klc(last_zs.last_bi_in.end_klc, seg.sure_time, bi_out_count, seg) + bi_out_count = 0 + #print(seg.start_bi.start_klc.start_time) + first_bi_out = None + # Last ZS is completed and look for new ZS + if seg.next and seg.next.next: + if seg.next.next.is_sure: + zg = min(seg.high, seg.next.high, seg.next.next.high) + zd = max(seg.low, seg.next.low, seg.next.next.low) + gg = max(seg.high, seg.next.high, seg.next.next.high) + dd = min(seg.low, seg.next.low, seg.next.next.low) + ddir = None + if last_zs: + if zg < last_zs.zd: + ddir = Chan_ZS_DIR.DOWN + else: + if zd > last_zs.zg: + ddir = Chan_ZS_DIR.UP + else: + ddir = None + else: + if seg.dir == Chan_SEG_DIR.UP: + ddir = Chan_ZS_DIR.DOWN + else: + ddir = Chan_ZS_DIR.UP + if (seg.dir == Chan_SEG_DIR.DOWN and ddir == Chan_ZS_DIR.DOWN) or (seg.dir == Chan_SEG_DIR.UP and ddir == Chan_ZS_DIR.UP): + ddir = None + if ddir and zg > zd: + # New ZS + zs = ChanZS(seg, len(zs_list), ddir) + zs.set_zg(zg) + zs.set_zd(zd) + zs.set_gg(gg) + zs.set_dd(dd) + last_zs.set_next(zs) + zs.set_pre(last_zs) + zs_list.append(zs) + if last_zs and last_zs.dir == zs.dir: + zs_count += 1 + else: + zs_count = 1 + last_zs = zs + # Last SEG is in ZS + else: + # SEG is inside ZS + if seg.end_bi: + for index in range(seg.start_bi.index, seg.end_bi.index+1): + bi = bi_list[index] + if (bi.high >= last_zs.zd and bi.high <= last_zs.zg) or (bi.low >= last_zs.zd and bi.low <= last_zs.zg) or (bi.high >= last_zs.zg and bi.low <= last_zs.zd): + in_again = True + last_zs.set_bi_out(None, None) + last_zs.set_last_bi_in(None) + last_zs.set_end_seg(None) + first_bi_out = None + #print("Bi in again 3", bi.start_klc.start_time) + if in_again and (bi.low > last_zs.zg or bi.high < last_zs.zd): + last_zs.set_bi_out(bi, seg) + last_zs.set_last_bi_in(bi_list[index - 1]) + #last_zs.set_end_seg(seg.next.next) + bi_out_count += 1 + first_bi_out = bi + if (bi.dir == Chan_BI_DIR.UP and seg.dir == Chan_SEG_DIR.DOWN) or (bi.dir == Chan_BI_DIR.DOWN and seg.dir == Chan_SEG_DIR.UP): + bsp = ChanBSP(first_bi_out, len(bsp_list), Chan_BSP_TYPE.T3, Chan_BSP_DIR.BUY if first_bi_out.dir == Chan_BI_DIR.DOWN else Chan_BSP_DIR.SELL, first_bi_out.sure_time, zs_count, zs, seg) + bsp_list.append(bsp) + #print("First bi out 3", first_bi_out.start_klc.start_time) + in_again = False + """" + if first_bi_out: + if seg.dir == Chan_SEG_DIR.UP and bi.dir == Chan_BI_DIR.UP: + #print(bi.start_klc.start_time, bi.high, seg.high) + if bi.high == seg.high: + bsp = ChanBSP(bi, len(bsp_list), Chan_BSP_TYPE.T3E, Chan_BSP_DIR.SELL if bi.dir == Chan_BI_DIR.DOWN else Chan_BSP_DIR.BUY, bi.sure_time, zs_count, zs, seg) + bsp_list.append(bsp) + else: + if seg.dir == Chan_SEG_DIR.DOWN and bi.dir == Chan_BI_DIR.DOWN: + if bi.low == seg.low: + bsp = ChanBSP(bi, len(bsp_list), Chan_BSP_TYPE.T3E, Chan_BSP_DIR.BUY if bi.dir == Chan_BI_DIR.DOWN else Chan_BSP_DIR.SELL, bi.sure_time, zs_count, zs, seg) + bsp_list.append(bsp) + """ + else: + # SEG in ZS and not out and find first bi out + if seg.end_bi: + for index in range(seg.start_bi.index, seg.end_bi.index+1): + bi = bi_list[index] + if (bi.high >= last_zs.zd and bi.high <= last_zs.zg) or (bi.low >= last_zs.zd and bi.low <= last_zs.zg) or (bi.high >= last_zs.zg and bi.low <= last_zs.zd): + in_again = True + last_zs.set_bi_out(None, None) + last_zs.set_last_bi_in(None) + last_zs.set_end_seg(None) + first_bi_out = None + #print("Bi in again 4", bi.start_klc.start_time) + if in_again and (bi.low > last_zs.zg or bi.high < last_zs.zd): + last_zs.set_bi_out(bi, seg) + last_zs.set_last_bi_in(bi_list[index - 1]) + #last_zs.set_end_seg(seg.next.next) + bi_out_count += 1 + first_bi_out = bi + if (bi.dir == Chan_BI_DIR.UP and seg.dir == Chan_SEG_DIR.DOWN) or (bi.dir == Chan_BI_DIR.DOWN and seg.dir == Chan_SEG_DIR.UP): + bsp = ChanBSP(first_bi_out, len(bsp_list), Chan_BSP_TYPE.T3, Chan_BSP_DIR.BUY if first_bi_out.dir == Chan_BI_DIR.DOWN else Chan_BSP_DIR.SELL, first_bi_out.sure_time, zs_count, zs, seg) + bsp_list.append(bsp) + #print("First bi out 4", first_bi_out.start_klc.start_time) + in_again = False + if first_bi_out: + if seg.dir == Chan_SEG_DIR.UP and bi.dir == Chan_BI_DIR.UP: + #print(bi.start_klc.start_time, bi.high, seg.high) + if bi.high == seg.high: + bsp = ChanBSP(bi, len(bsp_list), Chan_BSP_TYPE.T3E, Chan_BSP_DIR.SELL if bi.dir == Chan_BI_DIR.DOWN else Chan_BSP_DIR.BUY, bi.sure_time, zs_count, zs, seg) + bsp_list.append(bsp) + else: + if seg.dir == Chan_SEG_DIR.DOWN and bi.dir == Chan_BI_DIR.DOWN: + if bi.low == seg.low: + bsp = ChanBSP(bi, len(bsp_list), Chan_BSP_TYPE.T3E, Chan_BSP_DIR.BUY if bi.dir == Chan_BI_DIR.DOWN else Chan_BSP_DIR.SELL, bi.sure_time, zs_count, zs, seg) + bsp_list.append(bsp) + #self.print_zs(zs_list) + return zs_list \ No newline at end of file