From 7815eada0010886bf5d363615dd65d18a8ea48d6 Mon Sep 17 00:00:00 2001 From: jackyu66git Date: Fri, 10 Apr 2026 13:01:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=A8=E8=83=BD=E7=90=86?= =?UTF-8?q?=E8=AE=BA=EF=BC=8C=E4=BF=AE=E6=94=B9klc=E6=95=B4=E4=BD=93?= =?UTF-8?q?=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChanKLC.py | 4 +- K线动能理论.txt | 3 + TF_DF.py | 13 ++++ web/templates/index.html | 159 +++++++++++++++++---------------------- 缠论.txt | 36 +++++++++ 5 files changed, 124 insertions(+), 91 deletions(-) diff --git a/ChanKLC.py b/ChanKLC.py index a140f1d..7dcafcb 100644 --- a/ChanKLC.py +++ b/ChanKLC.py @@ -372,14 +372,14 @@ class ChanKLC(): end_time = self.next.end_time high = self.high low = self.pre.low if self.pre.low < self.next.low else self.next.low - if self.next.close < self.pre.low: + if self.next.close < self.pre.low or True: display = True elif self.fx == Chan_FX_TYPE.BOTTOM: start_time = self.pre.end_time end_time = self.next.end_time high = self.pre.high if self.pre.high > self.next.high else self.next.high low = self.low - if self.next.close > self.pre.high: + if self.next.close > self.pre.high or True: display = True if high > 0 and self.next.end_time and display: #print(start_time, end_time, high, low) diff --git a/K线动能理论.txt b/K线动能理论.txt index 09e598a..a01758e 100644 --- a/K线动能理论.txt +++ b/K线动能理论.txt @@ -39,6 +39,8 @@ MACD归零轴的两种情况,两者是或的关系,满足任意一种都是 3. MACD归零轴时,如果此时k线始终保持在EMA24附近,如果一直是EMA24之上之后出现反弹行情就会很大(最强反弹)这种反弹是2个时间级别同时归零轴形成的反弹,容易创新高新低,一般出现在强势行情。 4. K线先触碰EMA52,而MACD黄白线都未归零轴 +MACD归零轴反弹/反抽的完美形态是K线触碰EMA52附近,MACD的白线无限接近零轴之后出现上涨或下跌 + 高位空 当MACD的黄白线远离零轴运行时,与零轴有一定的距离,形成了零轴的高危形态。随着K线出现缓慢上涨或者下跌,或者盘整,MACD的能量柱出现衰减,同时能量柱与MACD黄白线形成空间夹角,随着能量柱越来越小,夹角越来越大形成高位空。这种容易形成回调下跌,特别是导致次一级的MACD穿越零轴 @@ -55,6 +57,7 @@ MACD黄白线和零轴的几种形态: 当MACD黄白线处于高位,随着K线出现缓慢上涨或者横盘整理,MACD黄白线保持高位出现平滑横盘走势,此时,MACD的能量柱出现衰减变化,同时能量柱和黄白线之间形成一定的空间夹脚,随着能量柱的不断衰减就导致黄白线和能量柱之间的空间夹脚越来越大,因此就形成高位空 归零轴 当MACD黄白线在高位,驱动K线上涨的能量所产生的加速度小于或者等于零,K线减速上涨或者下跌,能量变化越来越小,能量柱呈现出一根比一根短的排列方式 + 穿零轴 同时满足以下两个条件 1. 在某个时间级别,K线的价格或者指数有效击穿当前时间级别的EMA52 diff --git a/TF_DF.py b/TF_DF.py index 28e0910..48691f9 100644 --- a/TF_DF.py +++ b/TF_DF.py @@ -205,6 +205,19 @@ class TF_DF(): #print(klc.start_time, klc.end_time,klc.next.start_time, klc.next.end_time, klc.macd, klc.state, klc.fx, "BOTTOM") return Chan_FX_TYPE.BOTTOM return Chan_FX_TYPE.UNKNOWN + def check_fx2(self, klc): + if klc.pre and klc.next: + if klc.high > klc.pre.close and klc.close > klc.next.close and klc.close > klc.pre.close and klc.close > klc.next.close: + #if (klc.close > klc.ema52 or klc.next.close > klc.next.ema52) and klc.macd > 0: + klc.set_fx(Chan_FX_TYPE.TOP) + #print(klc.start_time, klc.end_time,klc.next.start_time, klc.next.end_time, klc.macd, klc.state, klc.fx, "TOP") + return Chan_FX_TYPE.TOP + elif klc.low < klc.pre.close and klc.close < klc.next.close and klc.close < klc.pre.close and klc.close < klc.next.close: + #if (klc.close < klc.ema52 or klc.next.close < klc.next.ema52) and klc.macd < 0: + klc.set_fx(Chan_FX_TYPE.BOTTOM) + #print(klc.start_time, klc.end_time,klc.next.start_time, klc.next.end_time, klc.macd, klc.state, klc.fx, "BOTTOM") + return Chan_FX_TYPE.BOTTOM + return Chan_FX_TYPE.UNKNOWN def check_fx_pattern(self, klc): klu_list = klc.pre.klu_list + klc.klu_list + klc.next.klu_list diff --git a/web/templates/index.html b/web/templates/index.html index 1635605..1bcd6d1 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -2049,72 +2049,24 @@ const periodChanged = (curPeriod !== _lastKlinePeriod); _lastKlinePeriod = curPeriod; - // 保存当前的可见逻辑范围(周期切换时不保留,避免范围越界) - let logicalRange = null; - let visibleRange = null; - + // 保存当前的可见范围(周期切换时不保留,避免范围越界) if (!periodChanged && tvWidget && tvWidget.mainChart) { - logicalRange = tvWidget.mainChart.timeScale().getVisibleLogicalRange(); - visibleRange = tvWidget.mainChart.timeScale().getVisibleRange(); + try { + const ts = tvWidget.mainChart.timeScale(); + window._pendingRestoreView = { + barSpacing: ts.options().barSpacing, + scrollPosition: ts.scrollPosition(), + rightOffset: ts.options().rightOffset + }; + } catch (e) { + window._pendingRestoreView = null; + } } console.log('更新图表显示'); - console.log('BI中枢输入状态:', { - main: $('#showMainBiZs').is(':checked'), - element: $('#showElementBiZs').is(':checked') - }); - console.log('- 显示K线:', $('#showOriginalKline').is(':checked')); - console.log('- 显示笔:', $('#showMainBi').is(':checked')); - console.log('- 显示线段:', $('#showMainSeg').is(':checked')); - console.log('- 显示中枢:', $('#showMainZs').is(':checked')); - console.log('- 显示BI中枢(主):', $('#showMainBiZs').is(':checked')); - console.log('- 显示BI中枢(次):', $('#showElementBiZs').is(':checked')); - console.log('- 显示MACD:', true); - console.log('- 显示成交量:', false); - console.log('- 显示分型类型:', $('#showKlcFxType').is(':checked')); - console.log('- 显示小周期分型:', $('#showElementKlcFxType').is(':checked')); - console.log('- 显示KLU分型:', $('#showKluFxType').is(':checked')); - console.log('- 显示小周期KLU分型:', $('#showElementKluFxType').is(':checked')); - console.log('- 显示买卖点:', $('#showTradePoints').is(':checked')); - console.log('- 显示原始K线:', $('#showOriginalKline').is(':checked')); - console.log('- 显示主周期布林带:', $('#showMainBollinger').is(':checked')); - console.log('- 显示次周期布林带:', $('#showElementBollinger').is(':checked')); - // 重新初始化图表,这将清除旧图形并重新绘制 + // 重新初始化图表(initTradingView 内部会在最终同步时读取 _pendingRestoreView) initTradingView($('#symbol').val(), $('#timeframe').val()); - - // 如果有保存的范围,恢复它 - setTimeout(() => { - if (tvWidget) { - if (logicalRange) { - // 应用保存的逻辑范围到所有图表 - tvWidget.mainChart.timeScale().setVisibleLogicalRange(logicalRange); - tvWidget.volumeChart.timeScale().setVisibleLogicalRange(logicalRange); - if (tvWidget.atrChart) { - tvWidget.atrChart.timeScale().setVisibleLogicalRange(logicalRange); - } - if (tvWidget.macdChart) { - tvWidget.macdChart.timeScale().setVisibleLogicalRange(logicalRange); - } - if (tvWidget.chanMacdChart) { - tvWidget.chanMacdChart.timeScale().setVisibleLogicalRange(logicalRange); - } - } else if (visibleRange) { - // 如果没有逻辑范围,使用时间戳范围 - tvWidget.mainChart.timeScale().setVisibleRange(visibleRange); - tvWidget.volumeChart.timeScale().setVisibleRange(visibleRange); - if (tvWidget.atrChart) { - tvWidget.atrChart.timeScale().setVisibleRange(visibleRange); - } - if (tvWidget.macdChart) { - tvWidget.macdChart.timeScale().setVisibleRange(visibleRange); - } - if (tvWidget.chanMacdChart) { - tvWidget.chanMacdChart.timeScale().setVisibleRange(visibleRange); - } - } - } - }, 100); } } // 确保所有时间处理都使用UTC时间,包括表格数据显示 @@ -6742,11 +6694,11 @@ } const defaultMAs = [ - { type: 'EMA', length: 52, color: '#800080', name: 'EMA52' }, // 紫色 - { type: 'EMA', length: 26, color: '#008000', name: 'EMA26' }, // 深绿色 - { type: 'EMA', length: 104, color: '#FF8C00', name: 'EMA104' }, // 橙色 - { type: 'EMA', length: 156, color: '#1E90FF', name: 'EMA156' }, // 蓝色 - { type: 'EMA', length: 208, color: '#1F004F', name: 'EMA312' } // 蓝色 + { type: 'EMA', length: 13, color: '#800080', name: 'EMA13', visible: true }, // 紫色 + { type: 'EMA', length: 26, color: '#000000', name: 'EMA26', visible: true }, // 黑色 + { type: 'EMA', length: 52, color: '#FF8C00', name: 'EMA52', visible: false }, // 橙色 + { type: 'EMA', length: 104, color: '#1E90FF', name: 'EMA104', visible: false }, // 蓝色 + { type: 'EMA', length: 156, color: '#F700FF', name: 'EMA156', visible: false } // 粉色 ]; defaultMAs.forEach(ma => { @@ -6760,7 +6712,7 @@ lineWidth: 1, // 1px线宽 lineStyle: 0, // 实线 color: ma.color, - visible: true + visible: ma.visible }; movingAverages.push(config); @@ -6775,7 +6727,7 @@ upperMultiplier: 2, lowerMultiplier: 2, source: 'close', - lineWidth: 2, + lineWidth: 1, lineStyle: 0, upperColor: '#ff6b6b', middleColor: '#ffffff', @@ -6802,24 +6754,39 @@ // 绑定同步事件 bindSyncEvents(mainChartContainer, volumeChartContainer, atrChartContainer, macdChartContainer, chanMacdChartContainer, mainChart, volumeChart, atrChart, macdChart, chanMacdChart, showMacd); - // 最终确保所有图表时间轴对齐 + // 最终确保所有图表时间轴对齐(同时恢复刷新前保存的缩放/位置) setTimeout(() => { - const visibleRange = mainChart.timeScale().getVisibleRange(); - if (visibleRange) { - console.log('🔧 最终同步可见范围:', visibleRange); - - // 强制重新设置所有图表的可见范围 - volumeChart.timeScale().setVisibleRange(visibleRange); - atrChart.timeScale().setVisibleRange(visibleRange); - if (showMacd && macdChart) { - macdChart.timeScale().setVisibleRange(visibleRange); + const allCharts = [mainChart, volumeChart, atrChart]; + if (showMacd && macdChart) allCharts.push(macdChart); + if (showMacd && chanMacdChart) allCharts.push(chanMacdChart); + + // 检查是否有待恢复的视图(barSpacing + scrollPosition) + const pending = window._pendingRestoreView; + window._pendingRestoreView = null; + + if (pending && pending.barSpacing) { + // 恢复刷新前的缩放和滚动位置 + console.log('📌 恢复图表视图 - barSpacing:', pending.barSpacing, 'scrollPosition:', pending.scrollPosition); + allCharts.forEach(c => { + try { + c.timeScale().applyOptions({ barSpacing: pending.barSpacing }); + c.timeScale().scrollToPosition(pending.scrollPosition, false); + } catch(e) {} + }); + } else { + // 无保存视图,正常同步主图到子图 + const visibleRange = mainChart.timeScale().getVisibleRange(); + if (visibleRange) { + console.log('🔧 最终同步可见范围:', visibleRange); + [volumeChart, atrChart].concat( + showMacd && macdChart ? [macdChart] : [], + showMacd && chanMacdChart ? [chanMacdChart] : [] + ).forEach(c => { + try { c.timeScale().setVisibleRange(visibleRange); } catch(e) {} + }); } - if (showMacd && chanMacdChart) { - chanMacdChart.timeScale().setVisibleRange(visibleRange); - } - - console.log('🔧 最终时间轴对齐完成'); } + console.log('🔧 最终时间轴对齐完成'); }, 150); // 只有在时间输入框都为空时才设置图表默认时间范围 if (!$('#start_time').val() && !$('#end_time').val()) { @@ -8410,14 +8377,28 @@ $('#elementTimeframe').val(data.element_timeframe); } + // 保存当前缩放(barSpacing)和滚动位置(scrollPosition)到 window + // tvWidget 会在 initTradingView 内被重建,所以必须存到 window 上 + if (tvWidget && tvWidget.mainChart) { + try { + const ts = tvWidget.mainChart.timeScale(); + window._pendingRestoreView = { + barSpacing: ts.options().barSpacing, + scrollPosition: ts.scrollPosition(), + rightOffset: ts.options().rightOffset + }; + console.log('📌 保存图表视图:', JSON.stringify(window._pendingRestoreView)); + } catch (e) { + console.warn('保存图表视图失败:', e); + window._pendingRestoreView = null; + } + } + initTradingView($('#symbol').val(), $('#timeframe').val()); // 更新表格数据 updateTables(data); - // 只有在图表已初始化且调用了updateTradingViewData时才不需要重复调用EMA52显示 - // 如果图表未初始化,调用了initTradingView,那么EMA52显示已经在initTradingView中处理了 - // 但为了确保在所有情况下都能正确显示,这里统一调用一次 if (currentData && currentData.ema52_dict) { updateEMA52Display(currentData); } @@ -10574,13 +10555,13 @@
- -
默认: 24 (12×2)
+ +
默认: 13
- -
默认: 52 (26×2)
+ +
默认: 26
diff --git a/缠论.txt b/缠论.txt index bd92f5e..0b9fd2d 100644 --- a/缠论.txt +++ b/缠论.txt @@ -82,3 +82,39 @@ 经过标准化处理后,所有向上线段都是以最低点开始最高点结束,向下线段都是以最高点开始最低点结束,这样,所以线段的连接,就形成一条延续不断、首尾相连的折线,这样,复杂的图形,就会十分地标准化,也为后面的中枢、走势类型等分析提供了最标准且基础的部件。 本级别没有背驰的,次级别背驰下跌后形成第三类卖点进而形成本级别的V型反转,小转大 + +大级别 判断趋势位置(是否进入末期) +中级别 识别第一类买卖点结构 +小级别 精准入场与风控 + +短线操作策略 +大级别1H/2H/4H,判断趋势方向, +上涨趋势 +趋势启动第一次穿零轴后归零轴反弹,EMA52和黄白线无限接近零轴,MACD黄白线在零轴以上 +下跌趋势 +趋势启动第一次穿零轴后归零轴反弹,EMA52和黄白线无限接近零轴,MACD黄白线在零轴以下 +MACD归零轴的两种情况,两者是或的关系,满足任意一种都是归零轴,归零轴的四种走势: +1. K线下跌或者上涨后触碰当前时间级别的EMA52附近 +2. MACD的白线快线无限接近零轴, +3. MACD归零轴时,如果此时k线始终保持在EMA24附近,如果一直是EMA24之上之后出现反弹行情就会很大(最强反弹)这种反弹是2个时间级别同时归零轴形成的反弹,容易创新高新低,一般出现在强势行情。 +4. K线先触碰EMA52,而MACD黄白线都未归零轴 +归零轴完美形态 +MACD归零轴反弹/反抽的完美形态是K线触碰EMA52附近,MACD的白线无限接近零轴之后出现上涨或下跌 +中级别 +识别EMA52和MACD黄白线归零轴,MACD能量柱形成背驰 +小级别 +识别最后下跌段MACD背驰和开始上涨K线形态,识别笔,精确定位第一类和第二类卖卖点 + +在小级别第一类或者第二类卖卖点开仓 + +平仓规则 +大级别如果K线在EMA13/EMA7均线以上,根据倍数关系到相应的小周期观察顶底背离进行平仓操作,一般来说在大级别的1/4小级别观察背离顶底 +比如1H归零轴反弹,K线一直运行在EMA7以上,那么到15M级别进行平仓操作,观察背离 + +趋势策略 +1. 使用30分钟,5分钟,1分钟时间周期进行交易 +2. 使用顶底分型和MACD背驰信号作为趋势衰竭信号,但是不作为开仓信号 +3. 等待价格确认跌破EMA26,K线跌破EMA26后2根确认,EMA13和EMA26交叉作为验证信号 +4. 通过小级别5分钟和1分钟找到精确入场点 +5. 止损定在最后一个顶底分型的高低点,止盈先设置1:2,如果出现反向分型和macd衰竭信号,先减半保本损 +6. \ No newline at end of file