From d61cbbec2110193292a1bbc9abb319a8f3dec25f Mon Sep 17 00:00:00 2001 From: jackyu66git Date: Sun, 16 Nov 2025 20:58:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=B0=E7=9A=84=E5=88=A4?= =?UTF-8?q?=E6=96=AD=E4=BE=9D=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChanKLC.py | 3 ++- ChanKLU.py | 9 ++++++++- ChanLun.py | 4 ++-- ChanMACD.py | 2 +- ChanMACDUnitTF.py | 4 ++-- TF_DF.py | 40 +++------------------------------------- data_provider/main.py | 10 +++++----- web/app.py | 28 +--------------------------- 8 files changed, 24 insertions(+), 76 deletions(-) diff --git a/ChanKLC.py b/ChanKLC.py index df0c7ef..132c52e 100644 --- a/ChanKLC.py +++ b/ChanKLC.py @@ -77,6 +77,7 @@ class ChanKLC(): self.continue_div = klu.continue_div if klu.macd_state != Chan_MACD_STATE.UNKNOWN: self.state = klu.macd_state + klu.set_klc(self) self.klc_dir = Chan_KLINE_DIR.UP if self.close > self.open else Chan_KLINE_DIR.DOWN self.cal_indicators() def cal_fx(self): @@ -175,7 +176,7 @@ class ChanKLC(): return False else: # high小于,low大于,右包含 - if self.low >= klu.low: + if self.low >= klu.low-10: self.add_klu(klu=klu) # gn>gn-1 if self.dir == Chan_KLINE_DIR.UP: diff --git a/ChanKLU.py b/ChanKLU.py index 78a2fca..62d1f84 100644 --- a/ChanKLU.py +++ b/ChanKLU.py @@ -1,4 +1,4 @@ -from ChanEnum import Chan_FX_TYPE, Chan_KLU_TYPE, Chan_K_DIR, Chan_MACD_STATE, Chan_MACDHIST_STATE, Chan_PRICE_TREND, Chan_KLU_PATTERN +from ChanEnum import Chan_FX_TYPE, Chan_KLU_TYPE, Chan_K_DIR, Chan_MACD_STATE, Chan_MACDHIST_STATE, Chan_PRICE_TREND, Chan_KLU_PATTERN, Chan_KLC_FX class ChanKLU: def __init__(self, time, open, high, low, close, volume): # _time, _close, _open, _high, _low, _extra_info={} @@ -79,6 +79,13 @@ class ChanKLU: self.exception = False def set_trend(self, trend): self.trend = trend + def set_separate_div(self, separate_div): + self.separate_div = separate_div + if self.klc: + if self.klc.klc_fx_type != Chan_KLC_FX.UNKNOWN: + self.separate_div = 99 + else: + self.separate_div = 0 def set_next(self, next): self.next = next #if self.fx_type != Chan_FX_TYPE.UNKNOWN and self.fx_strength > 1: diff --git a/ChanLun.py b/ChanLun.py index ece050a..a402053 100644 --- a/ChanLun.py +++ b/ChanLun.py @@ -115,7 +115,7 @@ class ChanLun(): return self.tf_df.cal_bi_zs(seg_list) def get_decimal(self, value): return Decimal("{:.2f}".format(value)) - def get_klc_list(self, dataframe): - return self.tf_df.get_klc_list(dataframe) + def get_klc_list(self, klu_list): + return self.tf_df.get_klc_list(klu_list) def get_klu_list(self, dataframe): return self.tf_df.cal_klu_pattern(self.get_kl_data(dataframe)) \ No newline at end of file diff --git a/ChanMACD.py b/ChanMACD.py index 42d2af6..c0756b8 100644 --- a/ChanMACD.py +++ b/ChanMACD.py @@ -38,7 +38,7 @@ class ChanMACD(): else: signal = klu.pre.signal < klu.signal and klu.next.signal > klu.signal sd = klu.separate_div - if sd > 1 and ((hist > 0 and hist < 20) or (hist < 0 and hist > -20)): + if sd > 1 and ((hist > 0 and hist < 200) or (hist < 0 and hist > -200)): sd_list.append(klu.time) print(klu.time, sd) return sd_list diff --git a/ChanMACDUnitTF.py b/ChanMACDUnitTF.py index 156ebb6..4f13fff 100644 --- a/ChanMACDUnitTF.py +++ b/ChanMACDUnitTF.py @@ -61,9 +61,9 @@ class ChanMACDUnitTF(): 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.separate_div = self.div_count + 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.separate_div = self.div_count + histset.peak_klu.set_separate_div(self.div_count) else: if histset.peak_klu: self.peak_klu = histset.peak_klu diff --git a/TF_DF.py b/TF_DF.py index 1dc09e6..3e10e95 100644 --- a/TF_DF.py +++ b/TF_DF.py @@ -492,42 +492,8 @@ class TF_DF(): bi_list = self.cal_bi_list(self.get_klc_list(dataframe)) return bi_list def get_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 get_klc_list(self, dataframe): - klu_list = self.get_klu_list(dataframe) + return self.cal_kl_data(dataframe) + def get_klc_list(self, klu_list): klc_list = [] last_klu = None macd = ChanMACD(klu_list) @@ -1664,6 +1630,6 @@ class TF_DF(): if is_near_support or volume_confirmation: third_klu.set_pattern(Chan_KLU_PATTERN.TWEEZER_BOTTOM) return - + def get_decimal(self, value): return Decimal("{:.2f}".format(value)) \ No newline at end of file diff --git a/data_provider/main.py b/data_provider/main.py index 15ce9ba..c632e03 100644 --- a/data_provider/main.py +++ b/data_provider/main.py @@ -29,10 +29,10 @@ TIMEFRAME_TO_MS: Dict[str, int] = { "1w": 604_800_000, } DERIVED_TIMEFRAME_PLAN: Dict[str, List[str]] = { - "1m": ["2m", "3m", "4m", "5m", "10m", "15m", "20m", "25m", "30m"], - "1h": ["2h", "3h", "4h", "6h", "8h", "12h", "16h"], + "1m": ["2m", "3m", "4m", "5m", "10m", "15m", "20m", "25m", "30m", "45m"], + "1h": ["2h", "3h", "4h", "6h", "8h", "12h", "16h", "20h"], "1d": ["2d", "3d", "4d", "5d", "6d"], - "1w": ["2w"], + "1w": ["2w", "3w"], } CSV_FIELDNAMES = ["timestamp", "datetime", "open", "high", "low", "close", "volume"] DEFAULT_LIMIT = 500 @@ -583,14 +583,14 @@ class DataProvider: resampled_df = resampled.copy() if "date" in resampled_df.columns: dates = pd.to_datetime(resampled_df["date"], utc=True, errors="coerce") - resampled_df["timestamp"] = (dates.view("int64") // 1_000_000).astype("int64") + resampled_df["timestamp"] = (dates.astype("int64", copy=False) // 1_000_000).astype("int64") elif isinstance(resampled_df.index, pd.DatetimeIndex): idx = resampled_df.index if idx.tz is None: idx = idx.tz_localize("UTC") else: idx = idx.tz_convert("UTC") - resampled_df["timestamp"] = (idx.view("int64") // 1_000_000).astype("int64") + resampled_df["timestamp"] = (idx.astype("int64", copy=False) // 1_000_000).astype("int64") else: raise HTTPException(status_code=500, detail=f"聚合结果缺少 timestamp 列 ({timeframe})") resampled_df = resampled_df.dropna(subset=["timestamp"]).sort_values("timestamp") diff --git a/web/app.py b/web/app.py index 207fe8e..36e354b 100644 --- a/web/app.py +++ b/web/app.py @@ -521,7 +521,7 @@ def analyze_chan(df, symbol=None, timeframe=None): ema52_dict = None # 获取分析结果 klu_list = chan.get_kl_data(df) - klc_list = chan.get_klc_list(df) + klc_list = chan.get_klc_list(klu_list) bi_list = chan.cal_bi_list(klc_list) #for index in range(0, 10): #print(bi_list[index].start_time, bi_list[index].start_klc.end_time, bi_list[index].dir) @@ -1209,9 +1209,6 @@ def analyze(): elements_only_param = request.args.get('elements_only') elements_only = elements_only_param == 'true' - # 获取是否需要回放数据的参数 - need_replay_data = request.args.get('need_replay_data', 'false').lower() == 'true' - # 验证小周期是否小于主周期 if element_timeframe and not is_smaller_or_equal_timeframe(element_timeframe, timeframe): return jsonify({'error': '分形元素时间周期必须小于或等于主图表时间周期'}) @@ -1243,12 +1240,6 @@ def analyze(): # 计算MACD macd_data = calculate_macd(df) - # 如果需要回放数据,生成逐步计算的回放数据 - if need_replay_data: - replay_data = generate_replay_data(df, client_tz, symbol, element_timeframe, start_time, end_time) - else: - replay_data = None - # 基于已有 KLC 列表生成趋势标记(不做额外计算) klc_trend = [] try: @@ -1391,9 +1382,6 @@ def analyze(): 'klc_trend': klc_trend }) - # 如果生成了回放数据,添加到返回结果中 - if replay_data is not None: - result['replay_data'] = replay_data # 如果有指定分形元素时间周期,获取小周期数据 if element_timeframe: @@ -1670,19 +1658,5 @@ def get_uncompleted_seg_list(seg_list, client_tz): return result -def format_fx_type(fx_type): - """格式化分型类型显示""" - fx_type_map = { - 'TOP1': '顶分型1', - 'TOP2': '顶分型2', - 'TOP3': '顶分型3', - 'BOTTOM1': '底分型1', - 'BOTTOM2': '底分型2', - 'BOTTOM3': '底分型3', - 'TOP': '顶分型', - 'BOTTOM': '底分型' - } - return fx_type_map.get(fx_type, fx_type) - if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port=8128) \ No newline at end of file