Add Top and Bottom
This commit is contained in:
+20
@@ -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
@@ -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
@@ -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})")
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user