A new strategy is added haha
This commit is contained in:
+674
-3
@@ -30,6 +30,7 @@ class ChanKLC():
|
|||||||
self.klc_fx_type = Chan_KLC_FX.UNKNOWN
|
self.klc_fx_type = Chan_KLC_FX.UNKNOWN
|
||||||
self.rsi = klu.rsi
|
self.rsi = klu.rsi
|
||||||
self.volume_ratio = klu.volume_ratio
|
self.volume_ratio = klu.volume_ratio
|
||||||
|
self.macdhist = 0
|
||||||
def set_klc_fx_type(self, klc_fx_type):
|
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'])
|
||||||
self.klc_fx_type = klc_fx_type
|
self.klc_fx_type = klc_fx_type
|
||||||
@@ -43,8 +44,11 @@ class ChanKLC():
|
|||||||
self.volume += self.klus[index].volume
|
self.volume += self.klus[index].volume
|
||||||
self.rsi += self.klus[index].rsi
|
self.rsi += self.klus[index].rsi
|
||||||
self.volume_ratio += self.klus[index].volume_ratio
|
self.volume_ratio += self.klus[index].volume_ratio
|
||||||
|
self.macdhist += self.klus[index].macdhist
|
||||||
self.rsi = self.rsi / len(self.klus)
|
self.rsi = self.rsi / len(self.klus)
|
||||||
self.volume_ratio = self.volume_ratio / len(self.klus)
|
self.volume_ratio = self.volume_ratio / len(self.klus)
|
||||||
|
self.volume = self.volume / len(self.klus)
|
||||||
|
self.macdhist = self.macdhist / len(self.klus)
|
||||||
def set_next(self, klc):
|
def set_next(self, klc):
|
||||||
self.next = klc
|
self.next = klc
|
||||||
def set_pre(self, klc):
|
def set_pre(self, klc):
|
||||||
@@ -122,6 +126,7 @@ class ChanKLC():
|
|||||||
def set_bi(self, bi):
|
def set_bi(self, bi):
|
||||||
self.bi = bi
|
self.bi = bi
|
||||||
self.distance = self.index - bi.start_klc.index
|
self.distance = self.index - bi.start_klc.index
|
||||||
|
#print(self.start_time, self.distance, bi.index, bi.dir)
|
||||||
def cal_klu_features(self):
|
def cal_klu_features(self):
|
||||||
features = dict()
|
features = dict()
|
||||||
feature_sums = dict()
|
feature_sums = dict()
|
||||||
@@ -189,7 +194,7 @@ class ChanKLC():
|
|||||||
|
|
||||||
# K线波动范围
|
# K线波动范围
|
||||||
if self.close != 0: # 避免除以零
|
if self.close != 0: # 避免除以零
|
||||||
features['klc_range'] = (self.high - self.low) / self.close
|
features['klc_range'] = 0 #(self.high - self.low) / self.close
|
||||||
else:
|
else:
|
||||||
features['klc_range'] = 0
|
features['klc_range'] = 0
|
||||||
|
|
||||||
@@ -301,9 +306,9 @@ class ChanKLC():
|
|||||||
features['klc_macd_signal'] = 0
|
features['klc_macd_signal'] = 0
|
||||||
|
|
||||||
if 'klu_macdhist' in klu_features:
|
if 'klu_macdhist' in klu_features:
|
||||||
features['klc_macd_hist'] = klu_features['klu_macdhist']
|
features['klc_macdhist'] = klu_features['klu_macdhist']
|
||||||
else:
|
else:
|
||||||
features['klc_macd_hist'] = 0
|
features['klc_macdhist'] = 0
|
||||||
|
|
||||||
# 成交量变化
|
# 成交量变化
|
||||||
if self.pre:
|
if self.pre:
|
||||||
@@ -459,4 +464,670 @@ class ChanKLC():
|
|||||||
# 从KLU获取其他特征
|
# 从KLU获取其他特征
|
||||||
#features.update(self.cal_klu_features())
|
#features.update(self.cal_klu_features())
|
||||||
|
|
||||||
|
# ===== 3.1 价格形态扩展因子 =====
|
||||||
|
|
||||||
|
# 区间突破强度
|
||||||
|
if self.pre and self.pre.pre:
|
||||||
|
prev_range = self.pre.high - self.pre.low
|
||||||
|
if prev_range > 0:
|
||||||
|
features['klc_breakout_strength'] = (self.close - self.pre.high) / prev_range if self.close > self.pre.high else (self.pre.low - self.close) / prev_range if self.close < self.pre.low else 0
|
||||||
|
else:
|
||||||
|
features['klc_breakout_strength'] = 0
|
||||||
|
else:
|
||||||
|
features['klc_breakout_strength'] = 0
|
||||||
|
|
||||||
|
# 价格动量
|
||||||
|
if self.pre:
|
||||||
|
features['klc_momentum_1'] = self.close - self.pre.close
|
||||||
|
if self.pre.pre:
|
||||||
|
features['klc_momentum_2'] = self.close - self.pre.pre.close
|
||||||
|
else:
|
||||||
|
features['klc_momentum_2'] = 0
|
||||||
|
else:
|
||||||
|
features['klc_momentum_1'] = 0
|
||||||
|
features['klc_momentum_2'] = 0
|
||||||
|
|
||||||
|
# 价格加速度
|
||||||
|
if self.pre and self.pre.pre:
|
||||||
|
prev_change = self.pre.close - self.pre.pre.close
|
||||||
|
curr_change = self.close - self.pre.close
|
||||||
|
features['klc_price_acceleration'] = curr_change - prev_change
|
||||||
|
else:
|
||||||
|
features['klc_price_acceleration'] = 0
|
||||||
|
|
||||||
|
# 相对位置
|
||||||
|
if self.high != self.low:
|
||||||
|
features['klc_relative_position'] = (self.close - self.low) / (self.high - self.low)
|
||||||
|
else:
|
||||||
|
features['klc_relative_position'] = 0.5
|
||||||
|
|
||||||
|
# 价格区间位置 (前N根K线)
|
||||||
|
prev_klcs = []
|
||||||
|
temp = self.pre
|
||||||
|
for _ in range(10): # 前10根K线
|
||||||
|
if temp:
|
||||||
|
prev_klcs.append(temp)
|
||||||
|
temp = temp.pre
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
if prev_klcs:
|
||||||
|
max_high = max([klc.high for klc in prev_klcs]) if prev_klcs else self.high
|
||||||
|
min_low = min([klc.low for klc in prev_klcs]) if prev_klcs else self.low
|
||||||
|
price_range = max_high - min_low
|
||||||
|
|
||||||
|
if price_range > 0:
|
||||||
|
features['klc_range_position'] = (self.close - min_low) / price_range
|
||||||
|
else:
|
||||||
|
features['klc_range_position'] = 0.5
|
||||||
|
else:
|
||||||
|
features['klc_range_position'] = 0.5
|
||||||
|
|
||||||
|
# ===== 3.2 更多技术指标因子 =====
|
||||||
|
|
||||||
|
# MACD趋势
|
||||||
|
if self.pre and 'klc_macdhist' in features:
|
||||||
|
features['klc_macdhist_change'] = features['klc_macdhist'] - self.pre.macdhist
|
||||||
|
else:
|
||||||
|
features['klc_macdhist_change'] = 0
|
||||||
|
|
||||||
|
# RSI趋势
|
||||||
|
if self.pre and 'klc_rsi' in features:
|
||||||
|
features['klc_rsi_change'] = features['klc_rsi'] - self.pre.rsi
|
||||||
|
else:
|
||||||
|
features['klc_rsi_change'] = 0
|
||||||
|
|
||||||
|
# RSI超买超卖
|
||||||
|
if 'klc_rsi' in features:
|
||||||
|
features['klc_rsi_overbought'] = 1 if features['klc_rsi'] > 70 else 0
|
||||||
|
features['klc_rsi_oversold'] = 1 if features['klc_rsi'] < 30 else 0
|
||||||
|
else:
|
||||||
|
features['klc_rsi_overbought'] = 0
|
||||||
|
features['klc_rsi_oversold'] = 0
|
||||||
|
|
||||||
|
# 布林带位置 (如果可从KLU获取)
|
||||||
|
if 'klu_upper_band' in klu_features and 'klu_lower_band' in klu_features:
|
||||||
|
upper_band = klu_features['klu_upper_band']
|
||||||
|
lower_band = klu_features['klu_lower_band']
|
||||||
|
middle_band = klu_features['klu_middle_band'] if 'klu_middle_band' in klu_features else (upper_band + lower_band) / 2
|
||||||
|
|
||||||
|
band_width = upper_band - lower_band
|
||||||
|
|
||||||
|
if band_width > 0:
|
||||||
|
features['klc_bollinger_position'] = (self.close - lower_band) / band_width
|
||||||
|
else:
|
||||||
|
features['klc_bollinger_position'] = 0.5
|
||||||
|
|
||||||
|
features['klc_bollinger_width'] = band_width / middle_band if middle_band > 0 else 0
|
||||||
|
features['klc_upper_band_touch'] = 1 if self.high >= upper_band else 0
|
||||||
|
features['klc_lower_band_touch'] = 1 if self.low <= lower_band else 0
|
||||||
|
else:
|
||||||
|
features['klc_bollinger_position'] = 0.5
|
||||||
|
features['klc_bollinger_width'] = 0
|
||||||
|
features['klc_upper_band_touch'] = 0
|
||||||
|
features['klc_lower_band_touch'] = 0
|
||||||
|
|
||||||
|
# 量价关系
|
||||||
|
if self.pre:
|
||||||
|
price_change = self.close - self.pre.close
|
||||||
|
if price_change != 0:
|
||||||
|
features['klc_volume_price_ratio'] = self.volume / abs(price_change)
|
||||||
|
else:
|
||||||
|
features['klc_volume_price_ratio'] = 0
|
||||||
|
else:
|
||||||
|
features['klc_volume_price_ratio'] = 0
|
||||||
|
|
||||||
|
# ===== 3.3 波动性因子 =====
|
||||||
|
|
||||||
|
# 真实波动幅度 (True Range)
|
||||||
|
if self.pre:
|
||||||
|
tr1 = self.high - self.low
|
||||||
|
tr2 = abs(self.high - self.pre.close)
|
||||||
|
tr3 = abs(self.low - self.pre.close)
|
||||||
|
features['klc_true_range'] = max(tr1, tr2, tr3)
|
||||||
|
else:
|
||||||
|
features['klc_true_range'] = self.high - self.low
|
||||||
|
|
||||||
|
# 归一化真实波动幅度
|
||||||
|
if self.pre and self.pre.close > 0:
|
||||||
|
features['klc_normalized_tr'] = features['klc_true_range'] / self.pre.close
|
||||||
|
else:
|
||||||
|
features['klc_normalized_tr'] = 0
|
||||||
|
|
||||||
|
# 滑动窗口波动率
|
||||||
|
if prev_klcs:
|
||||||
|
tr_values = []
|
||||||
|
|
||||||
|
for i in range(len(prev_klcs)):
|
||||||
|
if i == 0:
|
||||||
|
tr = max(prev_klcs[i].high - prev_klcs[i].low,
|
||||||
|
abs(prev_klcs[i].high - self.close),
|
||||||
|
abs(prev_klcs[i].low - self.close))
|
||||||
|
else:
|
||||||
|
tr = max(prev_klcs[i].high - prev_klcs[i].low,
|
||||||
|
abs(prev_klcs[i].high - prev_klcs[i-1].close),
|
||||||
|
abs(prev_klcs[i].low - prev_klcs[i-1].close))
|
||||||
|
tr_values.append(tr)
|
||||||
|
|
||||||
|
if tr_values:
|
||||||
|
import numpy as np
|
||||||
|
# ATR (Average True Range)
|
||||||
|
features['klc_atr'] = np.mean(tr_values)
|
||||||
|
if self.close > 0:
|
||||||
|
features['klc_atr_percent'] = features['klc_atr'] / self.close
|
||||||
|
else:
|
||||||
|
features['klc_atr_percent'] = 0
|
||||||
|
|
||||||
|
# 高低点波动
|
||||||
|
if len(prev_klcs) >= 5:
|
||||||
|
highs = [klc.high for klc in prev_klcs[:5]]
|
||||||
|
lows = [klc.low for klc in prev_klcs[:5]]
|
||||||
|
|
||||||
|
max_high = max(highs)
|
||||||
|
min_low = min(lows)
|
||||||
|
|
||||||
|
features['klc_high_volatility'] = np.std(highs) / np.mean(highs) if np.mean(highs) > 0 else 0
|
||||||
|
features['klc_low_volatility'] = np.std(lows) / np.mean(lows) if np.mean(lows) > 0 else 0
|
||||||
|
features['klc_price_range'] = (max_high - min_low) / min_low if min_low > 0 else 0
|
||||||
|
else:
|
||||||
|
features['klc_high_volatility'] = 0
|
||||||
|
features['klc_low_volatility'] = 0
|
||||||
|
features['klc_price_range'] = 0
|
||||||
|
else:
|
||||||
|
features['klc_atr'] = 0
|
||||||
|
features['klc_atr_percent'] = 0
|
||||||
|
features['klc_high_volatility'] = 0
|
||||||
|
features['klc_low_volatility'] = 0
|
||||||
|
features['klc_price_range'] = 0
|
||||||
|
else:
|
||||||
|
features['klc_atr'] = 0
|
||||||
|
features['klc_atr_percent'] = 0
|
||||||
|
features['klc_high_volatility'] = 0
|
||||||
|
features['klc_low_volatility'] = 0
|
||||||
|
features['klc_price_range'] = 0
|
||||||
|
|
||||||
|
# ===== 3.4 趋势强度因子 =====
|
||||||
|
|
||||||
|
# 方向移动指标
|
||||||
|
if self.pre:
|
||||||
|
# 上升动量和下降动量
|
||||||
|
up_move = self.high - self.pre.high
|
||||||
|
down_move = self.pre.low - self.low
|
||||||
|
|
||||||
|
features['klc_plus_dm'] = up_move if up_move > down_move and up_move > 0 else 0
|
||||||
|
features['klc_minus_dm'] = down_move if down_move > up_move and down_move > 0 else 0
|
||||||
|
|
||||||
|
# 方向指数
|
||||||
|
if features['klc_atr'] > 0:
|
||||||
|
features['klc_plus_di'] = 100 * features['klc_plus_dm'] / features['klc_atr']
|
||||||
|
features['klc_minus_di'] = 100 * features['klc_minus_dm'] / features['klc_atr']
|
||||||
|
else:
|
||||||
|
features['klc_plus_di'] = 0
|
||||||
|
features['klc_minus_di'] = 0
|
||||||
|
|
||||||
|
# 方向指数差
|
||||||
|
features['klc_dx'] = 100 * abs(features['klc_plus_di'] - features['klc_minus_di']) / (features['klc_plus_di'] + features['klc_minus_di']) if (features['klc_plus_di'] + features['klc_minus_di']) > 0 else 0
|
||||||
|
else:
|
||||||
|
features['klc_plus_dm'] = 0
|
||||||
|
features['klc_minus_dm'] = 0
|
||||||
|
features['klc_plus_di'] = 0
|
||||||
|
features['klc_minus_di'] = 0
|
||||||
|
features['klc_dx'] = 0
|
||||||
|
|
||||||
|
# 价格趋势强度
|
||||||
|
if prev_klcs and len(prev_klcs) >= 5:
|
||||||
|
import numpy as np
|
||||||
|
prices = [self.close] + [klc.close for klc in prev_klcs[:5]]
|
||||||
|
x = np.arange(len(prices))
|
||||||
|
|
||||||
|
# 线性回归
|
||||||
|
slope, intercept = np.polyfit(x, prices, 1)
|
||||||
|
|
||||||
|
# 趋势线拟合度 (R^2)
|
||||||
|
y_pred = slope * x + intercept
|
||||||
|
ss_total = np.sum((prices - np.mean(prices)) ** 2)
|
||||||
|
ss_residual = np.sum((prices - y_pred) ** 2)
|
||||||
|
|
||||||
|
if ss_total > 0:
|
||||||
|
features['klc_trend_r2'] = 1 - (ss_residual / ss_total)
|
||||||
|
else:
|
||||||
|
features['klc_trend_r2'] = 0
|
||||||
|
|
||||||
|
# 趋势线斜率
|
||||||
|
features['klc_trend_slope_norm'] = slope / np.mean(prices) if np.mean(prices) > 0 else 0
|
||||||
|
|
||||||
|
# 价格与趋势线的距离
|
||||||
|
current_trend_value = slope * 0 + intercept # x=0 表示当前K线在预测线上的值
|
||||||
|
if current_trend_value > 0:
|
||||||
|
features['klc_trend_distance'] = (self.close - current_trend_value) / current_trend_value
|
||||||
|
else:
|
||||||
|
features['klc_trend_distance'] = 0
|
||||||
|
else:
|
||||||
|
features['klc_trend_r2'] = 0
|
||||||
|
features['klc_trend_slope_norm'] = 0
|
||||||
|
features['klc_trend_distance'] = 0
|
||||||
|
|
||||||
|
# ===== 3.5 支撑与阻力因子 =====
|
||||||
|
|
||||||
|
# 前N根K线的支撑和阻力
|
||||||
|
if prev_klcs and len(prev_klcs) >= 5:
|
||||||
|
highs = [klc.high for klc in prev_klcs[:5]]
|
||||||
|
lows = [klc.low for klc in prev_klcs[:5]]
|
||||||
|
|
||||||
|
# 简单支撑位 (前5根K线最低点)
|
||||||
|
support = min(lows)
|
||||||
|
# 简单阻力位 (前5根K线最高点)
|
||||||
|
resistance = max(highs)
|
||||||
|
|
||||||
|
# 与支撑阻力的距离
|
||||||
|
if support > 0:
|
||||||
|
features['klc_distance_to_support'] = (self.close - support) / support
|
||||||
|
else:
|
||||||
|
features['klc_distance_to_support'] = 0
|
||||||
|
|
||||||
|
if resistance > 0:
|
||||||
|
features['klc_distance_to_resistance'] = (resistance - self.close) / resistance
|
||||||
|
else:
|
||||||
|
features['klc_distance_to_resistance'] = 0
|
||||||
|
|
||||||
|
# 支撑阻力突破
|
||||||
|
features['klc_breaks_support'] = 1 if self.low < support else 0
|
||||||
|
features['klc_breaks_resistance'] = 1 if self.high > resistance else 0
|
||||||
|
|
||||||
|
# 支撑阻力区间位置
|
||||||
|
if resistance > support:
|
||||||
|
features['klc_sr_position'] = (self.close - support) / (resistance - support)
|
||||||
|
else:
|
||||||
|
features['klc_sr_position'] = 0.5
|
||||||
|
else:
|
||||||
|
features['klc_distance_to_support'] = 0
|
||||||
|
features['klc_distance_to_resistance'] = 0
|
||||||
|
features['klc_breaks_support'] = 0
|
||||||
|
features['klc_breaks_resistance'] = 0
|
||||||
|
features['klc_sr_position'] = 0.5
|
||||||
|
|
||||||
|
# ===== 3.6 量价关系扩展因子 =====
|
||||||
|
|
||||||
|
# 价格与成交量的相关性
|
||||||
|
if prev_klcs and len(prev_klcs) >= 5:
|
||||||
|
import numpy as np
|
||||||
|
prices = [self.close] + [klc.close for klc in prev_klcs[:5]]
|
||||||
|
volumes = [self.volume] + [klc.volume for klc in prev_klcs[:5]]
|
||||||
|
|
||||||
|
# 计算相关系数
|
||||||
|
if len(prices) > 1 and np.std(prices) > 0 and np.std(volumes) > 0:
|
||||||
|
price_mean = np.mean(prices)
|
||||||
|
volume_mean = np.mean(volumes)
|
||||||
|
|
||||||
|
numerator = np.sum((prices - price_mean) * (volumes - volume_mean))
|
||||||
|
denominator = np.sqrt(np.sum((prices - price_mean) ** 2) * np.sum((volumes - volume_mean) ** 2))
|
||||||
|
|
||||||
|
if denominator > 0:
|
||||||
|
features['klc_price_volume_corr'] = numerator / denominator
|
||||||
|
else:
|
||||||
|
features['klc_price_volume_corr'] = 0
|
||||||
|
else:
|
||||||
|
features['klc_price_volume_corr'] = 0
|
||||||
|
|
||||||
|
# 价格上涨时的平均成交量
|
||||||
|
up_prices = []
|
||||||
|
up_volumes = []
|
||||||
|
|
||||||
|
# 价格下跌时的平均成交量
|
||||||
|
down_prices = []
|
||||||
|
down_volumes = []
|
||||||
|
|
||||||
|
for i in range(len(prev_klcs)):
|
||||||
|
if i < len(prev_klcs) - 1:
|
||||||
|
if prev_klcs[i].close > prev_klcs[i+1].close:
|
||||||
|
up_prices.append(prev_klcs[i].close)
|
||||||
|
up_volumes.append(prev_klcs[i].volume)
|
||||||
|
else:
|
||||||
|
down_prices.append(prev_klcs[i].close)
|
||||||
|
down_volumes.append(prev_klcs[i].volume)
|
||||||
|
|
||||||
|
features['klc_up_volume_avg'] = np.mean(up_volumes) if up_volumes else 0
|
||||||
|
features['klc_down_volume_avg'] = np.mean(down_volumes) if down_volumes else 0
|
||||||
|
|
||||||
|
if features['klc_down_volume_avg'] > 0:
|
||||||
|
features['klc_volume_ratio_up_down'] = features['klc_up_volume_avg'] / features['klc_down_volume_avg']
|
||||||
|
else:
|
||||||
|
features['klc_volume_ratio_up_down'] = 1
|
||||||
|
else:
|
||||||
|
features['klc_price_volume_corr'] = 0
|
||||||
|
features['klc_up_volume_avg'] = 0
|
||||||
|
features['klc_down_volume_avg'] = 0
|
||||||
|
features['klc_volume_ratio_up_down'] = 1
|
||||||
|
|
||||||
|
# 成交量变化率
|
||||||
|
if self.pre:
|
||||||
|
if self.pre.volume > 0:
|
||||||
|
features['klc_volume_change'] = (self.volume - self.pre.volume) / self.pre.volume
|
||||||
|
else:
|
||||||
|
features['klc_volume_change'] = 0
|
||||||
|
else:
|
||||||
|
features['klc_volume_change'] = 0
|
||||||
|
|
||||||
|
# 量能扩散
|
||||||
|
if prev_klcs and len(prev_klcs) >= 5:
|
||||||
|
avg_volume = np.mean([klc.volume for klc in prev_klcs[:5]])
|
||||||
|
if avg_volume > 0:
|
||||||
|
features['klc_volume_expansion'] = self.volume / avg_volume
|
||||||
|
else:
|
||||||
|
features['klc_volume_expansion'] = 1
|
||||||
|
else:
|
||||||
|
features['klc_volume_expansion'] = 1
|
||||||
|
|
||||||
|
# ===== 3.7 K线时序模式因子 =====
|
||||||
|
|
||||||
|
# 连续上涨/下跌计数
|
||||||
|
up_count = 0
|
||||||
|
down_count = 0
|
||||||
|
|
||||||
|
if prev_klcs:
|
||||||
|
temp = self
|
||||||
|
last_close = temp.close
|
||||||
|
|
||||||
|
for klc in prev_klcs:
|
||||||
|
if klc.close < last_close:
|
||||||
|
up_count += 1
|
||||||
|
down_count = 0
|
||||||
|
elif klc.close > last_close:
|
||||||
|
down_count += 1
|
||||||
|
up_count = 0
|
||||||
|
last_close = klc.close
|
||||||
|
|
||||||
|
features['klc_consecutive_up'] = up_count
|
||||||
|
features['klc_consecutive_down'] = down_count
|
||||||
|
else:
|
||||||
|
features['klc_consecutive_up'] = 0
|
||||||
|
features['klc_consecutive_down'] = 0
|
||||||
|
|
||||||
|
# 跳空缺口
|
||||||
|
if self.pre:
|
||||||
|
features['klc_gap_up'] = self.low - self.pre.high if self.low > self.pre.high else 0
|
||||||
|
features['klc_gap_down'] = self.pre.low - self.high if self.high < self.pre.low else 0
|
||||||
|
|
||||||
|
# 归一化缺口大小
|
||||||
|
if self.pre.close > 0:
|
||||||
|
features['klc_gap_up_pct'] = features['klc_gap_up'] / self.pre.close
|
||||||
|
features['klc_gap_down_pct'] = features['klc_gap_down'] / self.pre.close
|
||||||
|
else:
|
||||||
|
features['klc_gap_up_pct'] = 0
|
||||||
|
features['klc_gap_down_pct'] = 0
|
||||||
|
else:
|
||||||
|
features['klc_gap_up'] = 0
|
||||||
|
features['klc_gap_down'] = 0
|
||||||
|
features['klc_gap_up_pct'] = 0
|
||||||
|
features['klc_gap_down_pct'] = 0
|
||||||
|
|
||||||
|
# 价格回撤
|
||||||
|
if prev_klcs:
|
||||||
|
max_price = self.close
|
||||||
|
min_price = self.close
|
||||||
|
|
||||||
|
for klc in prev_klcs[:5]:
|
||||||
|
max_price = max(max_price, klc.close)
|
||||||
|
min_price = min(min_price, klc.close)
|
||||||
|
|
||||||
|
if max_price > 0:
|
||||||
|
features['klc_drawdown'] = (max_price - self.close) / max_price
|
||||||
|
else:
|
||||||
|
features['klc_drawdown'] = 0
|
||||||
|
|
||||||
|
if min_price > 0:
|
||||||
|
features['klc_pullback'] = (self.close - min_price) / min_price
|
||||||
|
else:
|
||||||
|
features['klc_pullback'] = 0
|
||||||
|
else:
|
||||||
|
features['klc_drawdown'] = 0
|
||||||
|
features['klc_pullback'] = 0
|
||||||
|
|
||||||
|
# ===== 3.8 复杂形态识别因子 =====
|
||||||
|
|
||||||
|
# 双顶/双底形态
|
||||||
|
if self.pre and self.pre.pre and self.pre.pre.pre and self.pre.pre.pre.pre:
|
||||||
|
p5 = self.pre.pre.pre.pre
|
||||||
|
p4 = self.pre.pre.pre
|
||||||
|
p3 = self.pre.pre
|
||||||
|
p2 = self.pre
|
||||||
|
p1 = self
|
||||||
|
|
||||||
|
# 双顶检测 (M形)
|
||||||
|
double_top = (p5.high < p4.high and p4.high > p3.high and
|
||||||
|
p3.high < p2.high and p2.high > p1.high and
|
||||||
|
abs(p4.high - p2.high) / p4.high < 0.03) # 两个顶的高度接近
|
||||||
|
|
||||||
|
# 双底检测 (W形)
|
||||||
|
double_bottom = (p5.low > p4.low and p4.low < p3.low and
|
||||||
|
p3.low > p2.low and p2.low < p1.low and
|
||||||
|
abs(p4.low - p2.low) / p4.low < 0.03) # 两个底的低点接近
|
||||||
|
|
||||||
|
features['klc_double_top'] = 1 if double_top else 0
|
||||||
|
features['klc_double_bottom'] = 1 if double_bottom else 0
|
||||||
|
else:
|
||||||
|
features['klc_double_top'] = 0
|
||||||
|
features['klc_double_bottom'] = 0
|
||||||
|
|
||||||
|
# 头肩顶/底形态
|
||||||
|
if self.pre and self.pre.pre and self.pre.pre.pre and self.pre.pre.pre.pre and self.pre.pre.pre.pre.pre:
|
||||||
|
p7 = self.pre.pre.pre.pre.pre
|
||||||
|
p6 = self.pre.pre.pre.pre
|
||||||
|
p5 = self.pre.pre.pre
|
||||||
|
p4 = self.pre.pre
|
||||||
|
p3 = self.pre
|
||||||
|
p2 = self
|
||||||
|
|
||||||
|
# 头肩顶 (左肩-头-右肩)
|
||||||
|
head_shoulders_top = (p7.high < p6.high and p6.high > p5.high and
|
||||||
|
p5.high < p4.high and p4.high > p3.high and
|
||||||
|
p3.high < p2.high and
|
||||||
|
abs(p6.high - p2.high) / p6.high < 0.05 and # 左肩和右肩高度接近
|
||||||
|
p4.high > p6.high and p4.high > p2.high) # 头部高于肩部
|
||||||
|
|
||||||
|
# 头肩底 (左肩-头-右肩)
|
||||||
|
head_shoulders_bottom = (p7.low > p6.low and p6.low < p5.low and
|
||||||
|
p5.low > p4.low and p4.low < p3.low and
|
||||||
|
p3.low > p2.low and
|
||||||
|
abs(p6.low - p2.low) / p6.low < 0.05 and # 左肩和右肩低点接近
|
||||||
|
p4.low < p6.low and p4.low < p2.low) # 头部低于肩部
|
||||||
|
|
||||||
|
features['klc_head_shoulders_top'] = 1 if head_shoulders_top else 0
|
||||||
|
features['klc_head_shoulders_bottom'] = 1 if head_shoulders_bottom else 0
|
||||||
|
else:
|
||||||
|
features['klc_head_shoulders_top'] = 0
|
||||||
|
features['klc_head_shoulders_bottom'] = 0
|
||||||
|
|
||||||
|
# 旗形/三角形
|
||||||
|
if prev_klcs and len(prev_klcs) >= 5:
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
highs = [self.high] + [klc.high for klc in prev_klcs[:5]]
|
||||||
|
lows = [self.low] + [klc.low for klc in prev_klcs[:5]]
|
||||||
|
|
||||||
|
# 计算高点趋势线斜率
|
||||||
|
x = np.arange(len(highs))
|
||||||
|
high_slope, _ = np.polyfit(x, highs, 1)
|
||||||
|
|
||||||
|
# 计算低点趋势线斜率
|
||||||
|
low_slope, _ = np.polyfit(x, lows, 1)
|
||||||
|
|
||||||
|
# 旗形: 高点和低点趋势线平行且方向相同
|
||||||
|
if abs(high_slope - low_slope) / (abs(high_slope) + 1e-10) < 0.2:
|
||||||
|
features['klc_flag_pattern'] = 1
|
||||||
|
else:
|
||||||
|
features['klc_flag_pattern'] = 0
|
||||||
|
|
||||||
|
# 上升三角形: 高点趋势线水平,低点趋势线向上
|
||||||
|
if abs(high_slope) < 0.01 and low_slope > 0.01:
|
||||||
|
features['klc_ascending_triangle'] = 1
|
||||||
|
else:
|
||||||
|
features['klc_ascending_triangle'] = 0
|
||||||
|
|
||||||
|
# 下降三角形: 高点趋势线向下,低点趋势线水平
|
||||||
|
if high_slope < -0.01 and abs(low_slope) < 0.01:
|
||||||
|
features['klc_descending_triangle'] = 1
|
||||||
|
else:
|
||||||
|
features['klc_descending_triangle'] = 0
|
||||||
|
|
||||||
|
# 对称三角形: 高点趋势线向下,低点趋势线向上
|
||||||
|
if high_slope < -0.01 and low_slope > 0.01:
|
||||||
|
features['klc_symmetric_triangle'] = 1
|
||||||
|
else:
|
||||||
|
features['klc_symmetric_triangle'] = 0
|
||||||
|
else:
|
||||||
|
features['klc_flag_pattern'] = 0
|
||||||
|
features['klc_ascending_triangle'] = 0
|
||||||
|
features['klc_descending_triangle'] = 0
|
||||||
|
features['klc_symmetric_triangle'] = 0
|
||||||
|
|
||||||
|
# ===== 3.9 微观结构因子 =====
|
||||||
|
|
||||||
|
# 价格动量加速度
|
||||||
|
if self.pre and self.pre.pre and self.pre.pre.pre:
|
||||||
|
mom1 = self.close - self.pre.close
|
||||||
|
mom2 = self.pre.close - self.pre.pre.close
|
||||||
|
mom3 = self.pre.pre.close - self.pre.pre.pre.close
|
||||||
|
|
||||||
|
# 一阶动量变化
|
||||||
|
features['klc_mom_change_1'] = mom1 - mom2
|
||||||
|
|
||||||
|
# 二阶动量变化
|
||||||
|
features['klc_mom_change_2'] = (mom1 - mom2) - (mom2 - mom3)
|
||||||
|
|
||||||
|
# 动量方向变化
|
||||||
|
features['klc_mom_direction_change'] = 1 if (mom1 > 0 and mom2 < 0) or (mom1 < 0 and mom2 > 0) else 0
|
||||||
|
else:
|
||||||
|
features['klc_mom_change_1'] = 0
|
||||||
|
features['klc_mom_change_2'] = 0
|
||||||
|
features['klc_mom_direction_change'] = 0
|
||||||
|
|
||||||
|
# 微观价格结构分析
|
||||||
|
if self.pre:
|
||||||
|
# K线重叠程度
|
||||||
|
overlap_range = min(self.high, self.pre.high) - max(self.low, self.pre.low)
|
||||||
|
total_range = max(self.high, self.pre.high) - min(self.low, self.pre.low)
|
||||||
|
|
||||||
|
if total_range > 0:
|
||||||
|
features['klc_overlap_ratio'] = max(0, overlap_range) / total_range
|
||||||
|
else:
|
||||||
|
features['klc_overlap_ratio'] = 0
|
||||||
|
|
||||||
|
# 收盘价在当前K线的相对位置
|
||||||
|
if self.high > self.low:
|
||||||
|
features['klc_close_position_inbar'] = (self.close - self.low) / (self.high - self.low)
|
||||||
|
else:
|
||||||
|
features['klc_close_position_inbar'] = 0.5
|
||||||
|
|
||||||
|
# 当前K线相对于前一根K线的位置
|
||||||
|
if self.pre.high > self.pre.low:
|
||||||
|
features['klc_rel_position_to_prev'] = (self.close - self.pre.low) / (self.pre.high - self.pre.low)
|
||||||
|
else:
|
||||||
|
features['klc_rel_position_to_prev'] = 0.5
|
||||||
|
else:
|
||||||
|
features['klc_overlap_ratio'] = 0
|
||||||
|
features['klc_close_position_inbar'] = 0.5
|
||||||
|
features['klc_rel_position_to_prev'] = 0.5
|
||||||
|
|
||||||
|
# 价格变化率序列
|
||||||
|
if prev_klcs and len(prev_klcs) >= 3:
|
||||||
|
ret1 = self.close / prev_klcs[0].close - 1 if prev_klcs[0].close > 0 else 0
|
||||||
|
ret2 = prev_klcs[0].close / prev_klcs[1].close - 1 if prev_klcs[1].close > 0 else 0
|
||||||
|
ret3 = prev_klcs[1].close / prev_klcs[2].close - 1 if prev_klcs[2].close > 0 else 0
|
||||||
|
|
||||||
|
features['klc_return_1'] = ret1
|
||||||
|
features['klc_return_2'] = ret2
|
||||||
|
features['klc_return_3'] = ret3
|
||||||
|
|
||||||
|
# 收益率加速度
|
||||||
|
features['klc_return_accel_1'] = ret1 - ret2
|
||||||
|
features['klc_return_accel_2'] = (ret1 - ret2) - (ret2 - ret3)
|
||||||
|
else:
|
||||||
|
features['klc_return_1'] = 0
|
||||||
|
features['klc_return_2'] = 0
|
||||||
|
features['klc_return_3'] = 0
|
||||||
|
features['klc_return_accel_1'] = 0
|
||||||
|
features['klc_return_accel_2'] = 0
|
||||||
|
|
||||||
|
# ===== 3.10 综合形态因子 =====
|
||||||
|
|
||||||
|
# 能量比率 (K线实体与影线比例)
|
||||||
|
body_size = abs(self.close - self.open)
|
||||||
|
if self.high > self.low:
|
||||||
|
upper_shadow = self.high - max(self.open, self.close)
|
||||||
|
lower_shadow = min(self.open, self.close) - self.low
|
||||||
|
|
||||||
|
features['klc_upper_shadow_ratio'] = upper_shadow / (self.high - self.low)
|
||||||
|
features['klc_lower_shadow_ratio'] = lower_shadow / (self.high - self.low)
|
||||||
|
features['klc_body_to_range_ratio'] = body_size / (self.high - self.low)
|
||||||
|
else:
|
||||||
|
features['klc_upper_shadow_ratio'] = 0
|
||||||
|
features['klc_lower_shadow_ratio'] = 0
|
||||||
|
features['klc_body_to_range_ratio'] = 1
|
||||||
|
|
||||||
|
# K线平衡点
|
||||||
|
features['klc_balance_point'] = (self.high + self.low + self.close) / 3
|
||||||
|
|
||||||
|
# 与平衡点的距离
|
||||||
|
if features['klc_balance_point'] > 0:
|
||||||
|
features['klc_distance_to_balance'] = (self.close - features['klc_balance_point']) / features['klc_balance_point']
|
||||||
|
else:
|
||||||
|
features['klc_distance_to_balance'] = 0
|
||||||
|
|
||||||
|
# 波动性和趋势组合因子
|
||||||
|
if 'klc_volatility' in features and 'klc_trend_slope_norm' in features:
|
||||||
|
features['klc_volatility_trend_ratio'] = features['klc_volatility'] / (abs(features['klc_trend_slope_norm']) + 1e-10)
|
||||||
|
else:
|
||||||
|
features['klc_volatility_trend_ratio'] = 0
|
||||||
|
|
||||||
|
# K线逆转形态
|
||||||
|
if self.pre:
|
||||||
|
# 看涨逆转 (前一根阴线,当前阳线,且当前收盘高于前一根中点)
|
||||||
|
bullish_reversal = (self.pre.close < self.pre.open and # 前一根阴线
|
||||||
|
self.close > self.open and # 当前阳线
|
||||||
|
self.close > (self.pre.high + self.pre.low) / 2) # 收盘价高于前一根中点
|
||||||
|
|
||||||
|
# 看跌逆转 (前一根阳线,当前阴线,且当前收盘低于前一根中点)
|
||||||
|
bearish_reversal = (self.pre.close > self.pre.open and # 前一根阳线
|
||||||
|
self.close < self.open and # 当前阴线
|
||||||
|
self.close < (self.pre.high + self.pre.low) / 2) # 收盘价低于前一根中点
|
||||||
|
|
||||||
|
features['klc_bullish_reversal'] = 1 if bullish_reversal else 0
|
||||||
|
features['klc_bearish_reversal'] = 1 if bearish_reversal else 0
|
||||||
|
else:
|
||||||
|
features['klc_bullish_reversal'] = 0
|
||||||
|
features['klc_bearish_reversal'] = 0
|
||||||
|
|
||||||
|
# 特殊K线形态
|
||||||
|
# 大阳线/大阴线
|
||||||
|
avg_body = 0
|
||||||
|
if prev_klcs and len(prev_klcs) >= 5:
|
||||||
|
bodies = [abs(klc.close - klc.open) for klc in prev_klcs[:5]]
|
||||||
|
avg_body = sum(bodies) / len(bodies) if bodies else 0
|
||||||
|
|
||||||
|
if avg_body > 0:
|
||||||
|
features['klc_large_candle'] = body_size / avg_body
|
||||||
|
else:
|
||||||
|
features['klc_large_candle'] = 1
|
||||||
|
|
||||||
|
# 长上影线/长下影线
|
||||||
|
if self.high > self.low:
|
||||||
|
upper_shadow_ratio = (self.high - max(self.open, self.close)) / (self.high - self.low)
|
||||||
|
lower_shadow_ratio = (min(self.open, self.close) - self.low) / (self.high - self.low)
|
||||||
|
|
||||||
|
features['klc_long_upper_shadow'] = 1 if upper_shadow_ratio > 0.6 else 0
|
||||||
|
features['klc_long_lower_shadow'] = 1 if lower_shadow_ratio > 0.6 else 0
|
||||||
|
else:
|
||||||
|
features['klc_long_upper_shadow'] = 0
|
||||||
|
features['klc_long_lower_shadow'] = 0
|
||||||
|
|
||||||
|
# 星线形态 (当前K线实体小,且与前一根K线有缺口)
|
||||||
|
if self.pre and (self.high - self.low) > 0:
|
||||||
|
small_body = body_size / (self.high - self.low) < 0.3
|
||||||
|
gap_with_prev = (min(self.open, self.close) > self.pre.close) if self.pre.close > self.pre.open else (max(self.open, self.close) < self.pre.close)
|
||||||
|
|
||||||
|
features['klc_star_pattern'] = 1 if small_body and gap_with_prev else 0
|
||||||
|
else:
|
||||||
|
features['klc_star_pattern'] = 0
|
||||||
|
|
||||||
return features
|
return features
|
||||||
+31
-14
@@ -88,21 +88,38 @@ class ChanLun():
|
|||||||
df['macdhist'] = macd['macdhist']
|
df['macdhist'] = macd['macdhist']
|
||||||
return df
|
return df
|
||||||
def plot_dataframe(self, dataframe):
|
def plot_dataframe(self, dataframe):
|
||||||
return self.get_klu_list(dataframe)
|
|
||||||
klc_list = self.get_klc_list(dataframe)
|
klc_list = self.get_klc_list(dataframe)
|
||||||
bi_list= self.cal_bi_list(klc_list)
|
bi_list= self.cal_bi_list(klc_list)
|
||||||
seg_list = self.get_seg_list(bi_list)
|
def get_klc_state_list(self, dataframe):
|
||||||
zs_list = self.calculate_zs(bi_list, seg_list)
|
klc_list = self.get_klc_list(dataframe)
|
||||||
#bi_macd_div_list = self.get_bi_macd_div_list(bi_list, dataframe)
|
bi_list= self.cal_bi_list(klc_list)
|
||||||
#seg_macd_div_list = self.get_seg_macd_div_list(seg_list, dataframe)
|
state_list = []
|
||||||
#buy_sell_points = self.identify_buy_sell_points(bi_list, seg_list, zs_list, dataframe)
|
if len(klc_list) > 0:
|
||||||
#divergence_points = self.identify_macd_divergence(dataframe, bi_list)
|
klc_index = 0
|
||||||
#self.print_bi(bi_list)
|
for index in range(0, len(dataframe)):
|
||||||
#self.print_seg(seg_list)
|
if klc_index == len(klc_list):
|
||||||
#self.print_zs(zs_list)
|
klc_index = len(klc_list) - 1
|
||||||
#self.print_bsp_list(bsp_list)
|
klc = klc_list[klc_index]
|
||||||
#self.plot(dataframe, bi_list, seg_list, zs_list, buy_sell_points, divergence_points)
|
if klc.end_klu:
|
||||||
#return plt.gcf()
|
if klc.end_klu.idx == index:
|
||||||
|
klc_index += 1
|
||||||
|
features = klc.get_feature_data()
|
||||||
|
if (klc.klc_fx_type == Chan_KLC_FX.TOP1 or klc.klc_fx_type == Chan_KLC_FX.TOP2) and klc.bi.dir == Chan_BI_DIR.UP:
|
||||||
|
state_list.append("10")
|
||||||
|
#print(klc.start_time, klc.klc_fx_type)
|
||||||
|
elif (klc.klc_fx_type == Chan_KLC_FX.BOTTOM1 or klc.klc_fx_type == Chan_KLC_FX.BOTTOM2) and klc.bi.dir == Chan_BI_DIR.DOWN:
|
||||||
|
state_list.append("-10")
|
||||||
|
#print(klc.end_time, klc.klc_fx_type, klc.bi.start_time, klc.bi.dir)
|
||||||
|
else:
|
||||||
|
state_list.append("00")
|
||||||
|
else:
|
||||||
|
state_list.append("00")
|
||||||
|
else:
|
||||||
|
state_list.append("00")
|
||||||
|
else:
|
||||||
|
for index in range(0, len(dataframe)):
|
||||||
|
state_list.append("00")
|
||||||
|
return state_list
|
||||||
def print_data(self, dataframe):
|
def print_data(self, dataframe):
|
||||||
klc_list = self.get_klc_list(dataframe)
|
klc_list = self.get_klc_list(dataframe)
|
||||||
bi_list = self.cal_bi_list(klc_list)
|
bi_list = self.cal_bi_list(klc_list)
|
||||||
@@ -658,7 +675,7 @@ class ChanLun():
|
|||||||
#print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Bottom Change 1")
|
#print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Bottom Change 1")
|
||||||
klc.set_klc_fx_type(Chan_KLC_FX.TOP2)
|
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")
|
#print(klc.start_time, last_bi.start_klc.start_time, "New TOP Found reset last bi")
|
||||||
klc.set_state("10")
|
#klc.set_state("10")
|
||||||
#print(klc.start_time, klc.fx, "笔卖点Sell 1")
|
#print(klc.start_time, klc.fx, "笔卖点Sell 1")
|
||||||
klc.set_klc_fx_type(Chan_KLC_FX.TOP2)
|
klc.set_klc_fx_type(Chan_KLC_FX.TOP2)
|
||||||
bi_list[-1].add_klc(klc)
|
bi_list[-1].add_klc(klc)
|
||||||
|
|||||||
+14
-8
@@ -62,15 +62,15 @@ class ChanLunClassifier:
|
|||||||
# 默认XGBoost参数
|
# 默认XGBoost参数
|
||||||
default_params = {
|
default_params = {
|
||||||
'objective': 'binary:logistic',
|
'objective': 'binary:logistic',
|
||||||
'max_depth': 4,
|
'max_depth': 8,
|
||||||
'eta': 0.03,
|
'eta': 0.01,
|
||||||
'subsample': 0.8,
|
'subsample': 0.8,
|
||||||
'colsample_bytree': 0.8,
|
'colsample_bytree': 0.8,
|
||||||
'eval_metric': 'auc',
|
'eval_metric': 'auc',
|
||||||
'gamma': 0.1,
|
'gamma': 0.0,
|
||||||
'min_child_weight': 3,
|
'min_child_weight': 1,
|
||||||
'alpha': 1, # L1正则化
|
'alpha': 0, # L1正则化
|
||||||
'lambda': 3, # L2正则化
|
'lambda': 0.5, # L2正则化
|
||||||
'scale_pos_weight': 1
|
'scale_pos_weight': 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +208,7 @@ class ChanLunClassifier:
|
|||||||
else:
|
else:
|
||||||
self.model = xgb.Booster()
|
self.model = xgb.Booster()
|
||||||
self.model.load_model(model_file_path)
|
self.model.load_model(model_file_path)
|
||||||
def find_best_params(self, dataframe=None, save_csv=False, csv_path_prefix='param_'):
|
def find_best_params(self, dataframe=None, save_csv=False, csv_path_prefix='param_', model_name=None):
|
||||||
"""
|
"""
|
||||||
寻找最佳参数组合
|
寻找最佳参数组合
|
||||||
:param dataframe: 输入的DataFrame,如果为None则使用初始化时的dataframe
|
:param dataframe: 输入的DataFrame,如果为None则使用初始化时的dataframe
|
||||||
@@ -240,7 +240,7 @@ class ChanLunClassifier:
|
|||||||
param_info = f"eta{params['eta']}_depth{params['max_depth']}"
|
param_info = f"eta{params['eta']}_depth{params['max_depth']}"
|
||||||
train_csv_path = f"{csv_path_prefix}train_{param_info}.csv" if save_csv else None
|
train_csv_path = f"{csv_path_prefix}train_{param_info}.csv" if save_csv else None
|
||||||
|
|
||||||
model = self.train_model(dataframe=dataframe, data_file_path=train_csv_path, custom_params=params)
|
model = self.train_model(dataframe=dataframe, data_file_path=train_csv_path, custom_params=params, model_name=model_name)
|
||||||
|
|
||||||
# 分割数据集,后20%用于测试
|
# 分割数据集,后20%用于测试
|
||||||
if dataframe is None:
|
if dataframe is None:
|
||||||
@@ -298,6 +298,8 @@ class ChanLunClassifier:
|
|||||||
for klc in klc_list:
|
for klc in klc_list:
|
||||||
if klc.klc_fx_type != Chan_KLC_FX.UNKNOWN:
|
if klc.klc_fx_type != Chan_KLC_FX.UNKNOWN:
|
||||||
sample_list.append(klc)
|
sample_list.append(klc)
|
||||||
|
klc_count = 0
|
||||||
|
print('Processing data...')
|
||||||
for klc in sample_list:
|
for klc in sample_list:
|
||||||
if bi_index >= len(bi_list):
|
if bi_index >= len(bi_list):
|
||||||
bi_index = len(bi_list) - 1
|
bi_index = len(bi_list) - 1
|
||||||
@@ -333,6 +335,10 @@ class ChanLunClassifier:
|
|||||||
|
|
||||||
feature_data.append(feature_vec)
|
feature_data.append(feature_vec)
|
||||||
labels.append(label)
|
labels.append(label)
|
||||||
|
klc_count += 1
|
||||||
|
percent = klc_count/len(sample_list)*100
|
||||||
|
if percent % 10 == 0:
|
||||||
|
print('Data processed:', percent, '%')
|
||||||
for index, key in enumerate(feature_keys):
|
for index, key in enumerate(feature_keys):
|
||||||
print(index, key, feature_data[0][index])
|
print(index, key, feature_data[0][index])
|
||||||
# 如果需要保存到CSV
|
# 如果需要保存到CSV
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
+119
-38
@@ -1,4 +1,5 @@
|
|||||||
# --- Do not remove these libs ---
|
# --- Do not remove these libs ---
|
||||||
|
from statistics import median
|
||||||
from freqtrade.strategy import IStrategy
|
from freqtrade.strategy import IStrategy
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
@@ -6,7 +7,7 @@ import os
|
|||||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
from ChanLun import ChanLun
|
from ChanLun import ChanLun
|
||||||
from ChanLun_Classifier import ChanLunClassifier
|
from ChanLun_Classifier import ChanLunClassifier
|
||||||
from ChanEnum import Chan_FX_TYPE, Chan_KLC_FX
|
from ChanEnum import Chan_FX_TYPE, Chan_KLC_FX, Chan_BI_DIR, Chan_KLC_FX
|
||||||
# --------------------------------
|
# --------------------------------
|
||||||
from technical.util import resample_to_interval, resampled_merge
|
from technical.util import resample_to_interval, resampled_merge
|
||||||
import talib.abstract as ta
|
import talib.abstract as ta
|
||||||
@@ -53,11 +54,17 @@ class ChanLun_SOL_5(IStrategy):
|
|||||||
"240": 0.052,
|
"240": 0.052,
|
||||||
"360": 0
|
"360": 0
|
||||||
}
|
}
|
||||||
can_short = True
|
minimal_roi_2 = {
|
||||||
stoploss = -0.20
|
"0": 0.10,
|
||||||
|
"1200": 0.05,
|
||||||
|
"2400": 0.025,
|
||||||
|
"3600": 0
|
||||||
|
}
|
||||||
|
can_short = False
|
||||||
|
stoploss = -0.30
|
||||||
trailing_stop = False
|
trailing_stop = False
|
||||||
trailing_stop_positive = 0.015
|
trailing_stop_positive = 0.025
|
||||||
trailing_stop_positive_offset = 0.043
|
trailing_stop_positive_offset = 0.045
|
||||||
trailing_only_offset_is_reached = False
|
trailing_only_offset_is_reached = False
|
||||||
|
|
||||||
position_adjustment_enable = True
|
position_adjustment_enable = True
|
||||||
@@ -70,7 +77,7 @@ class ChanLun_SOL_5(IStrategy):
|
|||||||
time30 = 30
|
time30 = 30
|
||||||
time60 = 60
|
time60 = 60
|
||||||
time4h = 240
|
time4h = 240
|
||||||
time5 = 5
|
time5 = 60
|
||||||
last_time = datetime.now()
|
last_time = datetime.now()
|
||||||
big_size = 0
|
big_size = 0
|
||||||
big_state = "00"
|
big_state = "00"
|
||||||
@@ -102,7 +109,7 @@ class ChanLun_SOL_5(IStrategy):
|
|||||||
dataframe_60 = self.add_indicators(dataframe_60)
|
dataframe_60 = self.add_indicators(dataframe_60)
|
||||||
dataframe_4h = self.add_indicators(dataframe_4h)
|
dataframe_4h = self.add_indicators(dataframe_4h)
|
||||||
dataframe_1d = self.add_indicators(dataframe_1d)
|
dataframe_1d = self.add_indicators(dataframe_1d)
|
||||||
dataframe['state'] = self.chan.plot_dataframe(dataframe)
|
dataframe_60['state'] = self.chan.get_klc_state_list(dataframe_60)
|
||||||
#dataframe_5['state'] = self.chan.plot_dataframe(dataframe_5)
|
#dataframe_5['state'] = self.chan.plot_dataframe(dataframe_5)
|
||||||
#self.chan.print_data(dataframe_5)
|
#self.chan.print_data(dataframe_5)
|
||||||
#self.chan.cal_qjt(dataframe, dataframe_5)
|
#self.chan.cal_qjt(dataframe, dataframe_5)
|
||||||
@@ -116,9 +123,10 @@ class ChanLun_SOL_5(IStrategy):
|
|||||||
self.classifier.train_model(dataframe_1d, model_name="1d_model")
|
self.classifier.train_model(dataframe_1d, model_name="1d_model")
|
||||||
"""
|
"""
|
||||||
|
|
||||||
model_name = "5m_model"
|
model_name = "1m_model"
|
||||||
df = dataframe_5
|
df = dataframe
|
||||||
if self.classifier.model is None:
|
#self.classifier.find_best_params(df, model_name=model_name)
|
||||||
|
if self.classifier.model is None and False:
|
||||||
#self.classifier.train_model(df, model_name=model_name, data_file_path=model_name + '_feature_data.csv')
|
#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)
|
self.classifier.load_model(model_name=model_name)
|
||||||
klc_list = self.chan.get_klc_list(df)
|
klc_list = self.chan.get_klc_list(df)
|
||||||
@@ -129,22 +137,21 @@ class ChanLun_SOL_5(IStrategy):
|
|||||||
bottom_count = 0
|
bottom_count = 0
|
||||||
for index in range(int(len(klc_list) * 0.8), len(klc_list)):
|
for index in range(int(len(klc_list) * 0.8), len(klc_list)):
|
||||||
klc = klc_list[index]
|
klc = klc_list[index]
|
||||||
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()
|
||||||
features = klc.get_feature_data()
|
if self.classifier.predict(klc) > 0.5 and (klc.klc_fx_type == Chan_KLC_FX.BOTTOM1 or klc.klc_fx_type == Chan_KLC_FX.BOTTOM2) and features['klc_rsi'] < 40:
|
||||||
print(klc.end_time, klc.fx, self.classifier.predict(klc), features['klc_volume_ratio'], features['klc_macd_hist'], features['klc_rsi'])
|
print(klc.end_time, klc.fx, self.classifier.predict(klc), features['klc_volume_ratio'], features['klc_macdhist'], features['klc_rsi'])
|
||||||
bottom_avg += self.classifier.predict(klc)
|
bottom_avg += self.classifier.predict(klc)
|
||||||
bottom_count += 1
|
bottom_count += 1
|
||||||
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):
|
if self.classifier.predict(klc) > 0.5 and (klc.klc_fx_type == Chan_KLC_FX.TOP1 or klc.klc_fx_type == Chan_KLC_FX.TOP2) and features['klc_rsi'] > 50:
|
||||||
features = klc.get_feature_data()
|
print(klc.end_time, klc.fx, self.classifier.predict(klc), features['klc_volume_ratio'], features['klc_macdhist'], features['klc_rsi'])
|
||||||
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_avg += self.classifier.predict(klc)
|
||||||
top_count += 1
|
top_count += 1
|
||||||
if bottom_count > 0:
|
if bottom_count > 0:
|
||||||
bottom_avg /= bottom_count
|
bottom_avg /= bottom_count
|
||||||
if top_count > 0:
|
if top_count > 0:
|
||||||
top_avg /= top_count
|
top_avg /= top_count
|
||||||
print(bottom_avg, top_avg)
|
print('Bottom:', bottom_avg, 'Top:', top_avg)
|
||||||
print("-------------------------------------------------------------------------------")
|
print("-------------------------------------------------------------------------------")
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.print_xgb(dataframe, "1m_model")
|
self.print_xgb(dataframe, "1m_model")
|
||||||
@@ -155,7 +162,7 @@ class ChanLun_SOL_5(IStrategy):
|
|||||||
print("-------------------------------------------------------------------------------")
|
print("-------------------------------------------------------------------------------")
|
||||||
"""
|
"""
|
||||||
|
|
||||||
#classifier.find_best_params(dataframe)
|
|
||||||
#classifier.train_model(use_cv=False)
|
#classifier.train_model(use_cv=False)
|
||||||
#classifier.validate_model(dataframe)
|
#classifier.validate_model(dataframe)
|
||||||
#self.chan.get_bsp_list(dataframe)
|
#self.chan.get_bsp_list(dataframe)
|
||||||
@@ -164,7 +171,7 @@ class ChanLun_SOL_5(IStrategy):
|
|||||||
#dataframe_30['state'] = self.chan.cal_klu_state(dataframe_30)
|
#dataframe_30['state'] = self.chan.cal_klu_state(dataframe_30)
|
||||||
#dataframe_60['state'] = self.chan.cal_klu_state(dataframe_60)
|
#dataframe_60['state'] = self.chan.cal_klu_state(dataframe_60)
|
||||||
#dataframe_4h['state'] = self.chan.resample_klc_list(dataframe_4h)
|
#dataframe_4h['state'] = self.chan.resample_klc_list(dataframe_4h)
|
||||||
|
#self.print_bi_klc_fx(dataframe_60, "60m_model")
|
||||||
#self.chan.plot_dual(dataframe_5, dataframe_30)
|
#self.chan.plot_dual(dataframe_5, dataframe_30)
|
||||||
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
|
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
|
||||||
#self.print_macd_div_list(dataframe)
|
#self.print_macd_div_list(dataframe)
|
||||||
@@ -176,20 +183,94 @@ class ChanLun_SOL_5(IStrategy):
|
|||||||
#self.print_klc(dataframe_5, "5m: ")
|
#self.print_klc(dataframe_5, "5m: ")
|
||||||
#self.print_klc(dataframe_30, "30m:")
|
#self.print_klc(dataframe_30, "30m:")
|
||||||
#self.log_macd_div_list(dataframe)
|
#self.log_macd_div_list(dataframe)
|
||||||
#self.print_xgb(dataframe, "1m_model")
|
self.print_xgb(dataframe, "1m_model")
|
||||||
#self.print_xgb(dataframe_5, "5m_model")
|
self.print_xgb(dataframe_5, "5m_model")
|
||||||
#self.print_xgb(dataframe_30, "30m_model")
|
self.print_xgb(dataframe_30, "30m_model")
|
||||||
#self.print_xgb(dataframe_60, "1h_model")
|
self.print_xgb(dataframe_60, "60m_model")
|
||||||
#self.print_xgb(dataframe_4h, "4h_model")
|
self.print_xgb(dataframe_4h, "4h_model")
|
||||||
|
#self.print_xgb(dataframe_1d, "1d_model")
|
||||||
print("-------------------------------------------------------------------------------")
|
print("-------------------------------------------------------------------------------")
|
||||||
self.last_time = datetime.now()
|
self.last_time = datetime.now()
|
||||||
#dataframe = resampled_merge(dataframe, dataframe_5)
|
#dataframe = resampled_merge(dataframe, dataframe_5)
|
||||||
#dataframe = resampled_merge(dataframe, dataframe_15)
|
#dataframe = resampled_merge(dataframe, dataframe_15)
|
||||||
#dataframe = resampled_merge(dataframe, dataframe_30)
|
#dataframe = resampled_merge(dataframe, dataframe_30)
|
||||||
#dataframe = resampled_merge(dataframe, dataframe_60)
|
dataframe = resampled_merge(dataframe, dataframe_60)
|
||||||
#dataframe = resampled_merge(dataframe, dataframe_4h)
|
#dataframe = resampled_merge(dataframe, dataframe_4h)
|
||||||
return dataframe
|
return dataframe
|
||||||
# This is called when placing the initial order (opening trade)
|
def print_bi_klc_fx(self, dataframe, model_name):
|
||||||
|
klc_list = self.chan.get_full_klc_list(dataframe)
|
||||||
|
bi_list = self.chan.cal_bi_list(klc_list)
|
||||||
|
fx_count_list = []
|
||||||
|
fx_count_list_up = []
|
||||||
|
fx_count_list_down = []
|
||||||
|
self.classifier.load_model(model_name)
|
||||||
|
for bi in bi_list[1:-1]:
|
||||||
|
fx_count = 0
|
||||||
|
if bi.end_klc:
|
||||||
|
for index in range(bi.start_klc.index, bi.end_klc.index+1):
|
||||||
|
klc = klc_list[index]
|
||||||
|
features = klc.get_feature_data()
|
||||||
|
if bi.dir == Chan_BI_DIR.UP and (klc.klc_fx_type == Chan_KLC_FX.TOP1 or klc.klc_fx_type == Chan_KLC_FX.TOP2):
|
||||||
|
fx_count += 1
|
||||||
|
print(klc.start_time, klc.klc_fx_type, self.classifier.predict(klc), bi.dir, features['klc_volume_ratio'], features['klc_macdhist'], features['klc_rsi'])
|
||||||
|
else:
|
||||||
|
if bi.dir == Chan_BI_DIR.DOWN and (klc.klc_fx_type == Chan_KLC_FX.BOTTOM1 or klc.klc_fx_type == Chan_KLC_FX.BOTTOM2):
|
||||||
|
fx_count += 1
|
||||||
|
print(klc.start_time, klc.klc_fx_type, self.classifier.predict(klc), bi.dir, features['klc_volume_ratio'], features['klc_macdhist'], features['klc_rsi'])
|
||||||
|
fx_count_list.append(fx_count)
|
||||||
|
if fx_count == 0:
|
||||||
|
print("Not a bi: ", bi.start_time, bi.end_time, bi.dir)
|
||||||
|
if bi.dir == Chan_BI_DIR.UP:
|
||||||
|
fx_count_list_up.append(fx_count)
|
||||||
|
else:
|
||||||
|
fx_count_list_down.append(fx_count)
|
||||||
|
#print(bi.start_time, bi.end_time, bi.dir, fx_count)
|
||||||
|
avg_count = sum(fx_count_list) / len(fx_count_list)
|
||||||
|
max_count = max(fx_count_list)
|
||||||
|
min_count = min(fx_count_list)
|
||||||
|
median_count = median(fx_count_list)
|
||||||
|
print("Total bi:", len(bi_list), "AVG:", avg_count, "MAX:", max_count, "MIN:", min_count, "MEDIAN:", median_count)
|
||||||
|
for index in range(0, max_count+1):
|
||||||
|
index_count = fx_count_list.count(index)
|
||||||
|
print("Total:", index, "COUNT:", index_count, "RATIO:", index_count/len(fx_count_list))
|
||||||
|
avg_count_up = sum(fx_count_list_up) / len(fx_count_list_up)
|
||||||
|
avg_count_down = sum(fx_count_list_down) / len(fx_count_list_down)
|
||||||
|
median_count_up = median(fx_count_list_up)
|
||||||
|
median_count_down = median(fx_count_list_down)
|
||||||
|
max_count_up = max(fx_count_list_up)
|
||||||
|
min_count_up = min(fx_count_list_up)
|
||||||
|
max_count_down = max(fx_count_list_down)
|
||||||
|
min_count_down = min(fx_count_list_down)
|
||||||
|
print("Total UP bi:", len(fx_count_list_up), "AVG:", avg_count_up, "MAX:", max_count_up, "MIN:", min_count_up, "MEDIAN:", median_count_up)
|
||||||
|
for index in range(0, max_count_up+1):
|
||||||
|
index_count = fx_count_list_up.count(index)
|
||||||
|
print("UP:", index, "COUNT:", index_count, "RATIO:", index_count/len(fx_count_list_up))
|
||||||
|
print("Total DOWN bi:", len(fx_count_list_down), "AVG:", avg_count_down, "MAX:", max_count_down, "MIN:", min_count_down, "MEDIAN:", median_count_down)
|
||||||
|
for index in range(0, max_count_down+1):
|
||||||
|
index_count = fx_count_list_down.count(index)
|
||||||
|
print("DOWN:", index, "COUNT:", index_count, "RATIO:", index_count/len(fx_count_list_down))
|
||||||
|
|
||||||
|
def print_klc_list(self, klc_list, bi_list):
|
||||||
|
bi_index = 0
|
||||||
|
for klc in klc_list:
|
||||||
|
if bi_index == len(bi_list):
|
||||||
|
bi_index = len(bi_list) - 1
|
||||||
|
bi = bi_list[bi_index]
|
||||||
|
if self.check_klc_in_bi(klc, bi):
|
||||||
|
print("KLC in Bi: ", klc.start_time, klc.klc_fx_type, klc.bi.dir, klc.distance, bi.start_time, bi.dir)
|
||||||
|
else:
|
||||||
|
if bi.start_klc.index < klc.index:
|
||||||
|
bi_index += 1
|
||||||
|
print("KLC not in Bi: ", klc.start_time, klc.klc_fx_type, klc.bi.dir, klc.distance, bi.start_time, bi.dir)
|
||||||
|
else:
|
||||||
|
if klc.bi:
|
||||||
|
print("KLC not in Bi: ", klc.start_time, klc.klc_fx_type, klc.bi.dir, klc.distance, bi.start_time, bi.dir)
|
||||||
|
else:
|
||||||
|
print("KLC not in Bi: ", klc.start_time, klc.klc_fx_type, klc.distance, bi.start_time, bi.dir)
|
||||||
|
def check_klc_in_bi(self, klc, bi):
|
||||||
|
if klc.bi and klc.bi.index == bi.index:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
def print_xgb(self, dataframe, model_name):
|
def print_xgb(self, dataframe, model_name):
|
||||||
self.classifier.load_model(model_name)
|
self.classifier.load_model(model_name)
|
||||||
klc_list = self.chan.get_klc_list(dataframe)
|
klc_list = self.chan.get_klc_list(dataframe)
|
||||||
@@ -210,7 +291,7 @@ class ChanLun_SOL_5(IStrategy):
|
|||||||
# We need to leave most of the funds for possible further DCA orders
|
# We need to leave most of the funds for possible further DCA orders
|
||||||
# This also applies to fixed stakes
|
# This also applies to fixed stakes
|
||||||
return proposed_stake / self.max_dca_multiplier
|
return proposed_stake / self.max_dca_multiplier
|
||||||
def adjust_trade_position1(self, trade: Trade, current_time: datetime,
|
def adjust_trade_position(self, trade: Trade, current_time: datetime,
|
||||||
current_rate: float, current_profit: float,
|
current_rate: float, current_profit: float,
|
||||||
min_stake: float | None, max_stake: float,
|
min_stake: float | None, max_stake: float,
|
||||||
current_entry_rate: float, current_exit_rate: float,
|
current_entry_rate: float, current_exit_rate: float,
|
||||||
@@ -282,12 +363,12 @@ class ChanLun_SOL_5(IStrategy):
|
|||||||
stake_amount = stake_amount * (1 + (count_of_entries * 0.5))
|
stake_amount = stake_amount * (1 + (count_of_entries * 0.5))
|
||||||
dataframe_date = dataframe.iloc[-1]['date']
|
dataframe_date = dataframe.iloc[-1]['date']
|
||||||
#print(stake_amount, "---------------------------------------------------")
|
#print(stake_amount, "---------------------------------------------------")
|
||||||
if last_entry.order_filled_utc + timedelta(minutes=self.time5) < dataframe_date:
|
if last_entry.order_filled_utc + timedelta(minutes=self.time5*6) < dataframe_date:
|
||||||
if dataframe.iloc[-self.time5]['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)] == "-10" and last_entry.side == "buy":
|
if dataframe.iloc[-self.time5]['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)] == "-10" and last_entry.side == "buy":
|
||||||
#print(dataframe.iloc[-self.time5])
|
#print(dataframe.iloc[-self.time5])
|
||||||
#print(stake_amount)
|
#print(stake_amount)
|
||||||
return stake_amount, "1/3rd_increase"
|
return stake_amount, "1/3rd_increase"
|
||||||
if last_entry.order_filled_utc + timedelta(minutes=self.time5) < dataframe_date:
|
if last_entry.order_filled_utc + timedelta(minutes=self.time5*6) < dataframe_date:
|
||||||
if dataframe.iloc[-self.time5]['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)] == "10" and last_entry.side == "sell":
|
if dataframe.iloc[-self.time5]['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)] == "10" and last_entry.side == "sell":
|
||||||
#print(dataframe.iloc[-self.time5])
|
#print(dataframe.iloc[-self.time5])
|
||||||
#print(stake_amount)
|
#print(stake_amount)
|
||||||
@@ -392,8 +473,8 @@ class ChanLun_SOL_5(IStrategy):
|
|||||||
|
|
||||||
dataframe.loc[
|
dataframe.loc[
|
||||||
(
|
(
|
||||||
(dataframe['state'] == "-30")
|
#(dataframe['state'] == "-30")
|
||||||
#((dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)] == "-11") |
|
(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "-10")
|
||||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "-10") &
|
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "-10") &
|
||||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time30)] == "-10") &
|
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time30)] == "-10") &
|
||||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "-10")
|
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "-10")
|
||||||
@@ -402,8 +483,8 @@ class ChanLun_SOL_5(IStrategy):
|
|||||||
['enter_long', 'enter_tag']] = (1, 'long_signal_chan')
|
['enter_long', 'enter_tag']] = (1, 'long_signal_chan')
|
||||||
dataframe.loc[
|
dataframe.loc[
|
||||||
(
|
(
|
||||||
(dataframe['state'] == "30")
|
#(dataframe['state'] == "30")
|
||||||
#((dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)] == "11") |
|
(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "10")
|
||||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "10") &
|
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "10") &
|
||||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time30)] == "10") &
|
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time30)] == "10") &
|
||||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "10")
|
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "10")
|
||||||
@@ -414,16 +495,16 @@ class ChanLun_SOL_5(IStrategy):
|
|||||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
dataframe.loc[
|
dataframe.loc[
|
||||||
(
|
(
|
||||||
(dataframe['state']== "30")
|
#(dataframe['state']== "30")
|
||||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "10")
|
(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "10")
|
||||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time30)] == "10") &
|
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time30)] == "10") &
|
||||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time60)] == "10")
|
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time60)] == "10")
|
||||||
),
|
),
|
||||||
['exit_long', 'exit_tag']] = (1, 'long_close_signal_chan')
|
['exit_long', 'exit_tag']] = (1, 'long_close_signal_chan')
|
||||||
dataframe.loc[
|
dataframe.loc[
|
||||||
(
|
(
|
||||||
(dataframe['state'] == "-30")
|
#(dataframe['state'] == "-30")
|
||||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "-10")
|
(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "-10")
|
||||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time30)] == "-10") &
|
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time30)] == "-10") &
|
||||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time60)] == "-10")
|
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time60)] == "-10")
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user