change something
This commit is contained in:
+3
-1
@@ -1,3 +1,5 @@
|
||||
.DS_Store
|
||||
__pycache__/
|
||||
strategies/__pycache__/
|
||||
strategies/__pycache__/
|
||||
/__pycache__
|
||||
*.pyc
|
||||
|
||||
@@ -1,92 +1,95 @@
|
||||
from decimal import Decimal
|
||||
import ChanKLC
|
||||
from ChanEnum import Chan_BI_DIR
|
||||
class ChanBI():
|
||||
def __init__(self, klc: ChanKLC, index, ddir=Chan_BI_DIR.UP):
|
||||
self.start_klc = klc
|
||||
self.end_klc = None
|
||||
self.next = None
|
||||
self.pre = None
|
||||
self.dir = ddir
|
||||
self.index = index
|
||||
self.is_sure = False
|
||||
self.high = klc.high
|
||||
self.low = klc.low
|
||||
self.sure_time = None
|
||||
self.klc_list = []
|
||||
self.klc_list.append(klc)
|
||||
self.end_time = None
|
||||
self.start_time = klc.start_time
|
||||
self.macd_hist = 0
|
||||
self.macd_div = 0
|
||||
def set_macdhist(self, macd_hist):
|
||||
self.macd_hist = macd_hist
|
||||
def set_macd_div(self, macd_div):
|
||||
self.macd_div = macd_div
|
||||
def cal_macd_div(self):
|
||||
self.macd_div = 0.0
|
||||
if self.pre and self.pre.pre:
|
||||
if self.pre.pre.macd_hist == 0:
|
||||
self.macd_div = 0.0
|
||||
else:
|
||||
self.macd_div = self.macd_hist / self.pre.pre.macd_hist
|
||||
def cal_macdhist(self):
|
||||
self.macd_hist = 0
|
||||
for klc in self.klc_list:
|
||||
for klu in klc.klus:
|
||||
if self.dir == Chan_BI_DIR.UP and klu.macdhist > 0:
|
||||
self.macd_hist += klu.macdhist
|
||||
if self.dir == Chan_BI_DIR.DOWN and klu.macdhist < 0:
|
||||
self.macd_hist -= klu.macdhist
|
||||
def check_overlap(self):
|
||||
if self.next and self.next.next:
|
||||
if self.dir == Chan_BI_DIR.UP:
|
||||
return self.high > self.next.low and self.high < self.next.next.high
|
||||
else:
|
||||
return self.high > self.next.high and self.low > self.next.next.low
|
||||
else:
|
||||
return False
|
||||
def set_end_klc(self, klc, sure_klc):
|
||||
if self.dir == Chan_BI_DIR.UP and klc.high > self.high:
|
||||
self.high = klc.high
|
||||
if self.dir == Chan_BI_DIR.DOWN and klc.low < self.low:
|
||||
self.low = klc.low
|
||||
self.end_klc = klc
|
||||
self.set_is_sure(True, sure_klc.end_time)
|
||||
self.end_time = klc.end_time
|
||||
#print(self.start_time, klc.start_time, klc.fx, "This bi is ended")
|
||||
def set_is_sure(self, is_sure, time):
|
||||
self.is_sure = is_sure
|
||||
self.sure_time = time
|
||||
def set_start_klc(self, klc, ddir):
|
||||
self.start_klc = klc
|
||||
self.klc_list = []
|
||||
self.klc_list.append(klc)
|
||||
self.high = klc.high
|
||||
self.low = klc.low
|
||||
self.dir = ddir
|
||||
def set_pre(self, bi):
|
||||
self.pre = bi
|
||||
def set_next(self, bi):
|
||||
self.next = bi
|
||||
def add_klc(self, klc):
|
||||
added = False
|
||||
if len(self.klc_list) > 0:
|
||||
for index in range(0, len(self.klc_list)):
|
||||
if self.klc_list[index].index == klc.index:
|
||||
added = True
|
||||
break
|
||||
if not added:
|
||||
self.klc_list.append(klc)
|
||||
self.cal_macdhist()
|
||||
self.cal_macd_div()
|
||||
def append_klc_list(self, klc_list):
|
||||
self.klc_list.append(klc_list)
|
||||
def update_bi(self, klc):
|
||||
self.end_klc = None
|
||||
if self.dir == Chan_BI_DIR.UP and klc.high > self.high:
|
||||
self.high = klc.high
|
||||
if self.dir == Chan_BI_DIR.DOWN and klc.low < self.low:
|
||||
self.low = klc.low
|
||||
self.is_sure = False
|
||||
self.sure_time = None
|
||||
#print(self.start_time, klc.start_time, klc.fx, "This bi is extended")
|
||||
def __init__(self, klc: ChanKLC, index, ddir=Chan_BI_DIR.UP):
|
||||
self.start_klc = klc
|
||||
self.end_klc = None
|
||||
self.next = None
|
||||
self.pre = None
|
||||
self.dir = ddir
|
||||
self.index = index
|
||||
self.is_sure = False
|
||||
self.high = klc.high
|
||||
self.low = klc.low
|
||||
self.sure_time = None
|
||||
self.klc_list = []
|
||||
self.klc_list.append(klc)
|
||||
self.end_time = None
|
||||
self.start_time = klc.start_time
|
||||
self.macd_hist = 0
|
||||
self.macd_div = 0
|
||||
def set_macdhist(self, macd_hist):
|
||||
self.macd_hist = macd_hist
|
||||
def set_macd_div(self, macd_div):
|
||||
self.macd_div = macd_div
|
||||
def cal_macd_div(self):
|
||||
self.macd_div = 0.0
|
||||
if self.pre and self.pre.pre:
|
||||
if self.pre.pre.macd_hist == 0:
|
||||
self.macd_div = 0.0
|
||||
else:
|
||||
self.macd_div = self.macd_hist / self.pre.pre.macd_hist
|
||||
def cal_macdhist(self):
|
||||
self.macd_hist = 0
|
||||
for klc in self.klc_list:
|
||||
for klu in klc.klus:
|
||||
if self.dir == Chan_BI_DIR.UP and klu.macdhist > 0:
|
||||
self.macd_hist += klu.macdhist
|
||||
if self.dir == Chan_BI_DIR.DOWN and klu.macdhist < 0:
|
||||
self.macd_hist -= klu.macdhist
|
||||
def check_overlap(self):
|
||||
if self.next and self.next.next:
|
||||
if self.dir == Chan_BI_DIR.UP:
|
||||
return self.high > self.next.low and self.high < self.next.next.high
|
||||
else:
|
||||
return self.high > self.next.high and self.low > self.next.next.low
|
||||
else:
|
||||
return False
|
||||
def set_end_klc(self, klc, sure_klc):
|
||||
if self.dir == Chan_BI_DIR.UP and klc.high > self.high:
|
||||
self.high = klc.high
|
||||
if self.dir == Chan_BI_DIR.DOWN and klc.low < self.low:
|
||||
self.low = klc.low
|
||||
self.end_klc = klc
|
||||
self.set_is_sure(True, sure_klc.end_time)
|
||||
self.end_time = klc.end_time
|
||||
#print(self.start_time, klc.start_time, klc.fx, "This bi is ended")
|
||||
def set_is_sure(self, is_sure, time):
|
||||
self.is_sure = is_sure
|
||||
self.sure_time = time
|
||||
def set_start_klc(self, klc, ddir):
|
||||
self.start_klc = klc
|
||||
self.klc_list = []
|
||||
self.klc_list.append(klc)
|
||||
self.high = klc.high
|
||||
self.low = klc.low
|
||||
self.dir = ddir
|
||||
def set_pre(self, bi):
|
||||
self.pre = bi
|
||||
def set_next(self, bi):
|
||||
self.next = bi
|
||||
def add_klc(self, klc):
|
||||
added = False
|
||||
if len(self.klc_list) > 0:
|
||||
for index in range(0, len(self.klc_list)):
|
||||
if self.klc_list[index].index == klc.index:
|
||||
added = True
|
||||
break
|
||||
if not added:
|
||||
self.klc_list.append(klc)
|
||||
self.cal_macdhist()
|
||||
self.cal_macd_div()
|
||||
def append_klc_list(self, klc_list):
|
||||
self.klc_list.append(klc_list)
|
||||
def get_decimal(self, value):
|
||||
return Decimal("{:.2f}".format(value))
|
||||
def update_bi(self, klc):
|
||||
self.end_klc = None
|
||||
if self.dir == Chan_BI_DIR.UP and klc.high > self.high:
|
||||
self.high = klc.high
|
||||
if self.dir == Chan_BI_DIR.DOWN and klc.low < self.low:
|
||||
self.low = klc.low
|
||||
self.is_sure = False
|
||||
self.sure_time = None
|
||||
#print(self.start_time, klc.start_time, klc.fx, "This bi is extended")
|
||||
+9
-44
@@ -25,35 +25,14 @@ class ChanKLC():
|
||||
self.open = klu.open
|
||||
self.close = klu.close
|
||||
self.volume = klu.volume
|
||||
self.macdhist = 0
|
||||
self.bi_macdhist = 0
|
||||
self.bi_macd_div = 0.0
|
||||
self.bi = None
|
||||
self.distance = 0
|
||||
self.klc_fx_type = Chan_KLC_FX.UNKNOWN
|
||||
self.rsi = klu.rsi
|
||||
self.volume_ratio = klu.volume_ratio
|
||||
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'])
|
||||
if self.check_klc_fx_type(klc_fx_type):
|
||||
self.klc_fx_type = klc_fx_type
|
||||
self.klc_fx_type = klc_fx_type
|
||||
def check_klc_fx_type(self, klc_fx_type):
|
||||
if klc_fx_type == Chan_KLC_FX.BOTTOM1:
|
||||
features = self.cal_klu_features()
|
||||
if features['klu_macd'] > 0:
|
||||
#print(self.start_time, klc_fx_type, features['klu_macd'])
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
elif klc_fx_type == Chan_KLC_FX.TOP1:
|
||||
features = self.get_feature_data()
|
||||
if features['klu_macd'] < 0:
|
||||
#print(self.start_time, klc_fx_type, features['klu_macd'])
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
else:
|
||||
return True
|
||||
|
||||
def add_klu(self, klu):
|
||||
self.klus.append(klu)
|
||||
def set_end_klu(self, klu):
|
||||
@@ -62,6 +41,10 @@ class ChanKLC():
|
||||
self.close = klu.close
|
||||
for index in range(1, len(self.klus)):
|
||||
self.volume += self.klus[index].volume
|
||||
self.rsi += self.klus[index].rsi
|
||||
self.volume_ratio += self.klus[index].volume_ratio
|
||||
self.rsi = self.rsi / len(self.klus)
|
||||
self.volume_ratio = self.volume_ratio / len(self.klus)
|
||||
def set_next(self, klc):
|
||||
self.next = klc
|
||||
def set_pre(self, klc):
|
||||
@@ -138,27 +121,7 @@ class ChanKLC():
|
||||
return Chan_FX_TYPE.UNKNOWN
|
||||
def set_bi(self, bi):
|
||||
self.bi = bi
|
||||
self.get_macdhist()
|
||||
for index in range(0, len(self.bi.klc_list)):
|
||||
klc = self.bi.klc_list[index]
|
||||
if klc.index == self.index:
|
||||
break
|
||||
else:
|
||||
if bi.dir == Chan_BI_DIR.UP and klc.get_macdhist() > 0:
|
||||
self.bi_macdhist += klc.get_macdhist()
|
||||
elif bi.dir == Chan_BI_DIR.DOWN and klc.get_macdhist() < 0:
|
||||
self.bi_macdhist -= klc.get_macdhist()
|
||||
self.distance = self.index - bi.start_klc.index
|
||||
if False:
|
||||
if bi.is_sure:
|
||||
print(self.start_time, self.distance, bi.index, bi.start_time, bi.dir, bi.end_time)
|
||||
else:
|
||||
print(self.start_time, self.distance, bi.index, bi.start_time, bi.dir)
|
||||
def get_macdhist(self):
|
||||
self.macdhist = 0
|
||||
for klu in self.klus:
|
||||
self.macdhist += klu.macdhist
|
||||
return self.macdhist
|
||||
def cal_klu_features(self):
|
||||
features = dict()
|
||||
feature_sums = dict()
|
||||
@@ -196,6 +159,8 @@ class ChanKLC():
|
||||
features['klc_pre_pre_fx'] = (0 if self.pre.pre.fx == Chan_FX_TYPE.UNKNOWN else 1 if self.pre.pre.fx == Chan_FX_TYPE.TOP else 2) if self.pre and self.pre.pre else 0 #11
|
||||
features['klc_pre_pre_pre_fx'] = (0 if self.pre.pre.pre.fx == Chan_FX_TYPE.UNKNOWN else 1 if self.pre.pre.pre.fx == Chan_FX_TYPE.TOP else 2) if self.pre and self.pre.pre and self.pre.pre.pre else 0 #12
|
||||
features['klc_distance'] = self.distance #13
|
||||
features['klc_volume_ratio'] = self.volume_ratio #14
|
||||
features['klc_rsi'] = self.rsi #15
|
||||
# New Add 20250422
|
||||
#features['klc_macdhist'] = self.get_macdhist() #11
|
||||
#features['klc_bi_macdhist'] = self.bi_macdhist #12
|
||||
@@ -492,6 +457,6 @@ class ChanKLC():
|
||||
features['klc_is_inner_inclusive'] = 0
|
||||
|
||||
# 从KLU获取其他特征
|
||||
features.update(self.cal_klu_features())
|
||||
#features.update(self.cal_klu_features())
|
||||
|
||||
return features
|
||||
@@ -18,6 +18,7 @@ class ChanKLU:
|
||||
self.ma30 = 0
|
||||
self.ma250 = 0
|
||||
self.rsi = 0
|
||||
self.volume_ratio = 0
|
||||
def set_idx(self, idx):
|
||||
self.idx = idx
|
||||
self.index = idx
|
||||
@@ -30,6 +31,7 @@ class ChanKLU:
|
||||
self.ma30 = float(item['ma30']) if item['ma30'] else 0
|
||||
self.ma250 = float(item['ma250']) if item['ma250'] else 0
|
||||
self.rsi = float(item['rsi']) if item['rsi'] else 0
|
||||
self.volume_ratio = float(item['volume_ratio']) if item['volume_ratio'] else 0
|
||||
def get_feature_data(self):
|
||||
features = dict()
|
||||
features['klu_close'] = self.close
|
||||
@@ -46,4 +48,5 @@ class ChanKLU:
|
||||
features['klu_ma30'] = self.ma30
|
||||
features['klu_ma250'] = self.ma250
|
||||
features['klu_rsi'] = self.rsi
|
||||
features['klu_volume_ratio'] = self.volume_ratio
|
||||
return features
|
||||
+28
-5
@@ -80,8 +80,8 @@ class ChanLun():
|
||||
return Chan_FX_TYPE.UNKNOWN
|
||||
def get_macd(self, df):
|
||||
fast = 8
|
||||
slow = 16
|
||||
period = 6
|
||||
slow = 15
|
||||
period = 2
|
||||
macd = ta.MACD(df, fastperiod=fast, slowperiod=slow, signalperiod=period)
|
||||
df['macd'] = macd['macd']
|
||||
df['macdsignal'] = macd['macdsignal']
|
||||
@@ -212,6 +212,27 @@ class ChanLun():
|
||||
klc_list = self.get_klc_list(dataframe)
|
||||
bi_list = self.cal_bi_list(klc_list)
|
||||
return klc_list
|
||||
def print_bi_klc(self, dataframe):
|
||||
klc_list = self.get_klc_list(dataframe)
|
||||
bi_list = self.cal_bi_list(klc_list)
|
||||
rsi_list = dataframe['rsi']
|
||||
fx_list = []
|
||||
for klc in klc_list:
|
||||
if klc.klc_fx_type != Chan_KLC_FX.UNKNOWN:
|
||||
if klc.bi.dir == Chan_BI_DIR.UP and klc.volume_ratio > 2:
|
||||
print(klc.start_time, klc.end_time, klc.klc_fx_type, klc.rsi, klc.volume_ratio)
|
||||
fx_list.append(klc)
|
||||
elif klc.bi.dir == Chan_BI_DIR.DOWN and klc.volume_ratio > 2:
|
||||
print(klc.start_time, klc.end_time, klc.klc_fx_type, klc.rsi, klc.volume_ratio)
|
||||
fx_list.append(klc)
|
||||
bi_start_index_list = []
|
||||
for bi in bi_list:
|
||||
bi_start_index_list.append(bi.start_klc.index)
|
||||
if bi.end_klc:
|
||||
bi.cal_macdhist()
|
||||
bi.cal_macd_div()
|
||||
print("Bi:", bi.start_time, bi.end_time, bi.dir, bi.macd_hist, bi.macd_div)
|
||||
klc_index_count = 0
|
||||
def get_seg_list(self, bi_list):
|
||||
seg_list = []
|
||||
up_bi_list = []
|
||||
@@ -639,6 +660,7 @@ class ChanLun():
|
||||
#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)
|
||||
bi_list[-1].add_klc(klc)
|
||||
klc.set_bi(bi_list[-1])
|
||||
else:
|
||||
@@ -758,6 +780,7 @@ class ChanLun():
|
||||
#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)
|
||||
bi_list[-1].add_klc(klc)
|
||||
klc.set_bi(bi_list[-1])
|
||||
else:
|
||||
@@ -1903,10 +1926,10 @@ class ChanLun():
|
||||
bbox=dict(boxstyle="round,pad=0.2", fc=style['color'], alpha=0.5))
|
||||
"""
|
||||
# 绘制MACD(使用小周期数据)
|
||||
exp1 = small_df['close'].ewm(span=8, adjust=False).mean()
|
||||
exp2 = small_df['close'].ewm(span=16, adjust=False).mean()
|
||||
exp1 = small_df['close'].ewm(span=12, adjust=False).mean()
|
||||
exp2 = small_df['close'].ewm(span=26, adjust=False).mean()
|
||||
macd = exp1 - exp2
|
||||
signal = macd.ewm(span=6, adjust=False).mean()
|
||||
signal = macd.ewm(span=9, adjust=False).mean()
|
||||
histogram = macd - signal
|
||||
|
||||
ax3.bar(small_dates_num, histogram, width=0.0002, color=['red' if h > 0 else 'green' for h in histogram])
|
||||
|
||||
@@ -288,7 +288,6 @@ class ChanLunClassifier:
|
||||
# 使用ChanLun获取bi_list
|
||||
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 = []
|
||||
@@ -312,7 +311,6 @@ class ChanLunClassifier:
|
||||
# 保存第一个样本的特征名称,用于CSV列名
|
||||
if len(feature_keys) == 0:
|
||||
feature_keys = list(features.keys())
|
||||
|
||||
# 将特征转换为模型可用的格式
|
||||
feature_vec = []
|
||||
for key, value in features.items():
|
||||
@@ -335,7 +333,8 @@ class ChanLunClassifier:
|
||||
|
||||
feature_data.append(feature_vec)
|
||||
labels.append(label)
|
||||
|
||||
for index, key in enumerate(feature_keys):
|
||||
print(index, key, feature_data[0][index])
|
||||
# 如果需要保存到CSV
|
||||
if save_csv:
|
||||
# 创建DataFrame保存特征数据
|
||||
|
||||
@@ -117,6 +117,8 @@ class ChanLun_SOL_15(IStrategy):
|
||||
#self.print_macd_div_list(dataframe)
|
||||
#self.print_resample_df(dataframe, 1, 50)
|
||||
#self.chan.get_bi_list(dataframe_30)
|
||||
#self.chan.plot_dual(dataframe_5, dataframe_30)
|
||||
self.chan.print_bi_klc(dataframe_5)
|
||||
#if self.last_time + timedelta(minutes=1) < datetime.now():
|
||||
#print(informative.iloc[-1])
|
||||
#self.print_klc(dataframe, "1m: ")
|
||||
@@ -279,10 +281,11 @@ class ChanLun_SOL_15(IStrategy):
|
||||
cn3 = 'resample_{}_state'.format(self.get_ticker_indicator()*time)
|
||||
logger.info(f'{df[cn1][index]}, {df[cn2][index]}, {df[cn3][index]}')
|
||||
def add_indicators(self, df):
|
||||
fast = 9
|
||||
slow = 24
|
||||
period = 14
|
||||
fast = 8
|
||||
slow = 16
|
||||
period = 6
|
||||
macd = ta.MACD(df, fastperiod=fast, slowperiod=slow, signalperiod=period)
|
||||
|
||||
df['macd'] = macd['macd']
|
||||
df['macdsignal'] = macd['macdsignal']
|
||||
df['macdhist'] = macd['macdhist']
|
||||
@@ -299,7 +302,17 @@ class ChanLun_SOL_15(IStrategy):
|
||||
df['ma30'] = df['ma30'].fillna(0)
|
||||
df['ma250'] = df['ma250'].fillna(0)
|
||||
df['rsi'] = df['rsi'].fillna(0)
|
||||
df['volume_ratio'] = self.cal_volume_ratio(df)
|
||||
return df
|
||||
def cal_volume_ratio(self, dataframe, window=10):
|
||||
df = dataframe.copy()
|
||||
# 计算过去N根K线的平均成交量
|
||||
df['avg_volume'] = df['volume'].rolling(window=window).mean()
|
||||
# 计算量比
|
||||
df['volume_ratio'] = df['volume'] / df['avg_volume']
|
||||
# 填充缺失值(前N根K线)
|
||||
df['volume_ratio'] = df['volume_ratio'].fillna(1.0)
|
||||
return df['volume_ratio']
|
||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
|
||||
dataframe.loc[
|
||||
|
||||
+21
-11
@@ -115,9 +115,9 @@ class ChanLun_SOL_5(IStrategy):
|
||||
self.classifier.train_model(dataframe, model_name="1m_model")
|
||||
self.classifier.train_model(dataframe_1d, model_name="1d_model")
|
||||
"""
|
||||
"""
|
||||
model_name = "30m_model"
|
||||
df = dataframe_30
|
||||
|
||||
model_name = "5m_model"
|
||||
df = dataframe_5
|
||||
if self.classifier.model is None:
|
||||
#self.classifier.train_model(df, model_name=model_name, data_file_path=model_name + '_feature_data.csv')
|
||||
self.classifier.load_model(model_name=model_name)
|
||||
@@ -129,14 +129,14 @@ class ChanLun_SOL_5(IStrategy):
|
||||
bottom_count = 0
|
||||
for index in range(int(len(klc_list) * 0.8), len(klc_list)):
|
||||
klc = klc_list[index]
|
||||
if self.classifier.predict(klc) > 0.4 and (klc.klc_fx_type == Chan_KLC_FX.BOTTOM1 or klc.klc_fx_type == Chan_KLC_FX.BOTTOM2):
|
||||
if self.classifier.predict(klc) > 0.37 and (klc.klc_fx_type == Chan_KLC_FX.BOTTOM1 or klc.klc_fx_type == Chan_KLC_FX.BOTTOM2):
|
||||
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'])
|
||||
print(klc.end_time, klc.fx, self.classifier.predict(klc), features['klc_volume_ratio'], features['klc_macd_hist'], features['klc_rsi'])
|
||||
bottom_avg += self.classifier.predict(klc)
|
||||
bottom_count += 1
|
||||
if self.classifier.predict(klc) > 0.35 and (klc.klc_fx_type == Chan_KLC_FX.TOP1 or klc.klc_fx_type == Chan_KLC_FX.TOP2):
|
||||
if self.classifier.predict(klc) > 0.37 and (klc.klc_fx_type == Chan_KLC_FX.TOP1 or klc.klc_fx_type == Chan_KLC_FX.TOP2):
|
||||
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'])
|
||||
print(klc.end_time, klc.fx, self.classifier.predict(klc), features['klc_volume_ratio'], features['klc_macd_hist'], features['klc_rsi'])
|
||||
top_avg += self.classifier.predict(klc)
|
||||
top_count += 1
|
||||
if bottom_count > 0:
|
||||
@@ -145,7 +145,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")
|
||||
@@ -350,9 +350,9 @@ class ChanLun_SOL_5(IStrategy):
|
||||
cn3 = 'resample_{}_state'.format(self.get_ticker_indicator()*time)
|
||||
logger.info(f'{df[cn1][index]}, {df[cn2][index]}, {df[cn3][index]}')
|
||||
def add_indicators(self, df):
|
||||
fast = 9
|
||||
slow = 24
|
||||
period = 14
|
||||
fast = 8
|
||||
slow = 16
|
||||
period = 6
|
||||
macd = ta.MACD(df, fastperiod=fast, slowperiod=slow, signalperiod=period)
|
||||
df['macd'] = macd['macd']
|
||||
df['macdsignal'] = macd['macdsignal']
|
||||
@@ -362,7 +362,17 @@ class ChanLun_SOL_5(IStrategy):
|
||||
df['ma30'] = ta.EMA(df, timeperiod=30)
|
||||
df['ma250'] = ta.MA(df, timeperiod=250)
|
||||
df['rsi'] = ta.RSI(df, timeperiod=14)
|
||||
df['volume_ratio'] = self.cal_volume_ratio(df)
|
||||
return df
|
||||
def cal_volume_ratio(self, dataframe, window=10):
|
||||
df = dataframe.copy()
|
||||
# 计算过去N根K线的平均成交量
|
||||
df['avg_volume'] = df['volume'].rolling(window=window).mean()
|
||||
# 计算量比
|
||||
df['volume_ratio'] = df['volume'] / df['avg_volume']
|
||||
# 填充缺失值(前N根K线)
|
||||
df['volume_ratio'] = df['volume_ratio'].fillna(1.0)
|
||||
return df['volume_ratio']
|
||||
def local_print(self, df):
|
||||
fast = 7
|
||||
slow = 14
|
||||
|
||||
+39
-4
@@ -12,7 +12,7 @@ import base64
|
||||
import time
|
||||
import traceback
|
||||
from pytz import timezone
|
||||
|
||||
import talib.abstract as ta
|
||||
# 添加父目录到系统路径
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
@@ -142,6 +142,7 @@ def get_kl_data(symbol, timeframe, limit=1000, start_time=None, end_time=None):
|
||||
ret_df.loc[klc_index] = df_copy.loc[index]
|
||||
klc_index += 1
|
||||
"""
|
||||
df = add_indicators(df)
|
||||
# 如果过滤后没有数据,返回None
|
||||
if len(df) == 0:
|
||||
print("过滤后无数据")
|
||||
@@ -154,7 +155,35 @@ def get_kl_data(symbol, timeframe, limit=1000, start_time=None, end_time=None):
|
||||
print(f"获取数据错误: {e}")
|
||||
traceback.print_exc()
|
||||
return None
|
||||
def add_indicators(df):
|
||||
fast = 8
|
||||
slow = 16
|
||||
period = 6
|
||||
macd = ta.MACD(df, fastperiod=fast, slowperiod=slow, signalperiod=period)
|
||||
|
||||
df['macd'] = macd['macd']
|
||||
df['macdsignal'] = macd['macdsignal']
|
||||
df['macdhist'] = macd['macdhist']
|
||||
df['ma5'] = (ta.MA(df, timeperiod=5)).fillna(0)
|
||||
df['ma10'] = (ta.MA(df, timeperiod=10)).fillna(0)
|
||||
df['ma30'] = (ta.EMA(df, timeperiod=30)).fillna(0)
|
||||
df['ma250'] = (ta.MA(df, timeperiod=250)).fillna(0)
|
||||
df['rsi'] = ta.RSI(df, timeperiod=14)
|
||||
df['macd'] = df['macd'].fillna(0)
|
||||
df['macdsignal'] = df['macdsignal'].fillna(0)
|
||||
df['macdhist'] = df['macdhist'].fillna(0)
|
||||
df['ma5'] = df['ma5'].fillna(0)
|
||||
df['ma10'] = df['ma10'].fillna(0)
|
||||
df['ma30'] = df['ma30'].fillna(0)
|
||||
df['ma250'] = df['ma250'].fillna(0)
|
||||
df['rsi'] = df['rsi'].fillna(0)
|
||||
df['avg_volume'] = df['volume'].rolling(10).mean()
|
||||
# 计算量比
|
||||
df['volume_ratio'] = df['volume'] / df['avg_volume']
|
||||
# 填充缺失值(前N根K线)
|
||||
df['volume_ratio'] = df['volume_ratio'].fillna(1.0)
|
||||
df['avg_volume'] = df['avg_volume'].fillna(0)
|
||||
return df
|
||||
def calculate_macd(df):
|
||||
"""计算MACD指标"""
|
||||
exp1 = df['close'].ewm(span=12, adjust=False).mean()
|
||||
@@ -182,7 +211,11 @@ def analyze_chan(df):
|
||||
zs_list = chan.calculate_zs(bi_list, seg_list)
|
||||
# 添加买卖点识别
|
||||
buy_sell_points = identify_trade_points(bi_list, seg_list, zs_list)
|
||||
|
||||
for bi in bi_list:
|
||||
bi.cal_macdhist()
|
||||
for bi in bi_list:
|
||||
bi.cal_macd_div()
|
||||
#print(bi.start_time, bi.macd_hist, bi.macd_div)
|
||||
# 提取K线分型信息
|
||||
klc_fx_info = []
|
||||
for klc in klc_list:
|
||||
@@ -411,7 +444,8 @@ def analyze():
|
||||
'end_time': (bi.end_klc.end_time if isinstance(bi.end_klc.end_time, str) else bi.end_klc.end_time.astimezone(client_tz).isoformat()) if bi.end_klc else None,
|
||||
'start_price': bi.start_klc.low if convert_direction(bi.dir) == 1 else bi.start_klc.high,
|
||||
'end_price': bi.end_klc.high if convert_direction(bi.dir) == 1 else bi.end_klc.low if bi.end_klc else None,
|
||||
'direction': convert_direction(bi.dir)
|
||||
'direction': convert_direction(bi.dir),
|
||||
'macd_div': float(bi.macd_div) if hasattr(bi, 'macd_div') else 0
|
||||
} for bi in analysis_result['bi_list'] if bi.end_klc],
|
||||
'seg_list': [{
|
||||
'start_time': seg.start_bi.start_klc.end_time if isinstance(seg.start_bi.start_klc.end_time, str) else seg.start_bi.start_klc.end_time.astimezone(client_tz).isoformat(),
|
||||
@@ -470,7 +504,8 @@ def analyze():
|
||||
'end_time': (bi.end_klc.end_time if isinstance(bi.end_klc.end_time, str) else bi.end_klc.end_time.astimezone(client_tz).isoformat()) if bi.end_klc else None,
|
||||
'start_price': bi.start_klc.low if convert_direction(bi.dir) == 1 else bi.start_klc.high,
|
||||
'end_price': bi.end_klc.high if convert_direction(bi.dir) == 1 else bi.end_klc.low if bi.end_klc else None,
|
||||
'direction': convert_direction(bi.dir)
|
||||
'direction': convert_direction(bi.dir),
|
||||
'macd_div': float(bi.macd_div) if hasattr(bi, 'macd_div') else 0
|
||||
} for bi in element_analysis['bi_list'] if bi.end_klc]
|
||||
|
||||
# 添加小周期K线数据
|
||||
|
||||
@@ -442,6 +442,7 @@
|
||||
<th>起始价格</th>
|
||||
<th>结束价格</th>
|
||||
<th>方向</th>
|
||||
<th>MACD背离值</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
@@ -1553,6 +1554,39 @@
|
||||
color: bi.direction === 1 ? '#dc3545' : '#28a745',
|
||||
lineWidth: 1
|
||||
});
|
||||
|
||||
// 在笔的末端添加macd_div值标记
|
||||
if (bi.macd_div && bi.macd_div !== 0) {
|
||||
console.log(`添加macd_div标记: ${bi.macd_div.toFixed(2)}, 在时间点: ${endTime}`);
|
||||
|
||||
const macdDivLabel = mainChart.addLineSeries({
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
});
|
||||
|
||||
// 确定标记位置
|
||||
const markerPosition = bi.direction === 1 ? 'aboveBar' : 'belowBar';
|
||||
const labelValue = bi.direction === 1 ? endPrice + (endPrice * 0.005) : endPrice - (endPrice * 0.005);
|
||||
const arrayShape = bi.direction === 1 ? 'arrowDown' : 'arrowUp';
|
||||
// 简化标记显示
|
||||
macdDivLabel.setData([
|
||||
{ time: endTime, value: labelValue }
|
||||
]);
|
||||
|
||||
// 使用不同方式添加文本标记
|
||||
const textColor = bi.macd_div > 0 ? '#dc3545' : '#28a745';
|
||||
const textSize = Math.min(14, Math.max(10, Math.abs(bi.macd_div) * 2));
|
||||
|
||||
macdDivLabel.setMarkers([
|
||||
{
|
||||
time: endTime,
|
||||
position: markerPosition,
|
||||
color: textColor,
|
||||
shape: arrayShape,
|
||||
text: bi.macd_div.toFixed(2),
|
||||
}
|
||||
]);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('主周期笔处理出错:', e);
|
||||
}
|
||||
@@ -1599,6 +1633,40 @@
|
||||
color: bi.direction === 1 ? '#9c27b0' : '#673ab7',
|
||||
lineWidth: 1
|
||||
});
|
||||
|
||||
// 在笔的末端添加macd_div值标记
|
||||
if (bi.macd_div && bi.macd_div !== 0) {
|
||||
console.log(`添加元素周期macd_div标记: ${bi.macd_div.toFixed(2)}, 在时间点: ${endTime}`);
|
||||
|
||||
const macdDivLabel = mainChart.addLineSeries({
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
});
|
||||
|
||||
// 确定标记位置
|
||||
const markerPosition = bi.direction === 1 ? 'aboveBar' : 'belowBar';
|
||||
const labelValue = bi.direction === 1 ? endPrice + (endPrice * 0.005) : endPrice - (endPrice * 0.005);
|
||||
const arrayShape = bi.direction === 1 ? 'arrowDown' : 'arrowUp';
|
||||
// 简化标记显示
|
||||
macdDivLabel.setData([
|
||||
{ time: endTime, value: labelValue }
|
||||
]);
|
||||
|
||||
// 使用不同方式添加文本标记
|
||||
const textColor = bi.macd_div > 0 ? '#9c27b0' : '#673ab7';
|
||||
const textSize = Math.min(14, Math.max(10, Math.abs(bi.macd_div) * 2));
|
||||
|
||||
macdDivLabel.setMarkers([
|
||||
{
|
||||
time: endTime,
|
||||
position: markerPosition,
|
||||
color: textColor,
|
||||
shape: arrayShape,
|
||||
text: bi.macd_div.toFixed(2),
|
||||
transparent: true,
|
||||
}
|
||||
]);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('次周期笔处理出错:', e);
|
||||
}
|
||||
@@ -3153,7 +3221,8 @@
|
||||
{ data: 'end_time', render: formatTime },
|
||||
{ data: 'start_price', render: formatPrice },
|
||||
{ data: 'end_price', render: formatPrice },
|
||||
{ data: 'direction', render: formatDirection }
|
||||
{ data: 'direction', render: formatDirection },
|
||||
{ data: 'macd_div', render: formatMacdValue }
|
||||
]
|
||||
});
|
||||
|
||||
@@ -3633,7 +3702,8 @@
|
||||
{ data: 'end_time', render: formatTime },
|
||||
{ data: 'start_price', render: formatPrice },
|
||||
{ data: 'end_price', render: formatPrice },
|
||||
{ data: 'direction', render: formatDirection }
|
||||
{ data: 'direction', render: formatDirection },
|
||||
{ data: 'macd_div', render: formatMacdValue }
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user