Add Top and Bottom

This commit is contained in:
jackyu66git
2025-04-24 19:31:01 +08:00
parent b849ce8ec8
commit 9cb242f706
7 changed files with 142 additions and 17 deletions
+20
View File
@@ -32,7 +32,27 @@ 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'])
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):
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):
+33 -12
View File
@@ -551,7 +551,7 @@ class ChanLun():
# A new top found
#last_top.set_fx(Chan_FX_TYPE.UNKNOWN)
last_top = klc
print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Change 1")
#print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Change 1")
klc.set_klc_fx_type(Chan_KLC_FX.TOP1)
#print(klc.start_time, klc.fx, "一类卖点Sell 1")
#klc.set_fx(fx)
@@ -578,7 +578,7 @@ class ChanLun():
#last_top.set_fx(Chan_FX_TYPE.PTOP)
last_top = klc
last_bottom = pre_last_bi.start_klc
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)
#print(klc.start_time, last_bi.start_klc.start_time, "New TOP Found reset last bi")
klc.set_state("10")
@@ -602,7 +602,7 @@ class ChanLun():
bi.add_klc(klc)
bi_list.append(bi)
last_top = klc
print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Change 2")
#print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Change 2")
klc.set_klc_fx_type(Chan_KLC_FX.TOP2)
klc.set_state('30')
bi_list[-1].add_klc(klc)
@@ -616,7 +616,7 @@ class ChanLun():
last_bi.set_start_klc(klc, Chan_BI_DIR.DOWN)
#last_top.set_fx(Chan_FX_TYPE.UNKNOWN)
last_top = klc
print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Change 3")
#print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Change 3")
bi_list[-1].add_klc(klc)
klc.set_bi(bi_list[-1])
#print(klc.start_time, klc.fx, "笔卖点Sell 3")
@@ -637,7 +637,7 @@ class ChanLun():
else:
# First temp top and last bottom confirmed
last_top = klc
print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Change 4")
#print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Change 4")
bi_list[-1].add_klc(klc)
klc.set_bi(bi_list[-1])
#print(klc.start_time, klc.fx, "一类卖点Sell 1")
@@ -649,7 +649,7 @@ class ChanLun():
bi_list.append(bi)
bi_list[-1].add_klc(klc)
klc.set_bi(bi_list[-1])
print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Change 5")
#print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Change 5")
#print(klc.start_time, 'Create first top')
#print(klc.start_time, klc.fx, "笔卖点Sell 1")
#klc.fx = Bottom ========================
@@ -669,7 +669,7 @@ class ChanLun():
# A new bottom found
#last_bottom.set_fx(Chan_FX_TYPE.UNKNOWN)
last_bottom = klc
print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 1")
#print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 1")
klc.set_klc_fx_type(Chan_KLC_FX.BOTTOM1)
#print(klc.start_time, klc.fx, "一类买点Buy 1")
klc.set_state("-10")
@@ -697,7 +697,7 @@ class ChanLun():
#last_bottom.set_fx(Chan_FX_TYPE.PBOTTOM)
last_bottom = klc
last_top = pre_last_bi.start_klc
print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Bottom Change 2")
#print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Top Bottom Change 2")
klc.set_klc_fx_type(Chan_KLC_FX.BOTTOM2)
#print(klc.start_time, last_bi.start_klc.start_time, "New BOTTOM Found reset last bi")
klc.set_state("-10")
@@ -721,7 +721,7 @@ class ChanLun():
bi.add_klc(klc)
bi_list.append(bi)
last_bottom = klc
print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 2")
#print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 2")
klc.set_klc_fx_type(Chan_KLC_FX.BOTTOM2)
klc.set_state('-30')
bi_list[-1].add_klc(klc)
@@ -735,7 +735,7 @@ class ChanLun():
last_bi.set_start_klc(klc, Chan_BI_DIR.UP)
#last_bottom.set_fx(Chan_FX_TYPE.UNKNOWN)
last_bottom = klc
print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 3")
#print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 3")
bi_list[-1].add_klc(klc)
klc.set_bi(bi_list[-1])
#print(klc.start_time, klc.fx, "笔买点Buy 3")
@@ -757,7 +757,7 @@ class ChanLun():
else:
# First temp bottom and last top confirmed
last_bottom = klc
print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 4")
#print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 4")
bi_list[-1].add_klc(klc)
klc.set_bi(bi_list[-1])
#print(klc.start_time, klc.fx, "一类买点Buy 1")
@@ -769,7 +769,7 @@ class ChanLun():
bi_list.append(bi)
bi_list[-1].add_klc(klc)
klc.set_bi(bi_list[-1])
print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 5")
#print(klc.start_time, klc.fx, bi_list[-1].dir, "Last Bottom Change 5")
#print(klc.start_time, klc.fx, "笔买点Buy 4")
#if klc.fx != Chan_FX_TYPE.UNKNOWN:
#print(klc.start_time, klc.fx, klc.index)
@@ -1661,6 +1661,15 @@ class ChanLun():
else:
ax1.text(big_dates_num[text_index], seg.end_bi.end_klc.low-1, seg_macd_div, color='green', fontsize=14, alpha=0.6)
big_klc = self.get_klc_list(big_df)
self.cal_bi_list(big_klc)
for klc in big_klc:
if klc.klc_fx_type != Chan_KLC_FX.UNKNOWN:
text_index = klc.end_klu.index
if klc.fx == Chan_FX_TYPE.BOTTOM:
ax1.text(big_dates_num[text_index], klc.low, str(klc.klc_fx_type).replace("Chan_KLC_FX.", ""), color='green', fontsize=6, alpha=1)
else:
ax1.text(big_dates_num[text_index], klc.high, str(klc.klc_fx_type).replace("Chan_KLC_FX.", ""), color='red', fontsize=6, alpha=1)
"""
model = xgb.Booster()
model.load_model("30m_modelchan_xgb_model.json")
for klc in big_klc:
@@ -1671,6 +1680,7 @@ class ChanLun():
if predict > 0.35 and klc.fx == Chan_FX_TYPE.TOP:
text_index = klc.end_klu.index
ax1.text(big_dates_num[text_index], klc.low-1, predict, color='green', fontsize=14, alpha=0.6)
"""
"""
# 绘制大周期买卖点
@@ -1825,6 +1835,15 @@ class ChanLun():
else:
ax2.text(small_dates_num[text_index], seg.end_bi.end_klc.low-1, seg_macd_div, color='green', fontsize=14, alpha=0.8)
small_klc = self.get_klc_list(small_df)
self.cal_bi_list(small_klc)
for klc in small_klc:
if klc.klc_fx_type != Chan_KLC_FX.UNKNOWN:
text_index = klc.end_klu.index
if klc.fx == Chan_FX_TYPE.BOTTOM:
ax2.text(small_dates_num[text_index], klc.low, str(klc.klc_fx_type).replace("Chan_KLC_FX.", ""), color='green', fontsize=6, alpha=1)
else:
ax2.text(small_dates_num[text_index], klc.high, str(klc.klc_fx_type).replace("Chan_KLC_FX.", ""), color='red', fontsize=6, alpha=1)
"""
model = xgb.Booster()
model.load_model("5m_modelchan_xgb_model.json")
for klc in small_klc:
@@ -1836,6 +1855,8 @@ class ChanLun():
text_index = klc.end_klu.index
ax2.text(small_dates_num[text_index], klc.low-1, predict, color='green', fontsize=14, alpha=0.6)
"""
"""
# 绘制小周期买卖点
for idx, point in small_buy_sell_points.items():
if idx < 0 or idx >= len(small_df):
Binary file not shown.
Binary file not shown.
Binary file not shown.
+22 -3
View File
@@ -17,7 +17,7 @@ from pytz import timezone
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from ChanLun import ChanLun
from ChanEnum import Chan_BI_DIR, Chan_SEG_DIR
from ChanEnum import Chan_BI_DIR, Chan_SEG_DIR, Chan_KLC_FX, Chan_FX_TYPE
# 添加买卖点枚举类型
class TRADE_POINT_TYPE:
@@ -180,12 +180,24 @@ def analyze_chan(df):
# 添加买卖点识别
buy_sell_points = identify_trade_points(bi_list, seg_list, zs_list)
# 提取K线分型信息
klc_fx_info = []
for klc in klc_list:
if hasattr(klc, 'klc_fx_type') and klc.klc_fx_type != Chan_KLC_FX.UNKNOWN:
klc_fx_info.append({
'time': klc.end_time,
'price': klc.low if klc.fx == Chan_FX_TYPE.BOTTOM else klc.high,
'fx_type': str(klc.klc_fx_type).replace("Chan_KLC_FX.", ""),
'is_bottom': klc.fx == Chan_FX_TYPE.BOTTOM
})
return {
'klc_list': klc_list,
'bi_list': bi_list,
'seg_list': seg_list,
'zs_list': zs_list,
'trade_points': buy_sell_points
'trade_points': buy_sell_points,
'klc_fx_info': klc_fx_info # 添加分型信息
}
def identify_trade_points(bi_list, seg_list, zs_list):
@@ -426,7 +438,14 @@ def analyze():
'price': point['price'],
'desc': point['desc']
} for point in analysis_result['trade_points']],
'macd': macd_data
'macd': macd_data,
# 添加K线分型信息
'klc_fx_info': [{
'time': format_time_safely(point['time'], client_tz),
'price': point['price'],
'fx_type': point['fx_type'],
'is_bottom': point['is_bottom']
} for point in analysis_result['klc_fx_info']]
})
else:
print(f"只请求元素数据,跳过主周期数据处理 (elements_only={elements_only})")
+65
View File
@@ -275,6 +275,10 @@
<input class="form-check-input" type="checkbox" id="showMacd" checked>
<label class="form-check-label" for="showMacd">MACD</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="showKlcFxType">
<label class="form-check-label" for="showKlcFxType">分型类型</label>
</div>
<div class="form-check form-check-inline" style="display: none;">
<input class="form-check-input" type="checkbox" id="showTradePoints">
<label class="form-check-label" for="showTradePoints">买卖点</label>
@@ -730,6 +734,11 @@
updateChartDisplay();
});
// 添加分型类型复选框变更事件
$('#showKlcFxType').change(function() {
updateChartDisplay();
});
// 当选择不同的元素时间周期时
$('#elementTimeframe').change(function() {
const elementTimeframe = $(this).val();
@@ -916,6 +925,7 @@
console.log('- 显示未完成中枢:', $('#showMainUncompletedZs').is(':checked'));
console.log('- 显示MACD:', $('#showMacd').is(':checked'));
console.log('- 显示买卖点:', $('#showTradePoints').is(':checked'));
console.log('- 显示分型类型:', $('#showKlcFxType').is(':checked'));
// 重新初始化图表,这将清除旧图形并重新绘制
initTradingView($('#symbol').val(), $('#timeframe').val());
@@ -2375,6 +2385,61 @@
console.log('绘制买卖点 - 已禁用');
}
// 显示分型类型标签
if ($('#showKlcFxType').is(':checked') && currentData.klc_fx_info && currentData.klc_fx_info.length > 0) {
console.log(`绘制K线分型类型标签,共${currentData.klc_fx_info.length}条`);
currentData.klc_fx_info.forEach(function(fx) {
try {
// 直接使用UTC时间戳(秒)
const timestamp = Math.floor(new Date(fx.time).getTime() / 1000);
const price = parseFloat(fx.price);
if (isNaN(timestamp) || isNaN(price)) {
console.error('分型类型时间或价格转换错误:', fx.time, fx.price);
return;
}
// 确定颜色和位置
const color = fx.is_bottom ? '#28a745' : '#dc3545'; // 底分型绿色,顶分型红色
// 创建标记系列
const markerSeries = mainChart.addLineSeries({
lastValueVisible: false,
priceLineVisible: false,
});
// 设置文本标记
markerSeries.setMarkers([
{
time: timestamp,
position: fx.is_bottom ? 'belowBar' : 'aboveBar',
color: color,
shape: 'circle',
text: fx.fx_type,
size: 1
}
]);
// 可选:添加更加明显的文本标签
const textSeries = mainChart.addLineSeries({
lastValueVisible: false,
priceLineVisible: false,
});
textSeries.setData([{
time: timestamp,
value: price + (fx.is_bottom ? -0.0005 * price : 0.0005 * price) // 小偏移,避免遮挡
}]);
} catch (e) {
console.error('绘制分型类型标签出错:', e);
}
});
} else {
console.log('绘制分型类型标签 - 已禁用或无数据');
}
// 调整所有图表以适应数据
mainChart.timeScale().fitContent();
volumeChart.timeScale().fitContent();