From e75aca320e52202d259103f04185b8ec92059c8c Mon Sep 17 00:00:00 2001 From: jackyu66git Date: Wed, 10 Sep 2025 00:59:13 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=AD=96=E7=95=A5=E5=BC=80?= =?UTF-8?q?=E5=A7=8B=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChanKLU.py | 8 +++++- ChanLun.py | 20 +++++++++++++++ ChanMACDHistSet.py | 2 +- config/ChanLun_BTC_30.json | 2 +- strategies/ChanLun_BTC_30.py | 49 ++++++++++++++---------------------- 5 files changed, 48 insertions(+), 33 deletions(-) diff --git a/ChanKLU.py b/ChanKLU.py index 7d618ac..aa21388 100644 --- a/ChanKLU.py +++ b/ChanKLU.py @@ -651,7 +651,12 @@ class ChanKLU: if (self.macd == 0 and self.signal == 0 and self.macdhist == 0) or self.ema52 == 0: self.macd_state = Chan_MACD_STATE.UNKNOWN return self.macd_state - + if self.macd > 0: + if self.macd < self.signal and self.close > self.ema52 and self.low < self.ema52: + self.near0_return = 6 + else: + if self.macd > self.signal and self.close < self.ema52 and self.high > self.ema52: + self.near0_return = 7 # CROSS0 仅以 Signal 穿越零轴判定 if self.pre.signal >= 0 and self.signal < 0: self.macd_state = Chan_MACD_STATE.CROSS0_DOWN @@ -703,6 +708,7 @@ class ChanKLU: self.macd_state = Chan_MACD_STATE.NEAR0 #self.near0_return = 5 return self.macd_state + # 穿零轴后离开零轴 if self.pre.macd_state == Chan_MACD_STATE.CROSS0_UP and ((self.macd >= self.pre.macd and self.signal >= self.pre.signal) or (abs(self.macdhist) >= abs(self.pre.macdhist))): self.macd_state = Chan_MACD_STATE.UP diff --git a/ChanLun.py b/ChanLun.py index 079a195..abf60d7 100644 --- a/ChanLun.py +++ b/ChanLun.py @@ -81,6 +81,26 @@ class ChanLun(): def plot_dataframe(self, dataframe): klc_list = self.get_klc_list(dataframe) bi_list= self.cal_bi_list(klc_list) + def get_klu_state_list(self, dataframe): + klu_list = self.get_klu_list(dataframe) + chanmacd = ChanMACD(klu_list) + state_list = [] + for klu in klu_list: + if klu.macd > 0: + if klu.separate_div: + state_list.append("20") + elif klu.continue_div: + state_list.append("20") + else: + state_list.append("00") + else: + if klu.separate_div: + state_list.append("-20") + elif klu.continue_div: + state_list.append("-20") + else: + state_list.append("00") + return state_list def get_klc_state_list(self, dataframe): klc_list = self.get_klc_list(dataframe) bi_list= self.cal_bi_list(klc_list) diff --git a/ChanMACDHistSet.py b/ChanMACDHistSet.py index 09277ae..6ce09f3 100644 --- a/ChanMACDHistSet.py +++ b/ChanMACDHistSet.py @@ -24,7 +24,7 @@ class ChanMACDHistSet(): def set_pre(self, pre_histset): self.pre = pre_histset def set_middle_klu(self, middle_klu): - #self.middle_klu = middle_klu + self.middle_klu = middle_klu #self.middle_area = abs(middle_klu.macdhist) self.middle_klu = None def set_unittf_div(self, unittf_div): diff --git a/config/ChanLun_BTC_30.json b/config/ChanLun_BTC_30.json index d403952..cb75620 100644 --- a/config/ChanLun_BTC_30.json +++ b/config/ChanLun_BTC_30.json @@ -42,7 +42,7 @@ "ccxt_config": {}, "ccxt_async_config": {}, "pair_whitelist": [ - "BTC/USDT:USDT" + "ETH/USDT:USDT" ], "pair_blacklist": [ "BNB/.*" diff --git a/strategies/ChanLun_BTC_30.py b/strategies/ChanLun_BTC_30.py index fec9f53..7702ae9 100644 --- a/strategies/ChanLun_BTC_30.py +++ b/strategies/ChanLun_BTC_30.py @@ -20,7 +20,7 @@ logger = logging.getLogger(__name__) # freqtrade plot-dataframe --strategy ChanLun_BTC_30 --datadir user_data/data/binance -c ./user_data/ChanLun_SOL_30.json --timerange=20250309- # freqtrade trade -c ./user_data/Chan/config/ChanLun_BTC_30.json --strategy ChanLun_BTC_30 --strategy-path ./user_data/Chan/strategies -# freqtrade backtesting -c ./user_data/Chan/config/ChanLun_BTC_30.json --strategy ChanLun_BTC_30 --strategy-path ./user_data/Chan/strategies --timerange=20250820- +# freqtrade backtesting -c ./user_data/Chan/config/ChanLun_BTC_30.json --strategy ChanLun_BTC_30 --strategy-path ./user_data/Chan/strategies --timerange=20250901- # freqtrade download-data -c ./user_data/Chan/config/ChanLun_BTC_30.json -t 1m --pairs BTC/USDT:USDT --timerange=20250405- # freqtrade hyperopt --hyperopt-loss SharpeHyperOptLossDaily --spaces roi stoploss --strategy ChanLun_BTC_30 --strategy-path ./user_data/Chan/strategies -c ./user_data/Chan/config/ChanLun_BTC_30.json -e 200 --timerange=20250201-20250401 @@ -60,10 +60,9 @@ class ChanLun_BTC_30(IStrategy): "240": 0.025, "360": 0 } - minimal_roi = { - } + can_short = True - lev = 1.0 + lev = 2.5 stoploss = -0.3 # 设置为很大的负值,让custom_stoploss来控制 use_custom_stoploss = True # 启用自定义止损 @@ -118,21 +117,21 @@ class ChanLun_BTC_30(IStrategy): #self.chan.plot_dual(dataframe_5, dataframe_30) #chanpy_state = self.chanpy.get_bsp_state(dataframe_5) #dataframe_5['chanpy_state'] = chanpy_state - state_list = self.chan.get_klc_state_list(dataframe_3) + state_list = self.chan.get_klu_state_list(dataframe_3) dataframe_3['state'] = state_list - state_list = self.chan.get_klc_state_list(dataframe_5) + state_list = self.chan.get_klu_state_list(dataframe_5) dataframe_5['state'] = state_list - state_list = self.chan.get_klc_state_list(dataframe_15) + state_list = self.chan.get_klu_state_list(dataframe_15) dataframe_15['state'] = state_list - state_list = self.chan.get_klc_state_list(dataframe_30) + state_list = self.chan.get_klu_state_list(dataframe_30) dataframe_30['state'] = state_list - state_list = self.chan.get_klc_state_list(dataframe_60) + state_list = self.chan.get_klu_state_list(dataframe_60) dataframe_60['state'] = state_list - state_list = self.chan.get_klc_state_list(dataframe_2h) + state_list = self.chan.get_klu_state_list(dataframe_2h) dataframe_2h['state'] = state_list - state_list = self.chan.get_klc_state_list(dataframe_4h) + state_list = self.chan.get_klu_state_list(dataframe_4h) dataframe_4h['state'] = state_list - state_list = self.chan.get_klc_state_list(dataframe_1d) + state_list = self.chan.get_klu_state_list(dataframe_1d) dataframe_1d['state'] = state_list #bi_list_1 = self.chan.get_bi_list(dataframe) #bi_list_5 = self.chan.get_bi_list(dataframe_5) @@ -295,7 +294,7 @@ class ChanLun_BTC_30(IStrategy): last = dataframe.iloc[-1] atr_str = 'resample_{}_atr'.format(self.get_ticker_indicator()*self.time30) atr_val = float(last.get(atr_str, 0) or 0) - if atr_val < 100: + if atr_val < 0.001: logger.info(f"ATR过滤:atr={atr_val:.2f} < 100, 拒绝进场 {pair}") return False return True @@ -324,20 +323,9 @@ class ChanLun_BTC_30(IStrategy): logger.info(f"保存开仓时ATR值: {entry_atr}") return None def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - state_str = 'resample_{}_state'.format(self.get_ticker_indicator()*self.time15) - shift_time = self.time15 - dataframe.loc[ - ( - (dataframe[state_str].shift(shift_time) == "-20") - ), - ['enter_long', 'enter_tag']] = (1, 'long_15') - dataframe.loc[ - ( - (dataframe[state_str].shift(shift_time) == "20") - ), - ['enter_short', 'enter_tag']] = (1, 'short_15') - state_str = 'resample_{}_state'.format(self.get_ticker_indicator()*self.time30) shift_time = self.time30 + state_str = 'resample_{}_state'.format(self.get_ticker_indicator()*shift_time) + dataframe.loc[ ( (dataframe[state_str].shift(shift_time) == "-20") @@ -350,16 +338,17 @@ class ChanLun_BTC_30(IStrategy): ['enter_short', 'enter_tag']] = (1, 'short_30') return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - state_str = 'resample_{}_state'.format(self.get_ticker_indicator()*self.time15) - shift_time = self.time15 + shift_time = self.time30 + state_str = 'resample_{}_state'.format(self.get_ticker_indicator()*shift_time) + dataframe.loc[ ( - (dataframe[state_str].shift(shift_time) == "10") + (dataframe[state_str].shift(shift_time) == "20") ), ['exit_long', 'exit_tag']] = (1, 'long_close_15') dataframe.loc[ ( - (dataframe[state_str].shift(shift_time) == "-10") + (dataframe[state_str].shift(shift_time) == "-20") ), ['exit_short', 'exit_tag']] = (1, 'short_close_15') return dataframe