From 63852efe47ca6590f61aa31c25e17bd76945ecc7 Mon Sep 17 00:00:00 2001 From: jackyu66git Date: Thu, 24 Apr 2025 20:34:16 +0800 Subject: [PATCH] Add classifier to the code --- ChanKLC.py | 2 +- ChanLun_Classifier.py | 66 ++++++++---------- __pycache__/ChanKLC.cpython-312.pyc | Bin 20885 -> 20616 bytes __pycache__/ChanLun.cpython-312.pyc | Bin 112036 -> 112036 bytes .../ChanLun_Classifier.cpython-312.pyc | Bin 18396 -> 17001 bytes config/ChanLun_SOL.json | 2 +- strategies/ChanLun_SOL_5.py | 22 +++--- 7 files changed, 42 insertions(+), 50 deletions(-) diff --git a/ChanKLC.py b/ChanKLC.py index b5934f4..42b742c 100644 --- a/ChanKLC.py +++ b/ChanKLC.py @@ -32,7 +32,7 @@ class ChanKLC(): self.distance = 0 self.klc_fx_type = Chan_KLC_FX.UNKNOWN def set_klc_fx_type(self, klc_fx_type): - print(self.start_time, klc_fx_type, self.get_feature_data()['klu_macd'], self.get_feature_data()['klu_macdhist'], self.get_feature_data()['klu_rsi']) + #print(self.start_time, klc_fx_type, self.get_feature_data()['klu_macd'], self.get_feature_data()['klu_macdhist'], self.get_feature_data()['klu_rsi']) if self.check_klc_fx_type(klc_fx_type): self.klc_fx_type = klc_fx_type def check_klc_fx_type(self, klc_fx_type): diff --git a/ChanLun_Classifier.py b/ChanLun_Classifier.py index e088d5b..4f44010 100644 --- a/ChanLun_Classifier.py +++ b/ChanLun_Classifier.py @@ -6,7 +6,7 @@ sys.path.append(os.path.abspath("/Users/jack/Project/freqtrade/user_data/Chan")) import numpy as np 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 +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 @@ -279,31 +279,24 @@ class ChanLunClassifier: :return: 特征矩阵X和标签y """ # 使用ChanLun获取bi_list - bi_list = self.chan.cal_bi_list(self.chan.get_klc_list(dataframe)) klc_list = self.chan.get_klc_list(dataframe) + bi_list = self.chan.cal_bi_list(klc_list) seg_list = self.chan.get_seg_list(bi_list) # 筛选方向为UP的bi的起始klc feature_data = [] labels = [] - bi_index = 0 + bi_index = 1 sample_list = [] for klc in klc_list: - if klc.pre and klc.next: - if klc.high > klc.pre.high and klc.high > klc.next.high: - klc.set_fx(Chan_FX_TYPE.TOP) - elif klc.low < klc.pre.low and klc.low < klc.next.low: - klc.set_fx(Chan_FX_TYPE.BOTTOM) - else: - klc.set_fx(Chan_FX_TYPE.UNKNOWN) - if klc.fx != Chan_FX_TYPE.UNKNOWN: + if klc.klc_fx_type != Chan_KLC_FX.UNKNOWN: sample_list.append(klc) for klc in sample_list: if bi_index >= len(bi_list): bi_index = len(bi_list) - 1 - bi = bi_list[bi_index] - if klc.end_klu and bi.end_klc and klc.start_klu.index >= bi.start_klc.start_klu.index and klc.end_klu.index <= bi.end_klc.end_klu.index: - klc.set_bi(bi) + #bi = bi_list[bi_index] + #if klc.end_klu and bi.end_klc and klc.start_klu.index >= bi.start_klc.start_klu.index and klc.end_klu.index <= bi.end_klc.end_klu.index: + #klc.set_bi(bi) # 提取特征 features = klc.get_feature_data() @@ -318,17 +311,21 @@ class ChanLunClassifier: # 判断这个bi是否赚钱(这里简单定义为:如果bi的结束价格高于起始价格,则标记为1,否则为0) # 这个标签定义可以根据实际需求修改 - bi = bi_list[bi_index] - if bi.start_klc.index == klc.index: - #if klc.index == seg.start_bi.start_klc.index and seg.dir == Chan_SEG_DIR.UP: - label = 1 - bi_index += 2 - else: + matched = False + for bi in bi_list: + if bi.end_klc and bi.end_klc.index == klc.index: + label = 1 + matched = True + break + if not matched: label = 0 feature_data.append(feature_vec) labels.append(label) - print("Trainning data: ", klc_list[-1].start_time, klc_list[-1].fx) + # 在return前添加 + positive_count = np.sum(labels) + print(f"正样本数量: {positive_count}, 负样本数量: {len(labels) - positive_count}") + print("Trainning data: ", len(feature_data), klc_list[-1].start_time, klc_list[-1].klc_fx_type , "---------------------") return np.array(feature_data), np.array(labels) def get_validate_feature_data(self, dataframe): """ @@ -337,23 +334,16 @@ class ChanLunClassifier: :return: 特征矩阵X和标签y """ # 使用ChanLun获取bi_list - bi_list = self.chan.cal_bi_list(self.chan.get_klc_list(dataframe)) klc_list = self.chan.get_klc_list(dataframe) + bi_list = self.chan.cal_bi_list(klc_list) seg_list = self.chan.get_seg_list(bi_list) # 筛选方向为UP的bi的起始klc feature_data = [] labels = [] - bi_index = 0 + bi_index = 1 sample_list = [] for klc in klc_list: - if klc.pre and klc.next: - if klc.high > klc.pre.high and klc.high > klc.next.high: - klc.set_fx(Chan_FX_TYPE.TOP) - elif klc.low < klc.pre.low and klc.low < klc.next.low: - klc.set_fx(Chan_FX_TYPE.BOTTOM) - else: - klc.set_fx(Chan_FX_TYPE.UNKNOWN) - if klc.fx != Chan_FX_TYPE.UNKNOWN: + if klc.klc_fx_type != Chan_KLC_FX.UNKNOWN: sample_list.append(klc) for klc in sample_list: if bi_index >= len(bi_list): @@ -371,16 +361,18 @@ class ChanLunClassifier: else: feature_vec.append(0) seg = seg_list[bi_index] - if bi.start_klc.index == klc.index: - #if klc.index == seg.start_bi.start_klc.index and seg.dir == Chan_SEG_DIR.UP: - label = 1 - bi_index += 2 - else: + matched = False + for bi in bi_list: + if bi.end_klc and bi.end_klc.index == klc.index: + label = 1 + matched = True + break + if not matched: label = 0 feature_data.append(feature_vec) labels.append(label) - + print("Validating data: ", len(feature_data), klc_list[-1].start_time, klc_list[-1].klc_fx_type , "---------------------") return np.array(feature_data), np.array(labels) def validate_model(self, dataframe=None): """ diff --git a/__pycache__/ChanKLC.cpython-312.pyc b/__pycache__/ChanKLC.cpython-312.pyc index 55ab417951dbf468316ca10f6749217686b10b4f..1408a12319a2733d901e1fed8f0966965e466e16 100644 GIT binary patch delta 650 zcmXxiPiWIn90&0H`e#Xl>C{$drg1B))=WB`3(k#oZC7Pf$L!b~h#euc)yB0&UNfQ4 zp?Fac5As6>f(O|_2VUe|L=;b+dhwjoj(YLpS@HcU2J*@8{oa?Cmq%Xg!jspa^)yYD z#ATdP>%I5d?{F+AMs)wWDAbIREgPcu zP}=9;w-bveV2*#yyae5s>F`+FrJ_Q`j|-HYL@zrY^$+|%+Pc^<-_3>q zs`xgSf+Bv)9UEAu=sf<+r3R*`oWbMy3{3Nz`NM$SM3i?HJncbIO!;!5?zFBg-C*Ms zJV#6rM~N&^Ag&OL#8o0pED;v5LaY(1ghP~x{@dx3_at_f8vVne|Bb2GC_RT2{8QTb E3*(NP)&Kwi delta 858 zcmYk5NlX(_7{}+E>9j+`V6}jNrIvtTv1q}>V8zm=7^4u%fF&NFW7EY}Wbt)S6ytWn zgHiM15>1Rtj1o@fUA&m+RT4wP0Wbd)$DgJL(XCyS2WDec{^Bh!j zx@pkv(rjg~Ae`rq-!^C}6Q^hO$y7RHR{l}>LeVfCXpv&UFPriVDNGq;6E8JgC$om0 z%chK3lGQUQBSnYp`iZkVbVc~2s0*2!)7Pi(&%f+j3q(tS=xQML_Gl>(U(ph4TCSw! zR<-;};ao|ZTe)!QyCBTNkhos%Hn1BOzY4;LI97I!i{AvHA}M}kukB+XlMX%&^(y`v z66C79AltF{P$%ic$b`}YUF?>kg0u*O>}f?&gb=N*yrzbD*bk%ut77zd;=V2Q%I2RaPNm8)7{OI$MQ*5si~y%+4O{-nr3G5&CI^XJ^yjl@b>&!baLKqXkio=woTmGBl54P$W(0szLN{6h#i7 zkNDA%WSaK{w1&C%+e}-gkT%MhxOY=77}?39-%%dEn|ghHG#Ra8Gro`q!fdJM0o0H^ zn8`0TjTif+3rFps$#A<&c5}_{hHU^j`mnccdq2h+5!O!eTOwN##}N_wxwp-}59I+` z6*&mqY#_1)pp)s*tLkMeHXX5iYN~%ALE15GFT$Fz7F85+2yqy31TlcHCK^O#o!bbi jQA7ffMkEo|+_>>Yf$Tzubwv385GU2+w_${?$M5|H84b%Q diff --git a/__pycache__/ChanLun.cpython-312.pyc b/__pycache__/ChanLun.cpython-312.pyc index 891bfbbee3dd1a2ca183a921a5a46108564deb0c..c1f8b8e514b35b4862f746cb6aed50da1c88917d 100644 GIT binary patch delta 24 ecmZ4Tnr+EzHm=jWyj%=G5UbV5wUvu;)>Z&xo(Dw$ delta 24 ecmZ4Tnr+EzHm=jWyj%=GFipIXYbzJytgQfL2M22a diff --git a/__pycache__/ChanLun_Classifier.cpython-312.pyc b/__pycache__/ChanLun_Classifier.cpython-312.pyc index e364a86f2e7942d82df37ae221bcfa922e004837..93f78e82c955e48c754371bcafb6f0b6818da59b 100644 GIT binary patch delta 4432 zcmcInYiu0V6`on|+xEV9?fAJ~+p))Q$B!5{b{=-@0>Oy{<*|h<f19=Zq|bM1EWlLqaSJQ4q2f^qih_&{0PN+fL(-(i8`(N%+CD zzMU%|ogk17gkbui(q8Gb-P|H-CBq$^rmdSQ(%B1`mck56P-)qs-G{wuj zq7bqlRUw3XQE!#`LqbSfK*FQKD94E+M7YhQ4vqY@(lf_S(WgA+-rT@fjiY-0!q%UC z(L1AuC_BnN-W`B`umUoAGwq7UWmv*=5LPkHN792q);0fM#X(X4G9-cV`(eVUIYH%e znQb`x*Yd9vq((urW=1uxWO}tQQJj%GKC<oFZf0Z>iT zM2JMg3aLO9t`6tSCA+4s;usoP$6-fh*5&J2J90n0r{;FZ_H#8`b@X3-7M)8^$99xa zN1d1Mt+UX3>sqP5+(I9zYppMM8aEI;N&O^~G{DaoVUs5KHz#z%%sr67q=k0W`*ezx z4%Sy%;N-~cTus7EcT`sGVVSuuJ(Dnl+# zadvhPXPc(;96x3qfwvucCQ^{JB?@2+*a}H|!hQfV{fP&r>bQ2xfhx*(d35l%v&&uG zsAZ))!X_ONebUAQ78>+eY^o&xI9sWRo@)pQQ zzg2K5xYxBOVn{e2gDWO4lg6xvgcCFQ81o%{R>LxRJ@ePakhMtYB4*@)1DkO)Q|68G zogQDr^0Xm6D7eXm_02|)Cz0!Zm7d1>t;Px6tqfxFs$<^Teh3 z=Py0}{YwuotbOgFe*cUcv@QPko;z{1{;1NAVuI>HGN_1=CQqZjHyO` zdRmA@(#J9eO@v^(H7ZAAvckv00>NXe8YY0F6x9T_I3{UE(>ZJ@kY^+UC%p|xQ{jmc z0>&3q15XHlgmYz1Fj|^(!J5XS^kmDfVe^E*D>Fop)xwMvIwXY26gqzpyO`ka2u}$S zRW}|bO{lR=$K|LJ1#%9@XJU%%qRv*gCCiU7+T7aGu?i>r%gnls@svJ#!|@xI-Q1F! zJH=gech8zvT)s!S7krWKTF4h2@z-jLO75mO$k)zf{Am4&%(iuMka zYe{J|W+vw#(djY}OTUrZjyi9LIt)1J6VyarfM(7^UPSws5MD<33BoG~NHXMAgx3(X zOFzdh{1Ub25iTJ73gJzJUnBem;kO9C zLwE~e5n+Q+3V;;J66%mmWETJwSG1(HIL9HU>3nZT&rQG~^2?u|NUC~Q+#aAAU+HY& zr=%2)2Kx8`U-@U`lWjf7C%uftwrHz4*)^ZISlhiYb&i}7mwRtn>b>Rs;l(?H7ZS^R zCztk4!r45??$YRCC`%7eU;e$%t}olDDoR9BEas;g$tOSX(ZCobger);y!n43- z{y|@>Hu4H;-bPRnFfQ2!0E?XWz}Lh6!5;R=6W{NUP zsknRVO}&P`%Q3di(064&+ikF37THq6;FWIH(4MwOQ?3W3Ej=nf9#Iyh@0Lu5@4rkVx-sTLA{rr8|h5>KvYfHykkPNS*WJNljHc2m0qhu zsK4IEB3jf}&*UTXHu(CR5rskWA@l_zVB}eV^#YbAo X>;SK5NFN^Uv&W2V`(*}EoAG}Dq?s5V delta 5026 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 0.01 and klc.fx == Chan_FX_TYPE.BOTTOM: + if self.classifier.predict(klc) > 0.45 and klc.fx == Chan_FX_TYPE.BOTTOM: features = klc.get_feature_data() print(klc.end_time, klc.fx, self.classifier.predict(klc), features['klc_macd'], features['klc_macd_hist'], features['klc_rsi'], features['klc_macd_signal']) bottom_avg += self.classifier.predict(klc) bottom_count += 1 - if self.classifier.predict(klc) > 0.05 and klc.fx == Chan_FX_TYPE.TOP: + if self.classifier.predict(klc) > 0.44 and klc.fx == Chan_FX_TYPE.TOP: features = klc.get_feature_data() print(klc.end_time, klc.fx, self.classifier.predict(klc), features['klc_macd'], features['klc_macd_hist'], features['klc_rsi'], features['klc_macd_signal']) top_avg += self.classifier.predict(klc) @@ -143,7 +143,7 @@ class ChanLun_SOL_5(IStrategy): top_avg /= top_count print(bottom_avg, top_avg) print("-------------------------------------------------------------------------------") - """ + """ self.print_xgb(dataframe, "1m_model") self.print_xgb(dataframe_5, "5m_model") @@ -163,11 +163,11 @@ class ChanLun_SOL_5(IStrategy): #dataframe_60['state'] = self.chan.cal_klu_state(dataframe_60) #dataframe_4h['state'] = self.chan.resample_klc_list(dataframe_4h) - self.chan.plot_dual(dataframe_30, dataframe_60) + #self.chan.plot_dual(dataframe_30, dataframe_60) dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) #self.print_macd_div_list(dataframe) #self.print_resample_df(dataframe, 1, 50) - self.chan.get_bi_list(dataframe_30) + #self.chan.get_bi_list(dataframe_30) if self.last_time + timedelta(minutes=1) < datetime.now(): #print(informative.iloc[-1]) #self.log_macd_div_list(dataframe)