添加老的策略

This commit is contained in:
jackyu66git
2025-09-28 11:48:03 +08:00
parent b40f4ceafc
commit 7f64ca2528
21 changed files with 3166 additions and 0 deletions
+135
View File
@@ -0,0 +1,135 @@
# 4根EMA均线收束发散策略使用说明
## 策略概述
这个策略基于4根不同周期的EMA(指数移动平均线)的收束和发散来识别买卖时机,主要特点:
- **买入信号**:4根均线从收束状态开始向同一方向发散
- **卖出信号**:均线开口达到最大时平仓
## 核心理念
**均线收束发散理论**:当多条均线聚集在一起(收束)时,表示市场处于整理状态;当均线开始向同一方向散开(发散)时,往往是新趋势的开始。这个策略专门捕捉这种从收束到发散的转折点。
## 核心参数设置
### EMA周期参数
- **EMA1周期**:默认5(快速均线,红色)
- **EMA2周期**:默认10(中速均线,橙色)
- **EMA3周期**:默认20(慢速均线,蓝色)
- **EMA4周期**:默认60(超慢速均线,紫色)
### 开口阈值
- **开口阈值(%)**:默认0.5%,控制卖出信号的敏感度
### 交易频率控制
- **最小交易间隔(K线数)**:默认20根,控制两次交易之间的最小间隔
- **最小价格变化(%)**:默认0.5%,要求价格有足够变化才能开新仓
### 均线收束参数
- **均线最大间距(%)**:默认0.3%,定义均线收束的最大距离阈值
- **收束确认周期**:默认3根K线,确认收束状态的持续时间
## 买入条件详解
### 1. 多头买入条件(向上发散)
- **均线之前收束**:4根均线距离在设定阈值内且持续足够周期
- **开始向上发散**:4根均线同时向上且距离开始扩大
- **价格在EMA52上方**:确保顺应长期趋势
- **交易间隔足够**:距离上次交易至少20根K线
- **价格变化足够**:相对上次交易价格变化超过0.5%
- 满足条件时产生**买多信号**
### 2. 空头买入条件(向下发散)
- **均线之前收束**:4根均线距离在设定阈值内且持续足够周期
- **开始向下发散**:4根均线同时向下且距离开始扩大
- **价格在EMA52下方**:确保顺应长期趋势
- **交易间隔足够**:距离上次交易至少20根K线
- **价格变化足够**:相对上次交易价格变化超过0.5%
- 满足条件时产生**买空信号**
## 卖出条件详解
### 开口最大检测
- 计算**最快均线(EMA5**和**最慢均线(EMA60**之间的距离
- 使用相对价格百分比来衡量开口程度
- 当开口达到**历史最大值的90%**且超过**设定阈值**时触发平仓
## 视觉指示功能
### 1. 均线显示
- **红色线**EMA5(最快)
- **橙色线**EMA10
- **蓝色线**EMA20
- **紫色线**EMA60(最慢)
### 2. 背景颜色
- **浅黄色背景**:均线处于收束状态
- **浅绿色背景**:均线开始向上发散
- **浅红色背景**:均线开始向下发散
### 3. 交易信号标记
- **绿色向上箭头"买多"**:向上发散买入信号
- **红色向下箭头"买空"**:向下发散买入信号
- **黄色"平仓"**:开口最大卖出信号
### 4. 信息表格
显示实时状态:
- 均线间距(当前4根均线的最大距离)
- 收束阈值(定义收束状态的距离上限)
- 收束状态(收束中/发散中)
- 发散方向(向上发散/向下发散/无发散)
- 趋势方向(同向上/同向下/分歧)
- 价格位置(EMA52上方/下方/附近)
- 距上次交易(K线数)
- 可交易状态(可交易/等待中)
- 当前仓位状态
## 策略优势
1. **趋势起点捕捉**:专门捕捉从整理到趋势的转折点,入场时机精准
2. **双向交易**:可以做多也可以做空,适应不同市场环境
3. **风险控制**:在开口最大时及时平仓,避免趋势反转损失
4. **频率控制**:严格的收束发散条件,避免过度交易
5. **多重过滤**:收束状态+发散方向+价格位置+时间间隔多重过滤
6. **信号质量高**:只在均线真正开始发散时才触发,减少假信号
7. **视觉友好**:直观的背景颜色显示收束/发散状态
## 使用建议
### 1. 时间周期选择
- **短线交易**:建议使用15分钟或1小时图
- **中线交易**:建议使用4小时或日线图
- **长线交易**:建议使用日线或周线图
### 2. 参数调优
- **活跃市场**:可以降低均线间距阈值(0.2%-0.25%),减少交易间隔(10-15根K线)
- **平静市场**:可以提高均线间距阈值(0.4%-0.5%),增加交易间隔(25-30根K线)
- **不同品种**:根据标的物波动性调整EMA周期和收束阈值
- **降低频率**:增大收束阈值和交易间隔,提高价格变化要求
- **提高敏感度**:减小收束阈值,缩短收束确认周期
- **波动性大的品种**:适当增大收束阈值,避免噪音干扰
### 3. 风险管理
- 建议设置固定的止损比例(如2-3%)
- 不要在横盘震荡市场中使用
- 注意重大消息面对策略的影响
### 4. 最佳使用场景
- **震荡后的突破**:最适合捕捉整理后的趋势启动
- **趋势转换点**:识别从无趋势到有趋势的转折
- **配合成交量**:发散时配合放量效果更佳
- **多时间框架**:可在不同时间周期上同时使用
- **避免强势单边市**:不适合已经大幅单边运行的市场
## 注意事项
1. 这是一个趋势跟踪策略,在震荡市场中可能产生较多假信号
2. 开口最大的判断具有一定滞后性,可能错过最佳卖点
3. 建议在回测中验证参数设置的有效性
4. 实盘使用时请注意资金管理和风险控制
## 版本信息
- Pine Script版本:v6
- 策略类型:双向交易策略
- 适用市场:股票、期货、外汇、加密货币
+126
View File
@@ -0,0 +1,126 @@
# 缠论 TradingView Pine Script 实现
本项目使用 Pine Script 6.0 实现了完整的缠论分析系统,包含K线合并、分型、笔、线段、中枢识别和买卖点信号。
## 文件说明
### 1. chan_theory.pine
**完整版缠论指标**
- 实现了缠论的全部核心概念
- 包含K线合并逻辑
- 完整的分型、笔、线段、中枢识别
- 基于中枢的买卖点信号
- 丰富的自定义参数和显示选项
### 2. chan_theory_simple.pine
**精简版缠论指标**
- 优化性能和可读性
- 使用Pine Script内置函数提高效率
- 简化的中枢识别算法
- 更稳定的绘图对象管理
- 适合日常使用
### 3. 缠论使用说明.md
**详细使用文档**
- 缠论理论基础解释
- 参数设置说明
- 使用方法和注意事项
- 常见问题解答
## 快速开始
1. **导入指标**
- 复制任一 `.pine` 文件内容
- 在 TradingView 的 Pine Editor 中粘贴
- 点击"添加到图表"
2. **选择版本**
- `chan_theory.pine`: 功能完整,适合深入学习
- `chan_theory_simple.pine`: 性能优化,适合实际交易
3. **参数调整**
- 根据交易级别调整分型周期
- 自定义颜色和显示选项
- 开启所需的警报功能
## 核心功能
### 🔍 分型识别
- 自动识别顶分型和底分型
- 标记为 "T"(顶)和 "B"(底)
- 可调节识别灵敏度
### 📈 笔的构建
- 连接相邻反向分型
- 蓝色线条显示价格波动路径
- 形成缠论分析的基础单位
### 🎯 中枢识别
- 自动识别三笔以上的重叠区间
- 灰色半透明方框显示
- 支持多级别中枢分析
### 💰 买卖点信号
- 基于中枢突破的交易信号
- 绿色"买"标签:跌破中枢下沿回调
- 红色"卖"标签:突破中枢上沿回调
### 📊 信息面板
- 实时显示分型和中枢统计
- 当前分析状态一目了然
- 右上角位置,不影响图表分析
## 技术特点
- **Pine Script 6.0**: 使用最新版本特性
- **内存优化**: 限制数组大小避免内存溢出
- **绘图管理**: 自动清理旧对象防止超限
- **警报功能**: 支持实时买卖点通知
- **多时间框架**: 适用于任何时间级别
## 使用建议
### 新手用户
1. 从精简版开始使用
2. 在日线级别练习识别
3. 先关注分型和笔的形成
4. 逐步学习中枢概念
### 进阶用户
1. 使用完整版深入分析
2. 结合多个时间级别
3. 自定义参数优化信号
4. 结合其他技术分析工具
### 实盘交易
1. 充分回测验证信号
2. 设置合理的风险控制
3. 结合基本面分析
4. 不要盲目依赖单一信号
## 免责声明
⚠️ **重要提示**
- 本指标仅供学习和研究使用
- 不构成投资建议
- 投资有风险,入市需谨慎
- 请结合自身风险承受能力使用
## 技术支持
如果在使用过程中遇到问题:
1. 查看使用说明文档
2. 检查 Pine Script 版本兼容性
3. 确认参数设置是否合理
4. 参考缠论相关书籍和资料
## 版本更新
- **v1.0**: 初始版本,实现核心功能
- **v1.1**: 性能优化,添加精简版
- **v1.2**: 改进中枢识别算法
- **v1.3**: 增强买卖点逻辑
---
*愿此工具能助您在技术分析的道路上更进一步!*
+136
View File
@@ -0,0 +1,136 @@
//@version=6
strategy("布林带ATR反转策略", shorttitle="BBB_ATR", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100, calc_on_every_tick=true)
// 输入参数
bb_length = input.int(90, "布林带长度", minval=10, maxval=200)
atr_multiplier = input.float(3.0, "ATR乘数(轨道)", minval=1.0, maxval=10.0, step=0.1)
atr_stop_multiplier = input.float(3.0, "ATR乘数(止损)", minval=0.5, maxval=5.0, step=0.1)
atr_length = input.int(9, "ATR计算周期", minval=5, maxval=50)
// 显示设置
show_bands = input.bool(true, "显示布林带")
show_signals = input.bool(true, "显示信号")
// 计算移动平均线(中线)
bb_middle = ta.sma(close, bb_length)
// 计算ATR
atr_value = ta.atr(atr_length)
// 计算上下轨
bb_upper = bb_middle + (atr_multiplier * atr_value)
bb_lower = bb_middle - (atr_multiplier * atr_value)
// 显示布林带
plot(show_bands ? bb_middle : na, "中线", color=color.blue, linewidth=2)
plot(show_bands ? bb_upper : na, "上轨", color=color.red, linewidth=2)
plot(show_bands ? bb_lower : na, "下轨", color=color.green, linewidth=2)
// 交易条件
// 做空条件:价格突破上轨
short_condition = close > bb_upper and close[1] <= bb_upper[1]
// 做多条件:价格跌破下轨
long_condition = close < bb_lower and close[1] >= bb_lower[1]
// 做空止盈条件:价格跌破下轨
short_take_profit = close < bb_lower
// 做多止盈条件:价格突破上轨
long_take_profit = close > bb_upper
// 记录入场价格和止损位
var float long_entry_price = na
var float short_entry_price = na
var float long_stop_loss = na
var float short_stop_loss = na
// 执行交易逻辑
if strategy.position_size == 0
if long_condition
strategy.entry("做多", strategy.long)
long_entry_price := close
long_stop_loss := close - (atr_stop_multiplier * atr_value)
if short_condition
strategy.entry("做空", strategy.short)
short_entry_price := close
short_stop_loss := close + (atr_stop_multiplier * atr_value)
// 多头仓位管理
if strategy.position_size > 0
// 止盈:价格突破上轨
if long_take_profit
strategy.close("做多", comment="多头止盈")
long_entry_price := na
long_stop_loss := na
// 止损:价格跌破止损位
else if close <= long_stop_loss
strategy.close("做多", comment="多头止损")
long_entry_price := na
long_stop_loss := na
// 空头仓位管理
if strategy.position_size < 0
// 止盈:价格跌破下轨
if short_take_profit
strategy.close("做空", comment="空头止盈")
short_entry_price := na
short_stop_loss := na
// 止损:价格突破止损位
else if close >= short_stop_loss
strategy.close("做空", comment="空头止损")
short_entry_price := na
short_stop_loss := na
// 显示信号
if show_signals
if long_condition and strategy.position_size == 0
label.new(bar_index, low, "做多", color=color.green, style=label.style_label_up, size=size.normal, textcolor=color.white)
if short_condition and strategy.position_size == 0
label.new(bar_index, high, "做空", color=color.red, style=label.style_label_down, size=size.normal, textcolor=color.white)
if long_take_profit and strategy.position_size > 0
label.new(bar_index, high, "多头止盈", color=color.green, style=label.style_label_down, size=size.small, textcolor=color.white)
if short_take_profit and strategy.position_size < 0
label.new(bar_index, low, "空头止盈", color=color.red, style=label.style_label_up, size=size.small, textcolor=color.white)
// 显示止损线
plot(strategy.position_size > 0 and not na(long_stop_loss) ? long_stop_loss : na, "多头止损", color=color.red, style=plot.style_linebr, linewidth=1)
plot(strategy.position_size < 0 and not na(short_stop_loss) ? short_stop_loss : na, "空头止损", color=color.red, style=plot.style_linebr, linewidth=1)
// 信息表格
if barstate.islast
var table info_table = table.new(position.top_right, 2, 10, bgcolor=color.white, border_width=1)
table.cell(info_table, 0, 0, "布林带ATR反转策略", text_color=color.black, bgcolor=color.gray)
table.cell(info_table, 1, 0, "", text_color=color.black, bgcolor=color.gray)
table.cell(info_table, 0, 1, "布林带长度", text_color=color.black)
table.cell(info_table, 1, 1, str.tostring(bb_length), text_color=color.black)
table.cell(info_table, 0, 2, "ATR轨道乘数", text_color=color.black)
table.cell(info_table, 1, 2, str.tostring(atr_multiplier), text_color=color.black)
table.cell(info_table, 0, 3, "ATR止损乘数", text_color=color.black)
table.cell(info_table, 1, 3, str.tostring(atr_stop_multiplier), text_color=color.black)
table.cell(info_table, 0, 4, "当前ATR", text_color=color.black)
table.cell(info_table, 1, 4, str.tostring(math.round(atr_value, 4)), text_color=color.black)
table.cell(info_table, 0, 5, "上轨价位", text_color=color.black)
table.cell(info_table, 1, 5, str.tostring(math.round(bb_upper, 2)), text_color=color.black)
table.cell(info_table, 0, 6, "下轨价位", text_color=color.black)
table.cell(info_table, 1, 6, str.tostring(math.round(bb_lower, 2)), text_color=color.black)
table.cell(info_table, 0, 7, "当前价格", text_color=color.black)
table.cell(info_table, 1, 7, str.tostring(math.round(close, 2)), text_color=color.black)
table.cell(info_table, 0, 8, "仓位状态", text_color=color.black)
position_text = strategy.position_size > 0 ? "多头" : strategy.position_size < 0 ? "空头" : "空仓"
table.cell(info_table, 1, 8, position_text, text_color=color.black)
table.cell(info_table, 0, 9, "价格位置", text_color=color.black)
price_position = close > bb_upper ? "上轨之上" : close < bb_lower ? "下轨之下" : "轨道之间"
table.cell(info_table, 1, 9, price_position, text_color=color.black)
+133
View File
@@ -0,0 +1,133 @@
//@version=5
strategy("布林带反转策略", shorttitle="BB_REV", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100, calc_on_every_tick=true)
// 输入参数
bb_length = input.int(90, "布林带长度", minval=10, maxval=200)
bb_mult = input.float(3.0, "布林带倍数", minval=1.0, maxval=10.0, step=0.1)
atr_length = input.int(14, "ATR计算周期", minval=5, maxval=50)
atr_mult = input.float(1.0, "止损ATR倍数", minval=0.5, maxval=5.0, step=0.1)
// 显示设置
show_bands = input.bool(true, "显示布林带")
show_signals = input.bool(true, "显示信号")
// 计算布林带(保持标准差计算)
bb_basis = ta.sma(close, bb_length)
bb_dev = bb_mult * ta.stdev(close, bb_length)
bb_upper = bb_basis + bb_dev
bb_lower = bb_basis - bb_dev
// 计算ATR(仅用于止损)
atr_value = ta.atr(atr_length)
// 显示布林带
plot(show_bands ? bb_basis : na, "中线", color=color.blue, linewidth=2)
plot(show_bands ? bb_upper : na, "上轨", color=color.red, linewidth=2)
plot(show_bands ? bb_lower : na, "下轨", color=color.green, linewidth=2)
// 交易条件
// 做空条件:价格突破上轨
short_condition = close > bb_upper and close[1] <= bb_upper[1]
// 做多条件:价格跌破下轨
long_condition = close < bb_lower and close[1] >= bb_lower[1]
// 做空止盈条件:价格跌破下轨
short_take_profit = close < bb_lower
// 做多止盈条件:价格突破上轨
long_take_profit = close > bb_upper
// 记录入场价格和止损位
var float long_entry_price = na
var float short_entry_price = na
var float long_stop_loss = na
var float short_stop_loss = na
// 执行交易逻辑
if strategy.position_size == 0
if long_condition
strategy.entry("做多", strategy.long)
long_entry_price := close
long_stop_loss := close - (atr_mult * atr_value)
if short_condition
strategy.entry("做空", strategy.short)
short_entry_price := close
short_stop_loss := close + (atr_mult * atr_value)
// 多头仓位管理
if strategy.position_size > 0
// 止盈:价格突破上轨
if long_take_profit
strategy.close("做多", comment="多头止盈")
long_entry_price := na
long_stop_loss := na
// 止损:价格跌破止损位
else if close <= long_stop_loss
strategy.close("做多", comment="多头止损")
long_entry_price := na
long_stop_loss := na
// 空头仓位管理
if strategy.position_size < 0
// 止盈:价格跌破下轨
if short_take_profit
strategy.close("做空", comment="空头止盈")
short_entry_price := na
short_stop_loss := na
// 止损:价格突破止损位
else if close >= short_stop_loss
strategy.close("做空", comment="空头止损")
short_entry_price := na
short_stop_loss := na
// 显示信号
if show_signals
if long_condition and strategy.position_size == 0
label.new(bar_index, low, "做多", color=color.green, style=label.style_label_up, size=size.normal, textcolor=color.white)
if short_condition and strategy.position_size == 0
label.new(bar_index, high, "做空", color=color.red, style=label.style_label_down, size=size.normal, textcolor=color.white)
if long_take_profit and strategy.position_size > 0
label.new(bar_index, high, "多头止盈", color=color.green, style=label.style_label_down, size=size.small, textcolor=color.white)
if short_take_profit and strategy.position_size < 0
label.new(bar_index, low, "空头止盈", color=color.red, style=label.style_label_up, size=size.small, textcolor=color.white)
// 显示止损线
plot(strategy.position_size > 0 and not na(long_stop_loss) ? long_stop_loss : na, "多头止损", color=color.red, style=plot.style_linebr, linewidth=1)
plot(strategy.position_size < 0 and not na(short_stop_loss) ? short_stop_loss : na, "空头止损", color=color.red, style=plot.style_linebr, linewidth=1)
// 信息表格
if barstate.islast
var table info_table = table.new(position.top_right, 2, 10, bgcolor=color.white, border_width=1)
table.cell(info_table, 0, 0, "布林带反转策略", text_color=color.black, bgcolor=color.gray)
table.cell(info_table, 1, 0, "", text_color=color.black, bgcolor=color.gray)
table.cell(info_table, 0, 1, "布林带长度", text_color=color.black)
table.cell(info_table, 1, 1, str.tostring(bb_length), text_color=color.black)
table.cell(info_table, 0, 2, "布林带倍数", text_color=color.black)
table.cell(info_table, 1, 2, str.tostring(bb_mult), text_color=color.black)
table.cell(info_table, 0, 3, "ATR止损倍数", text_color=color.black)
table.cell(info_table, 1, 3, str.tostring(atr_mult), text_color=color.black)
table.cell(info_table, 0, 4, "当前ATR", text_color=color.black)
table.cell(info_table, 1, 4, str.tostring(math.round(atr_value, 4)), text_color=color.black)
table.cell(info_table, 0, 5, "上轨价位", text_color=color.black)
table.cell(info_table, 1, 5, str.tostring(math.round(bb_upper, 2)), text_color=color.black)
table.cell(info_table, 0, 6, "下轨价位", text_color=color.black)
table.cell(info_table, 1, 6, str.tostring(math.round(bb_lower, 2)), text_color=color.black)
table.cell(info_table, 0, 7, "当前价格", text_color=color.black)
table.cell(info_table, 1, 7, str.tostring(math.round(close, 2)), text_color=color.black)
table.cell(info_table, 0, 8, "仓位状态", text_color=color.black)
position_text = strategy.position_size > 0 ? "多头" : strategy.position_size < 0 ? "空头" : "空仓"
table.cell(info_table, 1, 8, position_text, text_color=color.black)
table.cell(info_table, 0, 9, "价格位置", text_color=color.black)
price_position = close > bb_upper ? "上轨之上" : close < bb_lower ? "下轨之下" : "轨道之间"
table.cell(info_table, 1, 9, price_position, text_color=color.black)
+289
View File
@@ -0,0 +1,289 @@
//@version=6
indicator("缠论系统 - Chan Theory", shorttitle="缠论", overlay=true, max_lines_count=500, max_labels_count=500)
// ================== 参数设置 ==================
show_merged_klines = input.bool(true, "显示合并K线", group="显示设置")
show_bi = input.bool(true, "显示笔", group="显示设置")
show_segment = input.bool(true, "显示线段", group="显示设置")
show_zhongshu = input.bool(true, "显示中枢", group="显示设置")
show_signals = input.bool(true, "显示买卖点", group="显示设置")
bi_color = input.color(color.blue, "笔的颜色", group="颜色设置")
segment_color = input.color(color.red, "线段颜色", group="颜色设置")
zhongshu_color = input.color(color.gray, "中枢颜色", group="颜色设置")
// ================== 数据结构定义 ==================
type KLine
float high
float low
float open
float close
int index
type FenXing
int type // 1为顶分型,-1为底分型
float price
int index
bool valid
type Bi
FenXing start_fx
FenXing end_fx
bool valid
type Segment
Bi start_bi
Bi end_bi
bool valid
type ZhongShu
float high
float low
int start_index
int end_index
bool valid
// ================== K线合并函数 ==================
merge_klines(prev_kline, curr_kline) =>
var merged = KLine.new()
// 判断包含关系
prev_includes_curr = prev_kline.high >= curr_kline.high and prev_kline.low <= curr_kline.low
curr_includes_prev = curr_kline.high >= prev_kline.high and curr_kline.low <= prev_kline.low
if prev_includes_curr or curr_includes_prev
// 有包含关系,进行合并
if prev_kline.high >= prev_kline.low // 向上趋势中的合并
merged.high := math.max(prev_kline.high, curr_kline.high)
merged.low := math.max(prev_kline.low, curr_kline.low)
else // 向下趋势中的合并
merged.high := math.min(prev_kline.high, curr_kline.high)
merged.low := math.min(prev_kline.low, curr_kline.low)
merged.open := prev_kline.open
merged.close := curr_kline.close
merged.index := curr_kline.index
[merged, true]
else
// 无包含关系,返回当前K线
[curr_kline, false]
// ================== 分型识别函数 ==================
check_fenxing(k1, k2, k3) =>
var fx = FenXing.new()
// 顶分型:中间K线的高点是最高的,低点也是最高的
if k2.high > k1.high and k2.high > k3.high and k2.low > k1.low and k2.low > k3.low
fx.type := 1
fx.price := k2.high
fx.index := k2.index
fx.valid := true
fx
// 底分型:中间K线的低点是最低的,高点也是最低的
else if k2.low < k1.low and k2.low < k3.low and k2.high < k1.high and k2.high < k3.high
fx.type := -1
fx.price := k2.low
fx.index := k2.index
fx.valid := true
fx
else
fx.valid := false
fx
// ================== 笔的识别函数 ==================
create_bi(start_fx, end_fx) =>
var bi = Bi.new()
// 检查笔的有效性
if start_fx.valid and end_fx.valid and start_fx.type != end_fx.type and start_fx.index < end_fx.index
bi.start_fx := start_fx
bi.end_fx := end_fx
bi.valid := true
bi
else
bi.valid := false
bi
// ================== 线段识别函数 ==================
check_segment_break(bi_array) =>
// 简化的线段破坏判断逻辑
// 当新笔突破前面第三根笔的端点时,认为线段被破坏
bool segment_break = false
if array.size(bi_array) >= 4
current_bi = array.get(bi_array, array.size(bi_array) - 1)
third_bi = array.get(bi_array, array.size(bi_array) - 4)
if current_bi.valid and third_bi.valid
if current_bi.start_fx.type == 1 // 向下笔
segment_break := current_bi.end_fx.price < third_bi.end_fx.price
else // 向上笔
segment_break := current_bi.end_fx.price > third_bi.end_fx.price
segment_break
// ================== 中枢识别函数 ==================
find_zhongshu(bi_array) =>
var zhongshu_array = array.new<ZhongShu>()
if array.size(bi_array) >= 3
for i = 0 to array.size(bi_array) - 3
bi1 = array.get(bi_array, i)
bi2 = array.get(bi_array, i + 1)
bi3 = array.get(bi_array, i + 2)
if bi1.valid and bi2.valid and bi3.valid
// 计算重叠区间
high1 = math.max(bi1.start_fx.price, bi1.end_fx.price)
low1 = math.min(bi1.start_fx.price, bi1.end_fx.price)
high2 = math.max(bi2.start_fx.price, bi2.end_fx.price)
low2 = math.min(bi2.start_fx.price, bi2.end_fx.price)
high3 = math.max(bi3.start_fx.price, bi3.end_fx.price)
low3 = math.min(bi3.start_fx.price, bi3.end_fx.price)
overlap_high = math.min(math.min(high1, high2), high3)
overlap_low = math.max(math.max(low1, low2), low3)
if overlap_high > overlap_low
var zs = ZhongShu.new()
zs.high := overlap_high
zs.low := overlap_low
zs.start_index := bi1.start_fx.index
zs.end_index := bi3.end_fx.index
zs.valid := true
array.push(zhongshu_array, zs)
zhongshu_array
// ================== 买卖点识别函数 ==================
identify_trading_signals(bi_array, zhongshu_array) =>
var buy_signals = array.new<int>()
var sell_signals = array.new<int>()
if array.size(bi_array) >= 2 and array.size(zhongshu_array) >= 1
current_bi = array.get(bi_array, array.size(bi_array) - 1)
latest_zs = array.get(zhongshu_array, array.size(zhongshu_array) - 1)
if current_bi.valid and latest_zs.valid
// 一买:价格跌破中枢下沿后的第一次回调
if current_bi.end_fx.type == -1 and current_bi.end_fx.price < latest_zs.low
array.push(buy_signals, current_bi.end_fx.index)
// 一卖:价格突破中枢上沿后的第一次回调
if current_bi.end_fx.type == 1 and current_bi.end_fx.price > latest_zs.high
array.push(sell_signals, current_bi.end_fx.index)
[buy_signals, sell_signals]
// ================== 主逻辑 ==================
var merged_klines = array.new<KLine>()
var fenxing_array = array.new<FenXing>()
var bi_array = array.new<Bi>()
var segment_array = array.new<Segment>()
// 当前K线数据
current_kline = KLine.new(high, low, open, close, bar_index)
// K线合并处理
if array.size(merged_klines) > 0
last_merged = array.get(merged_klines, array.size(merged_klines) - 1)
[new_kline, is_merged] = merge_klines(last_merged, current_kline)
if is_merged
array.set(merged_klines, array.size(merged_klines) - 1, new_kline)
else
array.push(merged_klines, new_kline)
else
array.push(merged_klines, current_kline)
// 分型识别
if array.size(merged_klines) >= 3
k1 = array.get(merged_klines, array.size(merged_klines) - 3)
k2 = array.get(merged_klines, array.size(merged_klines) - 2)
k3 = array.get(merged_klines, array.size(merged_klines) - 1)
fx = check_fenxing(k1, k2, k3)
if fx.valid
array.push(fenxing_array, fx)
// 笔的构建
if array.size(fenxing_array) >= 2
for i = 0 to array.size(fenxing_array) - 2
start_fx = array.get(fenxing_array, i)
end_fx = array.get(fenxing_array, i + 1)
bi = create_bi(start_fx, end_fx)
if bi.valid
array.push(bi_array, bi)
// 中枢识别
zhongshu_array = find_zhongshu(bi_array)
// 买卖点识别
[buy_signals, sell_signals] = identify_trading_signals(bi_array, zhongshu_array)
// ================== 绘图显示 ==================
// 显示合并K线
if show_merged_klines and array.size(merged_klines) > 1
last_kline = array.get(merged_klines, array.size(merged_klines) - 1)
prev_kline = array.get(merged_klines, array.size(merged_klines) - 2)
line.new(bar_index[1], prev_kline.close, bar_index, last_kline.close, color=color.yellow, width=1)
// 显示笔
if show_bi and array.size(bi_array) > 0
for i = 0 to array.size(bi_array) - 1
bi = array.get(bi_array, i)
if bi.valid
line.new(bi.start_fx.index, bi.start_fx.price, bi.end_fx.index, bi.end_fx.price,
color=bi_color, width=2, style=line.style_solid)
// 显示分型
if array.size(fenxing_array) > 0
last_fx = array.get(fenxing_array, array.size(fenxing_array) - 1)
if last_fx.valid and last_fx.index == bar_index
if last_fx.type == 1
label.new(bar_index, last_fx.price, "顶", color=color.red, style=label.style_label_down, size=size.small)
else
label.new(bar_index, last_fx.price, "底", color=color.green, style=label.style_label_up, size=size.small)
// 显示中枢
if show_zhongshu and array.size(zhongshu_array) > 0
for i = 0 to array.size(zhongshu_array) - 1
zs = array.get(zhongshu_array, i)
if zs.valid
box.new(zs.start_index, zs.high, zs.end_index, zs.low, border_color=zhongshu_color, bgcolor=color.new(zhongshu_color, 90))
// 显示买卖点
if show_signals
if array.size(buy_signals) > 0
for i = 0 to array.size(buy_signals) - 1
signal_index = array.get(buy_signals, i)
if signal_index == bar_index
label.new(bar_index, low, "买", color=color.green, style=label.style_label_up, size=size.normal)
if array.size(sell_signals) > 0
for i = 0 to array.size(sell_signals) - 1
signal_index = array.get(sell_signals, i)
if signal_index == bar_index
label.new(bar_index, high, "卖", color=color.red, style=label.style_label_down, size=size.normal)
// ================== 警报设置 ==================
alertcondition(array.size(buy_signals) > 0 and array.get(buy_signals, array.size(buy_signals) - 1) == bar_index,
title="缠论买点", message="发现缠论买点信号")
alertcondition(array.size(sell_signals) > 0 and array.get(sell_signals, array.size(sell_signals) - 1) == bar_index,
title="缠论卖点", message="发现缠论卖点信号")
// ================== 信息面板 ==================
if barstate.islast
var table info_table = table.new(position.top_right, 2, 6, bgcolor=color.white, border_width=1)
table.cell(info_table, 0, 0, "缠论统计", text_color=color.black, text_size=size.normal)
table.cell(info_table, 1, 0, "", text_color=color.black)
table.cell(info_table, 0, 1, "合并K线数", text_color=color.black)
table.cell(info_table, 1, 1, str.tostring(array.size(merged_klines)), text_color=color.black)
table.cell(info_table, 0, 2, "分型数量", text_color=color.black)
table.cell(info_table, 1, 2, str.tostring(array.size(fenxing_array)), text_color=color.black)
table.cell(info_table, 0, 3, "笔数量", text_color=color.black)
table.cell(info_table, 1, 3, str.tostring(array.size(bi_array)), text_color=color.black)
table.cell(info_table, 0, 4, "中枢数量", text_color=color.black)
table.cell(info_table, 1, 4, str.tostring(array.size(zhongshu_array)), text_color=color.black)
table.cell(info_table, 0, 5, "当前级别", text_color=color.black)
table.cell(info_table, 1, 5, "1分钟", text_color=color.black)
+154
View File
@@ -0,0 +1,154 @@
//@version=6
indicator("缠论结合律版", shorttitle="结合律", overlay=true, max_lines_count=100, max_labels_count=100)
// 参数
min_gap = input.int(3, "分型间隔", minval=1, maxval=20)
show_fractals = input.bool(true, "显示分型")
show_strokes = input.bool(true, "显示笔")
show_filtered = input.bool(true, "显示过滤后分型")
// 数据类型
type Fractal
int bar_index
float price
string type
bool is_valid // 是否为有效分型(非中继)
// 全局变量
var all_fractals = array.new<Fractal>() // 所有分型
var valid_fractals = array.new<Fractal>() // 过滤后的分型
var stroke_lines = array.new<line>()
// 分型识别
is_high = high[1] > high[0] and high[1] > high[2]
is_low = low[1] < low[0] and low[1] < low[2]
// 距离检查
distance_ok(new_bar) =>
result = true
if array.size(all_fractals) > 0
last_fractal = array.get(all_fractals, array.size(all_fractals) - 1)
if new_bar - last_fractal.bar_index < min_gap
result := false
result
// 添加原始分型
if is_high and distance_ok(bar_index[1])
new_fractal = Fractal.new(bar_index[1], high[1], "top", true)
array.push(all_fractals, new_fractal)
if array.size(all_fractals) > 100
array.shift(all_fractals)
if is_low and distance_ok(bar_index[1])
new_fractal = Fractal.new(bar_index[1], low[1], "bottom", true)
array.push(all_fractals, new_fractal)
if array.size(all_fractals) > 100
array.shift(all_fractals)
// 显示原始分型
if show_fractals
if is_high and distance_ok(bar_index[1])
label.new(bar_index[1], high[1], "顶", color=color.red, style=label.style_label_down, size=size.tiny)
if is_low and distance_ok(bar_index[1])
label.new(bar_index[1], low[1], "底", color=color.green, style=label.style_label_up, size=size.tiny)
// 应用结合律,过滤中继分型
filter_fractals() =>
// 清空有效分型数组
array.clear(valid_fractals)
if array.size(all_fractals) <= 1
// 如果分型数量不足,直接返回
if array.size(all_fractals) == 1
array.push(valid_fractals, array.get(all_fractals, 0))
else
// 第一个分型总是有效的
first_fractal = array.get(all_fractals, 0)
array.push(valid_fractals, first_fractal)
// 从第二个分型开始处理
i = 1
while i < array.size(all_fractals)
current_fractal = array.get(all_fractals, i)
last_valid = array.get(valid_fractals, array.size(valid_fractals) - 1)
if current_fractal.type != last_valid.type
// 不同类型,直接添加
array.push(valid_fractals, current_fractal)
i += 1
else
// 相同类型,找到最极端的分型
extreme_fractal = current_fractal
extreme_idx = i
// 继续查找同类型的更极端分型
j = i + 1
while j < array.size(all_fractals)
next_fractal = array.get(all_fractals, j)
if next_fractal.type == current_fractal.type
// 同类型,比较极端程度
if current_fractal.type == "top"
if next_fractal.price > extreme_fractal.price
extreme_fractal := next_fractal
extreme_idx := j
else // bottom
if next_fractal.price < extreme_fractal.price
extreme_fractal := next_fractal
extreme_idx := j
j += 1
else
// 不同类型,结束查找
break
// 添加最极端的分型
array.push(valid_fractals, extreme_fractal)
i := j // 跳到不同类型的分型
// 每根K线更新
if barstate.isconfirmed
// 过滤分型
filter_fractals()
// 清理旧笔
if array.size(stroke_lines) > 0
for i = 0 to array.size(stroke_lines) - 1
line.delete(array.get(stroke_lines, i))
array.clear(stroke_lines)
// 绘制笔(连接有效分型)
if show_strokes and array.size(valid_fractals) >= 2
for i = 0 to array.size(valid_fractals) - 2
current_fractal = array.get(valid_fractals, i)
next_fractal = array.get(valid_fractals, i + 1)
// 检查距离
distance = bar_index - current_fractal.bar_index
if distance <= 500
stroke_line = line.new(current_fractal.bar_index, current_fractal.price, next_fractal.bar_index, next_fractal.price, color=color.blue, width=2, style=line.style_solid)
array.push(stroke_lines, stroke_line)
// 显示过滤后的分型
if show_filtered and barstate.islast
for i = 0 to array.size(valid_fractals) - 1
fractal = array.get(valid_fractals, i)
if fractal.type == "top"
label.new(fractal.bar_index, fractal.price, "T", color=color.yellow, style=label.style_label_down, size=size.small)
else
label.new(fractal.bar_index, fractal.price, "B", color=color.orange, style=label.style_label_up, size=size.small)
// 信息显示
if barstate.islast
var table info = table.new(position.top_right, 2, 5, bgcolor=color.white, border_width=1)
table.cell(info, 0, 0, "缠论结合律版", text_color=color.black, text_size=size.small)
table.cell(info, 1, 0, "", text_color=color.black)
table.cell(info, 0, 1, "原始分型", text_color=color.black)
table.cell(info, 1, 1, str.tostring(array.size(all_fractals)), text_color=color.black)
table.cell(info, 0, 2, "有效分型", text_color=color.black)
table.cell(info, 1, 2, str.tostring(array.size(valid_fractals)), text_color=color.black)
table.cell(info, 0, 3, "笔数", text_color=color.black)
table.cell(info, 1, 3, str.tostring(array.size(stroke_lines)), text_color=color.black)
table.cell(info, 0, 4, "分型间隔", text_color=color.black)
table.cell(info, 1, 4, str.tostring(min_gap), text_color=color.black)
+114
View File
@@ -0,0 +1,114 @@
//@version=6
indicator("缠论正确版", shorttitle="缠论正确", overlay=true, max_lines_count=100, max_labels_count=100)
// 简单参数
min_gap = input.int(5, "分型间隔")
show_fractals = input.bool(true, "显示分型")
show_strokes = input.bool(true, "显示笔")
// 数据类型
type Fractal
int bar_index
float price
string type // "top" or "bottom"
// 全局变量
var fractals = array.new<Fractal>()
var stroke_lines = array.new<line>()
// 简单分型检测
is_high = high[1] > high[0] and high[1] > high[2]
is_low = low[1] < low[0] and low[1] < low[2]
// 距离检查
distance_ok(new_bar) =>
result = true
if array.size(fractals) > 0
last_fractal = array.get(fractals, array.size(fractals) - 1)
if new_bar - last_fractal.bar_index < min_gap
result := false
result
// 添加分型
if is_high and distance_ok(bar_index[1])
new_fractal = Fractal.new(bar_index[1], high[1], "top")
array.push(fractals, new_fractal)
if array.size(fractals) > 50
array.shift(fractals)
if is_low and distance_ok(bar_index[1])
new_fractal = Fractal.new(bar_index[1], low[1], "bottom")
array.push(fractals, new_fractal)
if array.size(fractals) > 50
array.shift(fractals)
// 显示分型
if show_fractals
if is_high and distance_ok(bar_index[1])
label.new(bar_index[1], high[1], "顶", color=color.red, style=label.style_label_down, size=size.small)
if is_low and distance_ok(bar_index[1])
label.new(bar_index[1], low[1], "底", color=color.green, style=label.style_label_up, size=size.small)
// 重新构建所有笔(满足结合律)
if barstate.isconfirmed and show_strokes
// 清理旧笔
if array.size(stroke_lines) > 0
for i = 0 to array.size(stroke_lines) - 1
line.delete(array.get(stroke_lines, i))
array.clear(stroke_lines)
// 构建连续的笔序列(处理中继分型)
if array.size(fractals) >= 2
var current_start_idx = 0
var current_direction = ""
// 确定起始方向
if array.size(fractals) >= 2
first_fractal = array.get(fractals, 0)
second_fractal = array.get(fractals, 1)
if first_fractal.type != second_fractal.type
current_direction := first_fractal.type
// 从第二个分型开始遍历
for i = 1 to array.size(fractals) - 1
current_fractal = array.get(fractals, i)
// 如果找到不同类型的分型,结束当前笔
if current_fractal.type != current_direction
start_fractal = array.get(fractals, current_start_idx)
// 绘制笔
distance = bar_index - start_fractal.bar_index
if distance <= 500
stroke_line = line.new(start_fractal.bar_index, start_fractal.price, current_fractal.bar_index, current_fractal.price, color=color.blue, width=2, style=line.style_solid)
array.push(stroke_lines, stroke_line)
// 开始新笔
current_start_idx := i
current_direction := current_fractal.type
else
// 同类型分型,处理中继
start_fractal = array.get(fractals, current_start_idx)
// 如果当前分型更极端,更新起始点
if current_direction == "top"
if current_fractal.price > start_fractal.price
current_start_idx := i
else // bottom
if current_fractal.price < start_fractal.price
current_start_idx := i
// 信息显示
if barstate.islast
var table info = table.new(position.top_right, 2, 4, bgcolor=color.white, border_width=1)
table.cell(info, 0, 0, "缠论正确版", text_color=color.black, text_size=size.small)
table.cell(info, 1, 0, "", text_color=color.black)
table.cell(info, 0, 1, "分型数", text_color=color.black)
table.cell(info, 1, 1, str.tostring(array.size(fractals)), text_color=color.black)
table.cell(info, 0, 2, "笔数", text_color=color.black)
table.cell(info, 1, 2, str.tostring(array.size(stroke_lines)), text_color=color.black)
table.cell(info, 0, 3, "分型间隔", text_color=color.black)
table.cell(info, 1, 3, str.tostring(min_gap), text_color=color.black)
+102
View File
@@ -0,0 +1,102 @@
//@version=6
indicator("缠论调试版", shorttitle="缠论调试", overlay=true, max_lines_count=200, max_labels_count=200)
// ================== 参数设置 ==================
show_fenxing = input.bool(true, "显示分型", group="显示设置")
show_bi = input.bool(true, "显示笔", group="显示设置")
debug_mode = input.bool(true, "调试模式", group="显示设置")
// 缠论参数
min_bars_between = input.int(3, "分型最小间隔", minval=1, maxval=20, group="缠论参数")
// ================== 数据类型定义 ==================
type FractalPoint
int bar_index
float price
string fractal_type
bool confirmed
// ================== 全局变量 ==================
var fractal_points = array.new<FractalPoint>()
var bi_lines = array.new<line>()
// ================== 简单分型识别 ==================
// 检查高点分型
is_pivot_high = high[1] > high[0] and high[1] > high[2]
// 检查低点分型
is_pivot_low = low[1] < low[0] and low[1] < low[2]
// ================== 距离过滤 ==================
distance_ok(new_bar, new_type) =>
if debug_mode
true
else
result = true
if array.size(fractal_points) > 0
last_fractal = array.get(fractal_points, array.size(fractal_points) - 1)
bar_distance = new_bar - last_fractal.bar_index
if bar_distance < min_bars_between
result := false
result
// ================== 添加分型 ==================
var bool fractal_added = false
fractal_added := false
if is_pivot_high and distance_ok(bar_index[1], "top")
new_fractal = FractalPoint.new(bar_index[1], high[1], "top", true)
array.push(fractal_points, new_fractal)
fractal_added := true
if array.size(fractal_points) > 100
array.shift(fractal_points)
if is_pivot_low and distance_ok(bar_index[1], "bottom")
new_fractal = FractalPoint.new(bar_index[1], low[1], "bottom", true)
array.push(fractal_points, new_fractal)
fractal_added := true
if array.size(fractal_points) > 100
array.shift(fractal_points)
// ================== 显示分型 ==================
if show_fenxing
if is_pivot_high and distance_ok(bar_index[1], "top")
label.new(bar_index[1], high[1], "顶", color=color.red, style=label.style_label_down, size=size.small)
if is_pivot_low and distance_ok(bar_index[1], "bottom")
label.new(bar_index[1], low[1], "底", color=color.green, style=label.style_label_up, size=size.small)
// ================== 构建笔 ==================
if fractal_added and array.size(fractal_points) >= 2
last_fractal = array.get(fractal_points, array.size(fractal_points) - 1)
second_last_fractal = array.get(fractal_points, array.size(fractal_points) - 2)
// 如果最近两个分型类型不同,构建笔
if last_fractal.fractal_type != second_last_fractal.fractal_type
// 检查bar_index距离是否在合理范围内(Pine Script限制)
bar_distance = bar_index - second_last_fractal.bar_index
if bar_distance <= 500 // 限制在500根K线范围内
// 绘制笔
if show_bi
new_line = line.new(second_last_fractal.bar_index, second_last_fractal.price, last_fractal.bar_index, last_fractal.price, color=color.blue, width=2, style=line.style_solid)
array.push(bi_lines, new_line)
// 限制笔的数量
if array.size(bi_lines) > 200
old_line = array.shift(bi_lines)
line.delete(old_line)
// ================== 信息面板 ==================
if barstate.islast
var info_table = table.new(position.top_right, 2, 5, bgcolor=color.white, border_width=1)
table.cell(info_table, 0, 0, "缠论调试版", text_color=color.black, text_size=size.small)
table.cell(info_table, 1, 0, "", text_color=color.black)
table.cell(info_table, 0, 1, "分型数", text_color=color.black)
table.cell(info_table, 1, 1, str.tostring(array.size(fractal_points)), text_color=color.black)
table.cell(info_table, 0, 2, "笔数", text_color=color.black)
table.cell(info_table, 1, 2, str.tostring(array.size(bi_lines)), text_color=color.black)
table.cell(info_table, 0, 3, "调试模式", text_color=color.black)
table.cell(info_table, 1, 3, debug_mode ? "开" : "关", text_color=color.black)
table.cell(info_table, 0, 4, "当前K线", text_color=color.black)
table.cell(info_table, 1, 4, str.tostring(bar_index), text_color=color.black)
+1
View File
@@ -0,0 +1 @@
+89
View File
@@ -0,0 +1,89 @@
//@version=6
indicator("缠论最终版", shorttitle="缠论最终", overlay=true, max_lines_count=200, max_labels_count=200)
// ================== 参数设置 ==================
show_fenxing = input.bool(true, "显示分型", group="显示设置")
show_bi = input.bool(true, "显示笔", group="显示设置")
min_bars_between = input.int(3, "分型最小间隔", minval=1, maxval=20, group="缠论参数")
// ================== 数据类型定义 ==================
type FractalPoint
int bar_index
float price
string fractal_type
// ================== 全局变量 ==================
var fractal_points = array.new<FractalPoint>()
var bi_lines = array.new<line>()
// ================== 简单分型识别 ==================
// 基于原始K线的简单分型
is_top_fractal = high[1] > high[0] and high[1] > high[2]
is_bottom_fractal = low[1] < low[0] and low[1] < low[2]
// ================== 距离过滤 ==================
distance_ok(new_bar) =>
result = true
if array.size(fractal_points) > 0
last_fractal = array.get(fractal_points, array.size(fractal_points) - 1)
bar_distance = new_bar - last_fractal.bar_index
if bar_distance < min_bars_between
result := false
result
// ================== 添加分型 ==================
if is_top_fractal and distance_ok(bar_index[1])
new_fractal = FractalPoint.new(bar_index[1], high[1], "top")
array.push(fractal_points, new_fractal)
if array.size(fractal_points) > 50
array.shift(fractal_points)
if is_bottom_fractal and distance_ok(bar_index[1])
new_fractal = FractalPoint.new(bar_index[1], low[1], "bottom")
array.push(fractal_points, new_fractal)
if array.size(fractal_points) > 50
array.shift(fractal_points)
// ================== 显示分型 ==================
if show_fenxing
if is_top_fractal and distance_ok(bar_index[1])
label.new(bar_index[1], high[1], "顶", color=color.red, style=label.style_label_down, size=size.small)
if is_bottom_fractal and distance_ok(bar_index[1])
label.new(bar_index[1], low[1], "底", color=color.green, style=label.style_label_up, size=size.small)
// ================== 每根K线重新构建所有笔 ==================
if barstate.isconfirmed
// 清理旧笔
if array.size(bi_lines) > 0
for i = 0 to array.size(bi_lines) - 1
line.delete(array.get(bi_lines, i))
array.clear(bi_lines)
// 重新构建所有笔
if array.size(fractal_points) >= 2 and show_bi
for i = 0 to array.size(fractal_points) - 2
current_fractal = array.get(fractal_points, i)
next_fractal = array.get(fractal_points, i + 1)
// 只连接不同类型的分型
if current_fractal.fractal_type != next_fractal.fractal_type
// 检查距离限制
distance = bar_index - current_fractal.bar_index
if distance <= 500
new_line = line.new(current_fractal.bar_index, current_fractal.price, next_fractal.bar_index, next_fractal.price, color=color.blue, width=2, style=line.style_solid)
array.push(bi_lines, new_line)
// ================== 信息面板 ==================
if barstate.islast
var info_table = table.new(position.top_right, 2, 4, bgcolor=color.white, border_width=1)
table.cell(info_table, 0, 0, "缠论最终版", text_color=color.black, text_size=size.small)
table.cell(info_table, 1, 0, "", text_color=color.black)
table.cell(info_table, 0, 1, "分型数", text_color=color.black)
table.cell(info_table, 1, 1, str.tostring(array.size(fractal_points)), text_color=color.black)
table.cell(info_table, 0, 2, "笔数", text_color=color.black)
table.cell(info_table, 1, 2, str.tostring(array.size(bi_lines)), text_color=color.black)
table.cell(info_table, 0, 3, "间隔设置", text_color=color.black)
table.cell(info_table, 1, 3, str.tostring(min_bars_between), text_color=color.black)
+127
View File
@@ -0,0 +1,127 @@
//@version=6
indicator("缠论修复版", shorttitle="修复版", overlay=true, max_lines_count=100, max_labels_count=100)
// 参数
min_gap = input.int(3, "分型间隔", minval=1, maxval=20)
show_fractals = input.bool(true, "显示分型")
show_strokes = input.bool(true, "显示笔")
show_filtered = input.bool(true, "显示过滤后分型")
// 数据类型
type Fractal
int bar_index
float price
string type
bool is_valid
// 全局变量
var all_fractals = array.new<Fractal>()
var valid_fractals = array.new<Fractal>()
var stroke_lines = array.new<line>()
// 分型识别
is_high = high[1] > high[0] and high[1] > high[2]
is_low = low[1] < low[0] and low[1] < low[2]
// 距离检查
distance_ok(new_bar) =>
result = true
if array.size(all_fractals) > 0
last_fractal = array.get(all_fractals, array.size(all_fractals) - 1)
if new_bar - last_fractal.bar_index < min_gap
result := false
result
// 添加原始分型
if is_high and distance_ok(bar_index[1])
new_fractal = Fractal.new(bar_index[1], high[1], "top", true)
array.push(all_fractals, new_fractal)
if array.size(all_fractals) > 100
array.shift(all_fractals)
if is_low and distance_ok(bar_index[1])
new_fractal = Fractal.new(bar_index[1], low[1], "bottom", true)
array.push(all_fractals, new_fractal)
if array.size(all_fractals) > 100
array.shift(all_fractals)
// 显示原始分型
if show_fractals
if is_high and distance_ok(bar_index[1])
label.new(bar_index[1], high[1], "顶", color=color.red, style=label.style_label_down, size=size.tiny)
if is_low and distance_ok(bar_index[1])
label.new(bar_index[1], low[1], "底", color=color.green, style=label.style_label_up, size=size.tiny)
// 每根K线更新
if barstate.isconfirmed
// 清空有效分型数组
array.clear(valid_fractals)
// 应用结合律过滤分型
if array.size(all_fractals) >= 1
array.push(valid_fractals, array.get(all_fractals, 0))
i = 1
while i < array.size(all_fractals)
current_fractal = array.get(all_fractals, i)
last_valid = array.get(valid_fractals, array.size(valid_fractals) - 1)
if current_fractal.type != last_valid.type
array.push(valid_fractals, current_fractal)
i += 1
else
extreme_fractal = current_fractal
j = i + 1
while j < array.size(all_fractals)
next_fractal = array.get(all_fractals, j)
if next_fractal.type == current_fractal.type
if current_fractal.type == "top"
if next_fractal.price > extreme_fractal.price
extreme_fractal := next_fractal
else
if next_fractal.price < extreme_fractal.price
extreme_fractal := next_fractal
j += 1
else
break
array.push(valid_fractals, extreme_fractal)
i := j
// 清理旧笔
if array.size(stroke_lines) > 0
for k = 0 to array.size(stroke_lines) - 1
line.delete(array.get(stroke_lines, k))
array.clear(stroke_lines)
// 绘制笔
if show_strokes and array.size(valid_fractals) >= 2
for m = 0 to array.size(valid_fractals) - 2
current_fractal = array.get(valid_fractals, m)
next_fractal = array.get(valid_fractals, m + 1)
distance = bar_index - current_fractal.bar_index
if distance <= 500
stroke_line = line.new(current_fractal.bar_index, current_fractal.price, next_fractal.bar_index, next_fractal.price, color=color.blue, width=2)
array.push(stroke_lines, stroke_line)
// 显示过滤后的分型
if show_filtered and barstate.islast
for n = 0 to array.size(valid_fractals) - 1
fractal = array.get(valid_fractals, n)
if fractal.type == "top"
label.new(fractal.bar_index, fractal.price, "T", color=color.yellow, style=label.style_label_down, size=size.small)
else
label.new(fractal.bar_index, fractal.price, "B", color=color.orange, style=label.style_label_up, size=size.small)
// 信息显示
if barstate.islast
var table info = table.new(position.top_right, 2, 5, bgcolor=color.white, border_width=1)
table.cell(info, 0, 0, "缠论修复版", text_color=color.black, text_size=size.small)
table.cell(info, 1, 0, "", text_color=color.black)
table.cell(info, 0, 1, "原始分型", text_color=color.black)
table.cell(info, 1, 1, str.tostring(array.size(all_fractals)), text_color=color.black)
table.cell(info, 0, 2, "有效分型", text_color=color.black)
table.cell(info, 1, 2, str.tostring(array.size(valid_fractals)), text_color=color.black)
table.cell(info, 0, 3, "笔数", text_color=color.black)
table.cell(info, 1, 3, str.tostring(array.size(stroke_lines)), text_color=color.black)
table.cell(info, 0, 4, "分型间隔", text_color=color.black)
table.cell(info, 1, 4, str.tostring(min_gap), text_color=color.black)
+172
View File
@@ -0,0 +1,172 @@
//@version=6
indicator("缠论优化版", shorttitle="优化版", overlay=true, max_lines_count=100, max_labels_count=100)
// 优化参数设置
min_gap = input.int(8, "分型最小间隔", minval=5, maxval=20, tooltip="增大此值可减少分型数量")
strict_mode = input.bool(true, "严格分型模式", tooltip="开启后要求高低点都满足条件")
show_original = input.bool(false, "显示原始分型", tooltip="小标签显示所有分型")
show_valid = input.bool(true, "显示有效分型", tooltip="大标签显示过滤后分型")
show_strokes = input.bool(true, "显示笔连接", tooltip="蓝色粗线连接有效分型")
stroke_width = input.int(3, "笔线宽度", minval=1, maxval=5)
// 数据类型
type Fractal
int bar_index
float price
string type // "top" or "bottom"
bool is_extreme // 是否为极值点
// 全局变量
var all_fractals = array.new<Fractal>()
var valid_fractals = array.new<Fractal>()
var stroke_lines = array.new<line>()
// 优化的分型识别
check_fractal() =>
top_found = false
bottom_found = false
if strict_mode
// 严格模式:高低点都要满足条件
if high[1] > high[0] and high[1] > high[2] and low[1] > low[0] and low[1] > low[2]
top_found := true
if low[1] < low[0] and low[1] < low[2] and high[1] < high[0] and high[1] < high[2]
bottom_found := true
else
// 宽松模式:只要高点或低点满足条件
if high[1] > high[0] and high[1] > high[2]
top_found := true
if low[1] < low[0] and low[1] < low[2]
bottom_found := true
[top_found, bottom_found]
// 距离和类型检查
distance_and_type_ok(new_bar, new_type) =>
result = true
if array.size(all_fractals) > 0
last_fractal = array.get(all_fractals, array.size(all_fractals) - 1)
distance = new_bar - last_fractal.bar_index
// 距离检查
if distance < min_gap
result := false
// 同类型分型需要更大间隔
else if last_fractal.type == new_type and distance < min_gap * 1.5
result := false
result
[is_top, is_bottom] = check_fractal()
// 添加分型
if is_top and distance_and_type_ok(bar_index[1], "top")
new_fractal = Fractal.new(bar_index[1], high[1], "top", false)
array.push(all_fractals, new_fractal)
if array.size(all_fractals) > 100
array.shift(all_fractals)
if is_bottom and distance_and_type_ok(bar_index[1], "bottom")
new_fractal = Fractal.new(bar_index[1], low[1], "bottom", false)
array.push(all_fractals, new_fractal)
if array.size(all_fractals) > 100
array.shift(all_fractals)
// 显示原始分型
if show_original
if is_top and distance_and_type_ok(bar_index[1], "top")
label.new(bar_index[1], high[1], "顶", color=color.red, style=label.style_label_down, size=size.tiny)
if is_bottom and distance_and_type_ok(bar_index[1], "bottom")
label.new(bar_index[1], low[1], "底", color=color.green, style=label.style_label_up, size=size.tiny)
// 每根K线应用结合律过滤
if barstate.isconfirmed
// 清空有效分型数组
array.clear(valid_fractals)
// 应用结合律过滤
if array.size(all_fractals) > 0
// 添加第一个分型
array.push(valid_fractals, array.get(all_fractals, 0))
i = 1
while i < array.size(all_fractals)
current = array.get(all_fractals, i)
last_valid = array.get(valid_fractals, array.size(valid_fractals) - 1)
if current.type != last_valid.type
// 不同类型,直接添加
array.push(valid_fractals, current)
i += 1
else
// 相同类型,找到最极端的
extreme = current
j = i + 1
// 向前搜索相同类型的分型
while j < array.size(all_fractals)
next = array.get(all_fractals, j)
if next.type == current.type
// 比较极值
if current.type == "top"
if next.price > extreme.price
extreme := next
else // bottom
if next.price < extreme.price
extreme := next
j += 1
else
break
// 添加极值分型
array.push(valid_fractals, extreme)
i := j
// 清理旧笔
if array.size(stroke_lines) > 0
for k = 0 to array.size(stroke_lines) - 1
line.delete(array.get(stroke_lines, k))
array.clear(stroke_lines)
// 绘制新笔
if show_strokes and array.size(valid_fractals) >= 2
for m = 0 to array.size(valid_fractals) - 2
current = array.get(valid_fractals, m)
next = array.get(valid_fractals, m + 1)
// 检查距离限制
distance = bar_index - current.bar_index
if distance <= 500
line_color = current.type == "bottom" ? color.blue : color.navy
stroke_line = line.new(current.bar_index, current.price, next.bar_index, next.price, color=line_color, width=stroke_width)
array.push(stroke_lines, stroke_line)
// 显示有效分型(大标签)
if show_valid and barstate.islast
for n = 0 to array.size(valid_fractals) - 1
fractal = array.get(valid_fractals, n)
if fractal.type == "top"
label.new(fractal.bar_index, fractal.price, "T", color=color.yellow, style=label.style_label_down, size=size.normal, textcolor=color.black)
else
label.new(fractal.bar_index, fractal.price, "B", color=color.orange, style=label.style_label_up, size=size.normal, textcolor=color.black)
// 优化的信息面板
if barstate.islast
var table info = table.new(position.top_right, 2, 6, bgcolor=color.white, border_width=1)
table.cell(info, 0, 0, "缠论优化版", text_color=color.blue, text_size=size.normal)
table.cell(info, 1, 0, "", text_color=color.black)
table.cell(info, 0, 1, "原始分型", text_color=color.black)
table.cell(info, 1, 1, str.tostring(array.size(all_fractals)), text_color=color.green)
table.cell(info, 0, 2, "有效分型", text_color=color.black)
table.cell(info, 1, 2, str.tostring(array.size(valid_fractals)), text_color=color.red)
table.cell(info, 0, 3, "过滤率", text_color=color.black)
filter_rate = array.size(all_fractals) > 0 ? math.round((1 - array.size(valid_fractals) / array.size(all_fractals)) * 100) : 0
table.cell(info, 1, 3, str.tostring(filter_rate) + "%", text_color=color.purple)
table.cell(info, 0, 4, "笔数", text_color=color.black)
table.cell(info, 1, 4, str.tostring(array.size(stroke_lines)), text_color=color.blue)
table.cell(info, 0, 5, "分型间隔", text_color=color.black)
table.cell(info, 1, 5, str.tostring(min_gap), text_color=color.gray)
// 质量检查:理论上笔数应该 = 有效分型数 - 1
quality_check = array.size(valid_fractals) > 0 ? array.size(stroke_lines) == (array.size(valid_fractals) - 1) : true
if barstate.islast and not quality_check
label.new(bar_index, high, "⚠️质量检查失败", color=color.red, style=label.style_label_down, size=size.large)
+168
View File
@@ -0,0 +1,168 @@
//@version=6
indicator("缠论完美版", shorttitle="完美版", overlay=true, max_lines_count=100, max_labels_count=100)
// 参数设置
min_gap = input.int(10, "分型间隔", minval=5, maxval=30)
show_debug = input.bool(false, "显示调试信息")
show_strokes = input.bool(true, "显示笔")
// 数据类型
type Fractal
int bar_index
float price
string type
// 全局变量
var raw_fractals = array.new<Fractal>()
var final_fractals = array.new<Fractal>()
var strokes = array.new<line>()
// 安全的分型识别 - 添加历史数据检查
is_top = bar_index >= 2 and high[1] > high[0] and high[1] > high[2] and low[1] > low[0] and low[1] > low[2]
is_bottom = bar_index >= 2 and low[1] < low[0] and low[1] < low[2] and high[1] < high[0] and high[1] < high[2]
// 距离检查
valid_distance(new_bar) =>
result = true
if array.size(raw_fractals) > 0
last = array.get(raw_fractals, array.size(raw_fractals) - 1)
if new_bar - last.bar_index < min_gap
result := false
result
// 添加原始分型 - 简化条件检查
if is_top and valid_distance(bar_index[1])
array.push(raw_fractals, Fractal.new(bar_index[1], high[1], "top"))
if array.size(raw_fractals) > 50 // 减少数组大小限制
array.shift(raw_fractals)
if is_bottom and valid_distance(bar_index[1])
array.push(raw_fractals, Fractal.new(bar_index[1], low[1], "bottom"))
if array.size(raw_fractals) > 50 // 减少数组大小限制
array.shift(raw_fractals)
// 显示原始分型(调试)
if show_debug
if is_top and valid_distance(bar_index[1])
label.new(bar_index[1], high[1], "顶", color=color.red, style=label.style_label_down, size=size.tiny)
if is_bottom and valid_distance(bar_index[1])
label.new(bar_index[1], low[1], "底", color=color.green, style=label.style_label_up, size=size.tiny)
// 核心:结合律过滤 - 添加更多安全检查
if barstate.isconfirmed and array.size(raw_fractals) > 0
// 重新构建有效分型
array.clear(final_fractals)
// 第一个分型
array.push(final_fractals, array.get(raw_fractals, 0))
// 从第二个开始处理
if array.size(raw_fractals) > 1
i = 1
while i < array.size(raw_fractals)
current = array.get(raw_fractals, i)
if array.size(final_fractals) > 0
last_final = array.get(final_fractals, array.size(final_fractals) - 1)
if current.type != last_final.type
// 不同类型:直接加入
array.push(final_fractals, current)
i += 1
else
// 相同类型:找最极端的
extreme = current
j = i + 1
// 扫描后续同类型分型
while j < array.size(raw_fractals)
next = array.get(raw_fractals, j)
if next.type == current.type
if current.type == "top"
if next.price > extreme.price
extreme := next
else
if next.price < extreme.price
extreme := next
j += 1
else
break
// 加入极值分型
array.push(final_fractals, extreme)
i := j
else
// 如果final_fractals为空,直接添加
array.push(final_fractals, current)
i += 1
// 重绘笔 - 修复统计问题
if array.size(strokes) > 0
for k = 0 to array.size(strokes) - 1
line.delete(array.get(strokes, k))
array.clear(strokes)
if show_strokes and array.size(final_fractals) >= 2
for m = 0 to array.size(final_fractals) - 2
f1 = array.get(final_fractals, m)
f2 = array.get(final_fractals, m + 1)
// 放宽距离限制,确保所有笔都能绘制
distance_from_current = bar_index - f1.bar_index
if distance_from_current <= 500 and distance_from_current >= 0 // 恢复到500根K线
color_line = f1.type == "bottom" ? color.blue : color.red
line_obj = line.new(f1.bar_index, f1.price, f2.bar_index, f2.price, color=color_line, width=3)
array.push(strokes, line_obj)
// 显示最终分型 - 添加距离检查
if barstate.islast and array.size(final_fractals) > 0
for n = 0 to array.size(final_fractals) - 1
frac = array.get(final_fractals, n)
distance_from_current = bar_index - frac.bar_index
if distance_from_current <= 500 // 恢复到500根K线
if frac.type == "top"
label.new(frac.bar_index, frac.price, "T", color=color.yellow, style=label.style_label_down, size=size.normal)
else
label.new(frac.bar_index, frac.price, "B", color=color.orange, style=label.style_label_up, size=size.normal)
// 改进的信息统计
if barstate.islast
var table info = table.new(position.top_right, 2, 7, bgcolor=color.white, border_width=1)
raw_count = array.size(raw_fractals)
final_count = array.size(final_fractals)
stroke_count = array.size(strokes)
theoretical_strokes = final_count > 0 ? final_count - 1 : 0
filter_percent = raw_count > 0 ? math.round((raw_count - final_count) * 100 / raw_count) : 0
// 计算实际可绘制的笔数
drawable_strokes = 0
if array.size(final_fractals) >= 2
for m = 0 to array.size(final_fractals) - 2
f1 = array.get(final_fractals, m)
distance_from_current = bar_index - f1.bar_index
if distance_from_current <= 500 and distance_from_current >= 0
drawable_strokes += 1
table.cell(info, 0, 0, "缠论完美版", text_color=color.blue, text_size=size.normal)
table.cell(info, 1, 0, "V1.2", text_color=color.gray)
table.cell(info, 0, 1, "原始分型", text_color=color.black)
table.cell(info, 1, 1, str.tostring(raw_count), text_color=color.green)
table.cell(info, 0, 2, "有效分型", text_color=color.black)
table.cell(info, 1, 2, str.tostring(final_count), text_color=color.red)
table.cell(info, 0, 3, "过滤率", text_color=color.black)
table.cell(info, 1, 3, str.tostring(filter_percent) + "%", text_color=color.purple)
table.cell(info, 0, 4, "笔数", text_color=color.black)
table.cell(info, 1, 4, str.tostring(stroke_count), text_color=color.blue)
table.cell(info, 0, 5, "可绘制笔", text_color=color.black)
table.cell(info, 1, 5, str.tostring(drawable_strokes), text_color=color.gray)
table.cell(info, 0, 6, "状态", text_color=color.black)
status = stroke_count == drawable_strokes ? "✓正常" : "✗异常"
status_color = stroke_count == drawable_strokes ? color.green : color.red
table.cell(info, 1, 6, status, text_color=status_color)
+191
View File
@@ -0,0 +1,191 @@
//@version=6
indicator("缠论精简版", shorttitle="缠论", overlay=true, max_lines_count=100, max_labels_count=100)
// ================== 输入参数 ==================
show_fractal = input.bool(true, "显示分型", group="显示")
show_stroke = input.bool(true, "显示笔", group="显示")
show_hub = input.bool(true, "显示中枢", group="显示")
show_signals = input.bool(true, "显示买卖点", group="显示")
fractal_length = input.int(3, "分型周期", minval=3, maxval=10, group="参数")
stroke_color = input.color(color.blue, "笔颜色", group="颜色")
hub_color = input.color(color.gray, "中枢颜色", group="颜色")
// ================== 分型识别 ==================
// 顶分型
top_fractal = ta.pivothigh(high, fractal_length, fractal_length)
// 底分型
bottom_fractal = ta.pivotlow(low, fractal_length, fractal_length)
// ================== 存储分型数据 ==================
var fractal_highs = array.new<float>()
var fractal_lows = array.new<float>()
var fractal_high_bars = array.new<int>()
var fractal_low_bars = array.new<int>()
// 记录新的分型
if not na(top_fractal)
array.push(fractal_highs, top_fractal)
array.push(fractal_high_bars, bar_index - fractal_length)
// 保持数组大小
if array.size(fractal_highs) > 50
array.shift(fractal_highs)
array.shift(fractal_high_bars)
if not na(bottom_fractal)
array.push(fractal_lows, bottom_fractal)
array.push(fractal_low_bars, bar_index - fractal_length)
// 保持数组大小
if array.size(fractal_lows) > 50
array.shift(fractal_lows)
array.shift(fractal_low_bars)
// ================== 显示分型 ==================
if show_fractal
// 顶分型标记
if not na(top_fractal)
label.new(bar_index - fractal_length, top_fractal, "T",
color=color.red, style=label.style_label_down, size=size.tiny)
// 底分型标记
if not na(bottom_fractal)
label.new(bar_index - fractal_length, bottom_fractal, "B",
color=color.green, style=label.style_label_up, size=size.tiny)
// ================== 笔的构建 ==================
var strokes = array.new<line>()
// 构建笔
build_strokes() =>
if array.size(fractal_highs) >= 1 and array.size(fractal_lows) >= 1
high_size = array.size(fractal_highs)
low_size = array.size(fractal_lows)
last_high = array.get(fractal_highs, high_size - 1)
last_low = array.get(fractal_lows, low_size - 1)
last_high_bar = array.get(fractal_high_bars, high_size - 1)
last_low_bar = array.get(fractal_low_bars, low_size - 1)
// 根据最后的分型连接笔
if last_high_bar > last_low_bar
// 最后是顶分型,连接到前一个底分型
if low_size >= 2
prev_low = array.get(fractal_lows, low_size - 2)
prev_low_bar = array.get(fractal_low_bars, low_size - 2)
if show_stroke
new_line = line.new(prev_low_bar, prev_low, last_high_bar, last_high,
color=stroke_color, width=2)
array.push(strokes, new_line)
else
// 最后是底分型,连接到前一个顶分型
if high_size >= 2
prev_high = array.get(fractal_highs, high_size - 2)
prev_high_bar = array.get(fractal_high_bars, high_size - 2)
if show_stroke
new_line = line.new(prev_high_bar, prev_high, last_low_bar, last_low,
color=stroke_color, width=2)
array.push(strokes, new_line)
// 执行笔构建
if not na(top_fractal) or not na(bottom_fractal)
build_strokes()
// ================== 中枢识别 ==================
var hubs = array.new<box>()
identify_hubs() =>
if array.size(fractal_highs) >= 3 and array.size(fractal_lows) >= 3
// 简化的中枢识别:连续三个分型的重叠区域
high_size = array.size(fractal_highs)
low_size = array.size(fractal_lows)
if high_size >= 2 and low_size >= 2
h1 = array.get(fractal_highs, high_size - 2)
h2 = array.get(fractal_highs, high_size - 1)
l1 = array.get(fractal_lows, low_size - 2)
l2 = array.get(fractal_lows, low_size - 1)
hub_high = math.min(h1, h2)
hub_low = math.max(l1, l2)
if hub_high > hub_low
start_bar = math.min(array.get(fractal_high_bars, high_size - 2),
array.get(fractal_low_bars, low_size - 2))
end_bar = math.max(array.get(fractal_high_bars, high_size - 1),
array.get(fractal_low_bars, low_size - 1))
if show_hub
hub_box = box.new(start_bar, hub_high, end_bar, hub_low,
border_color=hub_color, bgcolor=color.new(hub_color, 85))
array.push(hubs, hub_box)
// 执行中枢识别
if barstate.islast and (not na(top_fractal) or not na(bottom_fractal))
identify_hubs()
// ================== 买卖点信号 ==================
var buy_point = false
var sell_point = false
// 简化的买卖点逻辑
if array.size(fractal_lows) >= 2 and array.size(hubs) >= 1
current_low = array.get(fractal_lows, array.size(fractal_lows) - 1)
if array.size(hubs) > 0
latest_hub = array.get(hubs, array.size(hubs) - 1)
hub_low = box.get_bottom(latest_hub)
// 跌破中枢下沿的买点
if current_low < hub_low
buy_point := true
if array.size(fractal_highs) >= 2 and array.size(hubs) >= 1
current_high = array.get(fractal_highs, array.size(fractal_highs) - 1)
if array.size(hubs) > 0
latest_hub = array.get(hubs, array.size(hubs) - 1)
hub_high = box.get_top(latest_hub)
// 突破中枢上沿的卖点
if current_high > hub_high
sell_point := true
// 显示买卖点
if show_signals
if buy_point and not na(bottom_fractal)
label.new(bar_index - fractal_length, bottom_fractal, "买",
color=color.green, style=label.style_label_up, size=size.normal)
if sell_point and not na(top_fractal)
label.new(bar_index - fractal_length, top_fractal, "卖",
color=color.red, style=label.style_label_down, size=size.normal)
// ================== 清理旧对象 ==================
// 限制绘图对象数量,避免超出限制
if array.size(strokes) > 30
old_line = array.shift(strokes)
line.delete(old_line)
if array.size(hubs) > 10
old_hub = array.shift(hubs)
box.delete(old_hub)
// ================== 警报 ==================
alertcondition(buy_point and not na(bottom_fractal), title="缠论买点", message="发现买入信号")
alertcondition(sell_point and not na(top_fractal), title="缠论卖点", message="发现卖出信号")
// ================== 状态显示 ==================
if barstate.islast
var info_table = table.new(position.top_right, 2, 4, bgcolor=color.white, border_width=1)
table.cell(info_table, 0, 0, "缠论状态", text_color=color.black, text_size=size.small)
table.cell(info_table, 1, 0, "", text_color=color.black)
table.cell(info_table, 0, 1, "顶分型", text_color=color.black)
table.cell(info_table, 1, 1, str.tostring(array.size(fractal_highs)), text_color=color.black)
table.cell(info_table, 0, 2, "底分型", text_color=color.black)
table.cell(info_table, 1, 2, str.tostring(array.size(fractal_lows)), text_color=color.black)
table.cell(info_table, 0, 3, "中枢数", text_color=color.black)
table.cell(info_table, 1, 3, str.tostring(array.size(hubs)), text_color=color.black)
+89
View File
@@ -0,0 +1,89 @@
//@version=6
indicator("缠论简化测试", shorttitle="缠论测试", overlay=true, max_lines_count=100, max_labels_count=100)
// ================== 参数设置 ==================
show_fenxing = input.bool(true, "显示分型", group="显示设置")
show_bi = input.bool(true, "显示笔", group="显示设置")
min_bars_between = input.int(8, "分型最小间隔", minval=5, maxval=20, group="缠论参数")
// ================== 数据类型定义 ==================
type FractalPoint
int bar_index
float price
string fractal_type
// ================== 全局变量 ==================
var fractal_points = array.new<FractalPoint>()
var bi_lines = array.new<line>()
// ================== 简单分型识别(严格模式)==================
// 严格分型:高点和低点都要满足条件
is_top_fractal = high[1] > high[0] and high[1] > high[2] and low[1] > low[0] and low[1] > low[2]
is_bottom_fractal = high[1] < high[0] and high[1] < high[2] and low[1] < low[0] and low[1] < low[2]
// ================== 距离过滤 ==================
distance_ok(new_bar) =>
result = true
if array.size(fractal_points) > 0
last_fractal = array.get(fractal_points, array.size(fractal_points) - 1)
bar_distance = new_bar - last_fractal.bar_index
if bar_distance < min_bars_between
result := false
result
// ================== 添加分型 ==================
if is_top_fractal and distance_ok(bar_index[1])
new_fractal = FractalPoint.new(bar_index[1], high[1], "top")
array.push(fractal_points, new_fractal)
if array.size(fractal_points) > 50
array.shift(fractal_points)
if is_bottom_fractal and distance_ok(bar_index[1])
new_fractal = FractalPoint.new(bar_index[1], low[1], "bottom")
array.push(fractal_points, new_fractal)
if array.size(fractal_points) > 50
array.shift(fractal_points)
// ================== 显示分型 ==================
if show_fenxing
if is_top_fractal and distance_ok(bar_index[1])
label.new(bar_index[1], high[1], "顶", color=color.red, style=label.style_label_down, size=size.small)
if is_bottom_fractal and distance_ok(bar_index[1])
label.new(bar_index[1], low[1], "底", color=color.green, style=label.style_label_up, size=size.small)
// ================== 重新构建所有笔 ==================
if barstate.islast
// 清理旧笔
if array.size(bi_lines) > 0
for i = 0 to array.size(bi_lines) - 1
line.delete(array.get(bi_lines, i))
array.clear(bi_lines)
// 重新构建所有笔
if array.size(fractal_points) >= 2 and show_bi
for i = 0 to array.size(fractal_points) - 2
current_fractal = array.get(fractal_points, i)
next_fractal = array.get(fractal_points, i + 1)
// 只连接不同类型的分型
if current_fractal.fractal_type != next_fractal.fractal_type
// 检查距离限制
distance = bar_index - current_fractal.bar_index
if distance <= 500
new_line = line.new(current_fractal.bar_index, current_fractal.price, next_fractal.bar_index, next_fractal.price, color=color.blue, width=2, style=line.style_solid)
array.push(bi_lines, new_line)
// ================== 信息面板 ==================
if barstate.islast
var info_table = table.new(position.top_right, 2, 4, bgcolor=color.white, border_width=1)
table.cell(info_table, 0, 0, "缠论简化测试", text_color=color.black, text_size=size.small)
table.cell(info_table, 1, 0, "", text_color=color.black)
table.cell(info_table, 0, 1, "分型数", text_color=color.black)
table.cell(info_table, 1, 1, str.tostring(array.size(fractal_points)), text_color=color.black)
table.cell(info_table, 0, 2, "笔数", text_color=color.black)
table.cell(info_table, 1, 2, str.tostring(array.size(bi_lines)), text_color=color.black)
table.cell(info_table, 0, 3, "间隔设置", text_color=color.black)
table.cell(info_table, 1, 3, str.tostring(min_bars_between), text_color=color.black)
+206
View File
@@ -0,0 +1,206 @@
//@version=6
indicator("缠论简化版V2", shorttitle="缠论V2", overlay=true, max_lines_count=100, max_labels_count=100)
// ================== 参数设置 ==================
show_fenxing = input.bool(true, "显示分型", group="显示设置")
show_bi = input.bool(true, "显示笔", group="显示设置")
show_zhongshu = input.bool(true, "显示中枢", group="显示设置")
show_signals = input.bool(true, "显示买卖点", group="显示设置")
// 缠论参数
fractal_length = input.int(2, "分型识别周期", minval=1, maxval=5, group="缠论参数")
min_bars_between = input.int(5, "分型最小间隔", minval=3, maxval=20, group="缠论参数")
bi_color = input.color(color.blue, "笔的颜色", group="颜色设置")
zhongshu_color = input.color(color.gray, "中枢颜色", group="颜色设置")
// ================== 数据类型定义 ==================
type FractalPoint
int bar_index
float price
string fractal_type // "top" or "bottom"
// ================== 全局变量 ==================
var fractal_points = array.new<FractalPoint>()
var bi_lines = array.new<line>()
var zhongshu_boxes = array.new<box>()
// ================== 分型识别 ==================
// 检查基本分型条件
is_basic_top_fractal = fractal_length > 0 and
high[fractal_length] > high[fractal_length-1] and
high[fractal_length] > high[fractal_length+1] and
low[fractal_length] > low[fractal_length-1] and
low[fractal_length] > low[fractal_length+1]
is_basic_bottom_fractal = fractal_length > 0 and
low[fractal_length] < low[fractal_length-1] and
low[fractal_length] < low[fractal_length+1] and
high[fractal_length] < high[fractal_length-1] and
high[fractal_length] < high[fractal_length+1]
// 检查距离过滤
check_distance_filter(new_bar, new_type) =>
if array.size(fractal_points) == 0
true
else
last_fractal = array.get(fractal_points, array.size(fractal_points) - 1)
bar_distance = new_bar - last_fractal.bar_index
// 如果距离太近,则不添加新分型
if bar_distance < min_bars_between
false
// 如果是相同类型且距离不够远,也不添加
else if last_fractal.fractal_type == new_type and bar_distance < min_bars_between * 2
false
else
true
// ================== 添加分型 ==================
current_bar = bar_index - fractal_length
// 检查顶分型
if is_basic_top_fractal and check_distance_filter(current_bar, "top")
new_fractal = FractalPoint.new(current_bar, high[fractal_length], "top")
array.push(fractal_points, new_fractal)
// 保持数组大小
if array.size(fractal_points) > 50
array.shift(fractal_points)
// 检查底分型
if is_basic_bottom_fractal and check_distance_filter(current_bar, "bottom")
new_fractal = FractalPoint.new(current_bar, low[fractal_length], "bottom")
array.push(fractal_points, new_fractal)
// 保持数组大小
if array.size(fractal_points) > 50
array.shift(fractal_points)
// ================== 显示分型 ==================
if show_fenxing
if is_basic_top_fractal and check_distance_filter(current_bar, "top")
label.new(current_bar, high[fractal_length], "T",
color=color.red, style=label.style_label_down, size=size.small)
if is_basic_bottom_fractal and check_distance_filter(current_bar, "bottom")
label.new(current_bar, low[fractal_length], "B",
color=color.green, style=label.style_label_up, size=size.small)
// ================== 构建笔 ==================
// 重建所有笔(当有新分型时)
rebuild_bi() =>
// 清空现有笔
for i = 0 to array.size(bi_lines) - 1
line.delete(array.get(bi_lines, i))
array.clear(bi_lines)
// 构建新笔
if array.size(fractal_points) >= 2
for i = 0 to array.size(fractal_points) - 2
current_fractal = array.get(fractal_points, i)
next_fractal = array.get(fractal_points, i + 1)
// 连接相邻的反向分型
if current_fractal.fractal_type != next_fractal.fractal_type and show_bi
new_line = line.new(
current_fractal.bar_index, current_fractal.price,
next_fractal.bar_index, next_fractal.price,
color=bi_color, width=2, style=line.style_solid)
array.push(bi_lines, new_line)
// 当分型数组发生变化时重建笔
var last_fractal_count = 0
current_fractal_count = array.size(fractal_points)
if current_fractal_count != last_fractal_count
rebuild_bi()
last_fractal_count := current_fractal_count
// ================== 中枢识别 ==================
// 简化的中枢识别
if array.size(bi_lines) >= 3 and show_zhongshu
// 检查最近是否需要添加新中枢
if array.size(bi_lines) >= 3
line1 = array.get(bi_lines, array.size(bi_lines) - 3)
line2 = array.get(bi_lines, array.size(bi_lines) - 2)
line3 = array.get(bi_lines, array.size(bi_lines) - 1)
// 获取价格区间
h1 = math.max(line.get_y1(line1), line.get_y2(line1))
l1 = math.min(line.get_y1(line1), line.get_y2(line1))
h2 = math.max(line.get_y1(line2), line.get_y2(line2))
l2 = math.min(line.get_y1(line2), line.get_y2(line2))
h3 = math.max(line.get_y1(line3), line.get_y2(line3))
l3 = math.min(line.get_y1(line3), line.get_y2(line3))
// 计算重叠区域
overlap_high = math.min(math.min(h1, h2), h3)
overlap_low = math.max(math.max(l1, l2), l3)
// 形成中枢
if overlap_high > overlap_low
start_bar = math.min(line.get_x1(line1), line.get_x2(line1))
end_bar = math.max(line.get_x1(line3), line.get_x2(line3))
// 检查是否需要添加新中枢
should_add = true
if array.size(zhongshu_boxes) > 0
last_box = array.get(zhongshu_boxes, array.size(zhongshu_boxes) - 1)
if math.abs(box.get_right(last_box) - end_bar) < 10
should_add := false
if should_add
zs_box = box.new(start_bar, overlap_high, end_bar, overlap_low,
border_color=zhongshu_color,
bgcolor=color.new(zhongshu_color, 80))
array.push(zhongshu_boxes, zs_box)
// ================== 买卖点识别 ==================
var last_signal_bar = 0
if array.size(zhongshu_boxes) > 0 and array.size(fractal_points) > 0 and show_signals
latest_zs = array.get(zhongshu_boxes, array.size(zhongshu_boxes) - 1)
zs_high = box.get_top(latest_zs)
zs_low = box.get_bottom(latest_zs)
zs_right = box.get_right(latest_zs)
// 检查最新分型
if array.size(fractal_points) > 0
latest_fractal = array.get(fractal_points, array.size(fractal_points) - 1)
// 确保信号间隔
if latest_fractal.bar_index > last_signal_bar + 5 and latest_fractal.bar_index > zs_right
// 买点:底分型跌破中枢下沿
if latest_fractal.fractal_type == "bottom" and latest_fractal.price < zs_low
label.new(latest_fractal.bar_index, latest_fractal.price, "买",
color=color.green, style=label.style_label_up, size=size.normal)
last_signal_bar := latest_fractal.bar_index
// 卖点:顶分型突破中枢上沿
if latest_fractal.fractal_type == "top" and latest_fractal.price > zs_high
label.new(latest_fractal.bar_index, latest_fractal.price, "卖",
color=color.red, style=label.style_label_down, size=size.normal)
last_signal_bar := latest_fractal.bar_index
// ================== 清理旧对象 ==================
if array.size(zhongshu_boxes) > 10
old_box = array.shift(zhongshu_boxes)
box.delete(old_box)
// ================== 信息面板 ==================
if barstate.islast
var info_table = table.new(position.top_right, 2, 4, bgcolor=color.white, border_width=1)
table.cell(info_table, 0, 0, "缠论V2", text_color=color.black, text_size=size.small)
table.cell(info_table, 1, 0, "", text_color=color.black)
table.cell(info_table, 0, 1, "分型数", text_color=color.black)
table.cell(info_table, 1, 1, str.tostring(array.size(fractal_points)), text_color=color.black)
table.cell(info_table, 0, 2, "笔数", text_color=color.black)
table.cell(info_table, 1, 2, str.tostring(array.size(bi_lines)), text_color=color.black)
table.cell(info_table, 0, 3, "中枢数", text_color=color.black)
table.cell(info_table, 1, 3, str.tostring(array.size(zhongshu_boxes)), text_color=color.black)
// ================== 警报 ==================
alertcondition(is_basic_bottom_fractal and check_distance_filter(current_bar, "bottom"),
title="缠论买点", message="发现底分型")
alertcondition(is_basic_top_fractal and check_distance_filter(current_bar, "top"),
title="缠论卖点", message="发现顶分型")
+371
View File
@@ -0,0 +1,371 @@
//@version=6
indicator("缠论标准版V3", shorttitle="缠论标准V3", overlay=true, max_lines_count=200, max_labels_count=200)
// ================== 参数设置 ==================
show_merged_k = input.bool(true, "显示合并K线", group="显示设置")
show_fenxing = input.bool(true, "显示分型", group="显示设置")
show_bi = input.bool(true, "显示笔", group="显示设置")
show_xianduan = input.bool(true, "显示线段", group="显示设置")
show_zhongshu = input.bool(true, "显示中枢", group="显示设置")
show_signals = input.bool(true, "显示买卖点", group="显示设置")
debug_mode = input.bool(false, "调试模式(禁用分型间隔过滤)", group="显示设置")
// 缠论参数
fractal_length = input.int(1, "分型识别周期", minval=1, maxval=3, group="缠论参数")
min_bars_between = input.int(2, "分型最小间隔", minval=1, maxval=20, group="缠论参数")
strict_fractal = input.bool(false, "严格分型模式", group="缠论参数")
bi_color = input.color(color.blue, "笔的颜色", group="颜色设置")
xianduan_color = input.color(color.red, "线段颜色", group="颜色设置")
zhongshu_color = input.color(color.gray, "中枢颜色", group="颜色设置")
merged_k_color = input.color(color.orange, "合并K线颜色", group="颜色设置")
// ================== 数据类型定义 ==================
type MergedK
int bar_index
float high
float low
float open
float close
int direction // 1: 向上, -1: 向下, 0: 未确定
type FractalPoint
int bar_index
float price
string fractal_type
bool confirmed
type BiSegment
FractalPoint start_point
FractalPoint end_point
int direction
type XianDuan
array<BiSegment> bi_segments
FractalPoint start_point
FractalPoint end_point
bool broken
// ================== 全局变量 ==================
var merged_ks = array.new<MergedK>()
var fractal_points = array.new<FractalPoint>()
var bi_segments = array.new<BiSegment>()
var xianduan_segments = array.new<XianDuan>()
var bi_lines = array.new<line>()
var xianduan_lines = array.new<line>()
var zhongshu_boxes = array.new<box>()
var merged_k_lines = array.new<line>()
var last_signal_bar = 0
var current_trend = 0 // 当前趋势方向
// ================== K线合并处理 ==================
// 判断是否存在包含关系
is_contained(k1_high, k1_low, k2_high, k2_low) =>
(k1_high >= k2_high and k1_low <= k2_low) or (k2_high >= k1_high and k2_low <= k1_low)
// 执行K线合并
if barstate.isconfirmed
current_k = MergedK.new(bar_index, high, low, open, close, 0)
if array.size(merged_ks) == 0
array.push(merged_ks, current_k)
else
last_k = array.get(merged_ks, array.size(merged_ks) - 1)
// 检查包含关系
if is_contained(last_k.high, last_k.low, current_k.high, current_k.low)
// 存在包含关系,需要合并
merged_high = 0.0
merged_low = 0.0
// 根据趋势方向确定合并规则
if current_trend > 0 // 向上趋势
merged_high := math.max(last_k.high, current_k.high)
merged_low := math.max(last_k.low, current_k.low)
else if current_trend < 0 // 向下趋势
merged_high := math.min(last_k.high, current_k.high)
merged_low := math.min(last_k.low, current_k.low)
else // 趋势未确定,按第一根K线方向
if last_k.close > last_k.open // 阳线趋势
merged_high := math.max(last_k.high, current_k.high)
merged_low := math.max(last_k.low, current_k.low)
else // 阴线趋势
merged_high := math.min(last_k.high, current_k.high)
merged_low := math.min(last_k.low, current_k.low)
// 更新最后一个合并K线
last_k.high := merged_high
last_k.low := merged_low
last_k.close := current_k.close
last_k.bar_index := current_k.bar_index
else
// 无包含关系,直接添加
array.push(merged_ks, current_k)
// 更新趋势方向
if array.size(merged_ks) >= 2
prev_k = array.get(merged_ks, array.size(merged_ks) - 2)
if current_k.high > prev_k.high
current_trend := 1
else if current_k.low < prev_k.low
current_trend := -1
// 限制数组大小
if array.size(merged_ks) > 1000
array.shift(merged_ks)
// ================== 分型识别(基于合并K线)==================
// 标准分型识别
check_fractal_from_merged() =>
var top_fractal = false
var bottom_fractal = false
var fractal_bar = 0
var fractal_high = 0.0
var fractal_low = 0.0
if array.size(merged_ks) >= 3
// 检查最近三根合并K线
k1 = array.get(merged_ks, array.size(merged_ks) - 3)
k2 = array.get(merged_ks, array.size(merged_ks) - 2)
k3 = array.get(merged_ks, array.size(merged_ks) - 1)
if strict_fractal
// 严格分型:中间K线的高低点都比左右K线高/低
if k2.high > k1.high and k2.high > k3.high and k2.low > k1.low and k2.low > k3.low
top_fractal := true
fractal_bar := k2.bar_index
fractal_high := k2.high
if k2.high < k1.high and k2.high < k3.high and k2.low < k1.low and k2.low < k3.low
bottom_fractal := true
fractal_bar := k2.bar_index
fractal_low := k2.low
else
// 宽松分型:只要高点或低点满足条件即可
if k2.high > k1.high and k2.high > k3.high
top_fractal := true
fractal_bar := k2.bar_index
fractal_high := k2.high
if k2.low < k1.low and k2.low < k3.low
bottom_fractal := true
fractal_bar := k2.bar_index
fractal_low := k2.low
[top_fractal, bottom_fractal, fractal_bar, fractal_high, fractal_low]
[is_top_fractal, is_bottom_fractal, fractal_bar_index, fractal_high_price, fractal_low_price] = check_fractal_from_merged()
// 检查距离过滤
distance_ok(new_bar, new_type) =>
if debug_mode
true
else
result = true
if array.size(fractal_points) > 0
last_fractal = array.get(fractal_points, array.size(fractal_points) - 1)
bar_distance = new_bar - last_fractal.bar_index
if bar_distance < min_bars_between
result := false
result
// ================== 添加分型 ==================
var bool fractal_added = false
fractal_added := false
if is_top_fractal and distance_ok(fractal_bar_index, "top")
new_fractal = FractalPoint.new(fractal_bar_index, fractal_high_price, "top", true)
array.push(fractal_points, new_fractal)
fractal_added := true
if array.size(fractal_points) > 100
array.shift(fractal_points)
if is_bottom_fractal and distance_ok(fractal_bar_index, "bottom")
new_fractal = FractalPoint.new(fractal_bar_index, fractal_low_price, "bottom", true)
array.push(fractal_points, new_fractal)
fractal_added := true
if array.size(fractal_points) > 100
array.shift(fractal_points)
// ================== 显示合并K线 ==================
if show_merged_k and array.size(merged_ks) >= 2
// 清理旧线条
if array.size(merged_k_lines) > 0
for i = 0 to array.size(merged_k_lines) - 1
line.delete(array.get(merged_k_lines, i))
array.clear(merged_k_lines)
// 绘制合并K线连线
for i = 0 to array.size(merged_ks) - 2
k1 = array.get(merged_ks, i)
k2 = array.get(merged_ks, i + 1)
// 检查距离限制
k_distance = bar_index - k1.bar_index
if k_distance <= 500
high_line = line.new(k1.bar_index, k1.high, k2.bar_index, k2.high, color=merged_k_color, width=1, style=line.style_dashed)
low_line = line.new(k1.bar_index, k1.low, k2.bar_index, k2.low, color=merged_k_color, width=1, style=line.style_dashed)
array.push(merged_k_lines, high_line)
array.push(merged_k_lines, low_line)
// ================== 显示分型 ==================
if show_fenxing
if is_top_fractal and distance_ok(fractal_bar_index, "top")
label.new(fractal_bar_index, fractal_high_price, "顶", color=color.red, style=label.style_label_down, size=size.small)
if is_bottom_fractal and distance_ok(fractal_bar_index, "bottom")
label.new(fractal_bar_index, fractal_low_price, "底", color=color.green, style=label.style_label_up, size=size.small)
// ================== 构建笔 ==================
// 在每根K线重新构建所有笔
if barstate.isconfirmed
// 清理旧笔
if array.size(bi_lines) > 0
for i = 0 to array.size(bi_lines) - 1
line.delete(array.get(bi_lines, i))
array.clear(bi_lines)
array.clear(bi_segments)
// 重新构建所有笔
if array.size(fractal_points) >= 2 and show_bi
for i = 0 to array.size(fractal_points) - 2
current_fractal = array.get(fractal_points, i)
next_fractal = array.get(fractal_points, i + 1)
// 只连接不同类型的分型
if current_fractal.fractal_type != next_fractal.fractal_type
// 确定方向
direction = current_fractal.fractal_type == "bottom" ? 1 : -1
// 创建笔段
bi_seg = BiSegment.new(current_fractal, next_fractal, direction)
array.push(bi_segments, bi_seg)
// 检查距离限制
distance = bar_index - current_fractal.bar_index
if distance <= 500
new_line = line.new(current_fractal.bar_index, current_fractal.price, next_fractal.bar_index, next_fractal.price, color=bi_color, width=2, style=line.style_solid)
array.push(bi_lines, new_line)
// ================== 线段识别 ==================
// 在每根K线重新构建线段
if barstate.isconfirmed and array.size(bi_segments) >= 3
// 清理旧线段
if array.size(xianduan_lines) > 0
for i = 0 to array.size(xianduan_lines) - 1
line.delete(array.get(xianduan_lines, i))
array.clear(xianduan_lines)
array.clear(xianduan_segments)
// 每三笔构建一个线段
segment_count = array.size(bi_segments) // 3
for j = 0 to segment_count - 1
start_idx = j * 3
if start_idx + 2 < array.size(bi_segments)
bi1 = array.get(bi_segments, start_idx)
bi2 = array.get(bi_segments, start_idx + 1)
bi3 = array.get(bi_segments, start_idx + 2)
// 创建线段
bi_array = array.new<BiSegment>()
array.push(bi_array, bi1)
array.push(bi_array, bi2)
array.push(bi_array, bi3)
xianduan = XianDuan.new(bi_array, bi1.start_point, bi3.end_point, false)
array.push(xianduan_segments, xianduan)
// 绘制线段
if show_xianduan
xianduan_distance = bar_index - bi1.start_point.bar_index
if xianduan_distance <= 500
xianduan_line = line.new(bi1.start_point.bar_index, bi1.start_point.price, bi3.end_point.bar_index, bi3.end_point.price, color=xianduan_color, width=3, style=line.style_solid)
array.push(xianduan_lines, xianduan_line)
// ================== 中枢识别(基于笔的重叠)==================
if barstate.isconfirmed and array.size(bi_segments) >= 3 and show_zhongshu
// 清理旧中枢
if array.size(zhongshu_boxes) > 0
for i = 0 to array.size(zhongshu_boxes) - 1
box.delete(array.get(zhongshu_boxes, i))
array.clear(zhongshu_boxes)
// 为每三笔检查中枢
for k = 0 to array.size(bi_segments) - 3
bi1 = array.get(bi_segments, k)
bi2 = array.get(bi_segments, k + 1)
bi3 = array.get(bi_segments, k + 2)
// 计算笔的价格区间
bi1_high = math.max(bi1.start_point.price, bi1.end_point.price)
bi1_low = math.min(bi1.start_point.price, bi1.end_point.price)
bi2_high = math.max(bi2.start_point.price, bi2.end_point.price)
bi2_low = math.min(bi2.start_point.price, bi2.end_point.price)
bi3_high = math.max(bi3.start_point.price, bi3.end_point.price)
bi3_low = math.min(bi3.start_point.price, bi3.end_point.price)
// 计算重叠区域
overlap_high = math.min(math.min(bi1_high, bi2_high), bi3_high)
overlap_low = math.max(math.max(bi1_low, bi2_low), bi3_low)
// 形成中枢
if overlap_high > overlap_low
start_bar = math.min(bi1.start_point.bar_index, bi1.end_point.bar_index)
end_bar = math.max(bi3.start_point.bar_index, bi3.end_point.bar_index)
// 创建中枢(检查距离限制)
zs_distance = bar_index - start_bar
if zs_distance <= 500
zs_box = box.new(start_bar, overlap_high, end_bar, overlap_low, border_color=zhongshu_color, bgcolor=color.new(zhongshu_color, 85))
array.push(zhongshu_boxes, zs_box)
// ================== 改进的买卖点识别 ==================
if show_signals and array.size(zhongshu_boxes) > 0 and array.size(fractal_points) >= 2
last_zhongshu = array.get(zhongshu_boxes, array.size(zhongshu_boxes) - 1)
last_fractal = array.get(fractal_points, array.size(fractal_points) - 1)
zhongshu_high = box.get_top(last_zhongshu)
zhongshu_low = box.get_bottom(last_zhongshu)
// 一买点:跌破中枢下沿后的底分型
if last_fractal.fractal_type == "bottom" and last_fractal.price < zhongshu_low and last_fractal.bar_index > last_signal_bar + 5
label.new(last_fractal.bar_index, last_fractal.price, "一买", color=color.green, style=label.style_label_up, size=size.normal)
last_signal_bar := last_fractal.bar_index
// 一卖点:突破中枢上沿后的顶分型
if last_fractal.fractal_type == "top" and last_fractal.price > zhongshu_high and last_fractal.bar_index > last_signal_bar + 5
label.new(last_fractal.bar_index, last_fractal.price, "一卖", color=color.red, style=label.style_label_down, size=size.normal)
last_signal_bar := last_fractal.bar_index
// ================== 信息面板 ==================
if barstate.islast
var info_table = table.new(position.top_right, 2, 10, bgcolor=color.white, border_width=1)
table.cell(info_table, 0, 0, "缠论标准V3", text_color=color.black, text_size=size.small)
table.cell(info_table, 1, 0, "", text_color=color.black)
table.cell(info_table, 0, 1, "合并K线数", text_color=color.black)
table.cell(info_table, 1, 1, str.tostring(array.size(merged_ks)), text_color=color.black)
table.cell(info_table, 0, 2, "分型数", text_color=color.black)
table.cell(info_table, 1, 2, str.tostring(array.size(fractal_points)), text_color=color.black)
table.cell(info_table, 0, 3, "笔数", text_color=color.black)
table.cell(info_table, 1, 3, str.tostring(array.size(bi_segments)), text_color=color.black)
table.cell(info_table, 0, 4, "线段数", text_color=color.black)
table.cell(info_table, 1, 4, str.tostring(array.size(xianduan_segments)), text_color=color.black)
table.cell(info_table, 0, 5, "中枢数", text_color=color.black)
table.cell(info_table, 1, 5, str.tostring(array.size(zhongshu_boxes)), text_color=color.black)
table.cell(info_table, 0, 6, "当前趋势", text_color=color.black)
trend_text = current_trend > 0 ? "向上" : current_trend < 0 ? "向下" : "震荡"
table.cell(info_table, 1, 6, trend_text, text_color=color.black)
table.cell(info_table, 0, 7, "合并K线", text_color=color.black)
table.cell(info_table, 1, 7, show_merged_k ? "开" : "关", text_color=color.black)
table.cell(info_table, 0, 8, "线段显示", text_color=color.black)
table.cell(info_table, 1, 8, show_xianduan ? "开" : "关", text_color=color.black)
table.cell(info_table, 0, 9, "调试模式", text_color=color.black)
table.cell(info_table, 1, 9, debug_mode ? "开" : "关", text_color=color.black)
// ================== 警报 ==================
alertcondition(is_bottom_fractal and distance_ok(fractal_bar_index, "bottom"),
title="缠论买点", message="发现底分型")
alertcondition(is_top_fractal and distance_ok(fractal_bar_index, "top"),
title="缠论卖点", message="发现顶分型")
+106
View File
@@ -0,0 +1,106 @@
//@version=6
indicator("缠论测试版", shorttitle="缠论测试", overlay=true)
// 参数设置
show_merged_k = input.bool(true, "显示合并K线")
show_fenxing = input.bool(true, "显示分型")
show_bi = input.bool(true, "显示笔")
// 数据类型
type MergedK
int bar_index
float high
float low
float open
float close
type FractalPoint
int bar_index
float price
string fractal_type
// 全局变量
var merged_ks = array.new<MergedK>()
var fractal_points = array.new<FractalPoint>()
var current_trend = 0
// 包含关系判断
is_contained(k1_high, k1_low, k2_high, k2_low) =>
(k1_high >= k2_high and k1_low <= k2_low) or (k2_high >= k1_high and k2_low <= k1_low)
// K线合并
if barstate.isconfirmed
current_k = MergedK.new(bar_index, high, low, open, close)
if array.size(merged_ks) == 0
array.push(merged_ks, current_k)
else
last_k = array.get(merged_ks, array.size(merged_ks) - 1)
if is_contained(last_k.high, last_k.low, current_k.high, current_k.low)
// 合并K线
if current_trend > 0
last_k.high := math.max(last_k.high, current_k.high)
last_k.low := math.max(last_k.low, current_k.low)
else if current_trend < 0
last_k.high := math.min(last_k.high, current_k.high)
last_k.low := math.min(last_k.low, current_k.low)
else
if last_k.close > last_k.open
last_k.high := math.max(last_k.high, current_k.high)
last_k.low := math.max(last_k.low, current_k.low)
else
last_k.high := math.min(last_k.high, current_k.high)
last_k.low := math.min(last_k.low, current_k.low)
last_k.bar_index := current_k.bar_index
else
array.push(merged_ks, current_k)
// 更新趋势
if array.size(merged_ks) >= 2
prev_k = array.get(merged_ks, array.size(merged_ks) - 2)
if current_k.high > prev_k.high
current_trend := 1
else if current_k.low < prev_k.low
current_trend := -1
// 分型识别
if array.size(merged_ks) >= 3
k1 = array.get(merged_ks, array.size(merged_ks) - 3)
k2 = array.get(merged_ks, array.size(merged_ks) - 2)
k3 = array.get(merged_ks, array.size(merged_ks) - 1)
// 顶分型
if k2.high > k1.high and k2.high > k3.high and k2.low > k1.low and k2.low > k3.low
new_fractal = FractalPoint.new(k2.bar_index, k2.high, "top")
array.push(fractal_points, new_fractal)
if show_fenxing
label.new(k2.bar_index, k2.high, "顶", color=color.red, style=label.style_label_down)
// 底分型
if k2.high < k1.high and k2.high < k3.high and k2.low < k1.low and k2.low < k3.low
new_fractal = FractalPoint.new(k2.bar_index, k2.low, "bottom")
array.push(fractal_points, new_fractal)
if show_fenxing
label.new(k2.bar_index, k2.low, "底", color=color.green, style=label.style_label_up)
// 构建笔
if show_bi and array.size(fractal_points) >= 2
for i = 0 to array.size(fractal_points) - 2
current_fractal = array.get(fractal_points, i)
next_fractal = array.get(fractal_points, i + 1)
if current_fractal.fractal_type != next_fractal.fractal_type
line.new(current_fractal.bar_index, current_fractal.price, next_fractal.bar_index, next_fractal.price, color=color.blue, width=2)
// 信息面板
if barstate.islast
var info_table = table.new(position.top_right, 2, 4, bgcolor=color.white, border_width=1)
table.cell(info_table, 0, 0, "缠论测试", text_color=color.black)
table.cell(info_table, 1, 0, "", text_color=color.black)
table.cell(info_table, 0, 1, "合并K线", text_color=color.black)
table.cell(info_table, 1, 1, str.tostring(array.size(merged_ks)), text_color=color.black)
table.cell(info_table, 0, 2, "分型数", text_color=color.black)
table.cell(info_table, 1, 2, str.tostring(array.size(fractal_points)), text_color=color.black)
table.cell(info_table, 0, 3, "当前趋势", text_color=color.black)
trend_text = current_trend > 0 ? "向上" : current_trend < 0 ? "向下" : "震荡"
table.cell(info_table, 1, 3, trend_text, text_color=color.black)
+47
View File
@@ -0,0 +1,47 @@
//@version=6
indicator("缠论超简版", shorttitle="缠论超简", overlay=true)
// 简单参数
min_gap = input.int(5, "分型间隔")
// 全局变量
var int last_fractal_bar = 0
var float last_fractal_price = 0.0
var string last_fractal_type = ""
// 简单分型检测
is_high = high[1] > high[0] and high[1] > high[2]
is_low = low[1] < low[0] and low[1] < low[2]
// 距离检查
gap_ok = bar_index[1] - last_fractal_bar >= min_gap
// 识别并显示顶分型
if is_high and gap_ok
label.new(bar_index[1], high[1], "顶", color=color.red, style=label.style_label_down, size=size.normal)
// 如果上一个是底分型,画笔
if last_fractal_type == "bottom" and last_fractal_bar > 0
line.new(last_fractal_bar, last_fractal_price, bar_index[1], high[1], color=color.blue, width=2)
last_fractal_bar := bar_index[1]
last_fractal_price := high[1]
last_fractal_type := "top"
// 识别并显示底分型
if is_low and gap_ok
label.new(bar_index[1], low[1], "底", color=color.green, style=label.style_label_up, size=size.normal)
// 如果上一个是顶分型,画笔
if last_fractal_type == "top" and last_fractal_bar > 0
line.new(last_fractal_bar, last_fractal_price, bar_index[1], low[1], color=color.blue, width=2)
last_fractal_bar := bar_index[1]
last_fractal_price := low[1]
last_fractal_type := "bottom"
// 信息显示
if barstate.islast
var table info = table.new(position.top_right, 2, 3, bgcolor=color.white)
table.cell(info, 0, 0, "缠论超简版", text_color=color.black)
table.cell(info, 1, 0, "", text_color=color.black)
table.cell(info, 0, 1, "最后分型", text_color=color.black)
table.cell(info, 1, 1, last_fractal_type, text_color=color.black)
table.cell(info, 0, 2, "分型间隔", text_color=color.black)
table.cell(info, 1, 2, str.tostring(min_gap), text_color=color.black)
+190
View File
@@ -0,0 +1,190 @@
//@version=6
strategy("4均线开口策略", shorttitle="EMA4线", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=10, calc_on_every_tick=true)
// 输入参数
ema1_length = input.int(5, "EMA1周期", minval=1)
ema2_length = input.int(10, "EMA2周期", minval=1)
ema3_length = input.int(26, "EMA3周期", minval=1)
ema4_length = input.int(52, "EMA4周期", minval=1)
// 开口阈值设置
opening_threshold = input.float(0.5, "开口阈值(%)", minval=0.1, maxval=5.0) / 100
// 交易频率控制
min_bars_between_trades = input.int(10, "最小交易间隔(K线数)", minval=1, maxval=100)
min_price_change = input.float(0.2, "最小价格变化(%)", minval=0.1, maxval=2.0) / 100
// 均线收束参数
max_ema_spread = input.float(0.8, "均线最大间距(%)", minval=0.1, maxval=2.0) / 100 // 均线间最大距离
convergence_periods = input.int(2, "收束确认周期", minval=1, maxval=10) // 收束状态持续周期
// 显示设置
show_signals = input.bool(true, "显示信号")
show_ema_lines = input.bool(true, "显示EMA线")
// 计算EMA
ema1 = ta.ema(close, ema1_length)
ema2 = ta.ema(close, ema2_length)
ema3 = ta.ema(close, ema3_length)
ema4 = ta.ema(close, ema4_length)
// 显示EMA线
plot(show_ema_lines ? ema1 : na, "EMA快线", color=color.red, linewidth=2)
plot(show_ema_lines ? ema2 : na, "EMA中线", color=color.orange, linewidth=2)
plot(show_ema_lines ? ema3 : na, "EMA慢线", color=color.blue, linewidth=2)
plot(show_ema_lines ? ema4 : na, "EMA超慢线", color=color.purple, linewidth=2)
// 计算均线间距
max_ema = math.max(math.max(ema1, ema2), math.max(ema3, ema4))
min_ema = math.min(math.min(ema1, ema2), math.min(ema3, ema4))
ema_range = (max_ema - min_ema) / close // 所有均线的最大间距
// 计算均线开口程度(使用相对距离)
ema_spread = math.abs(ema1 - ema4) / close
opening_magnitude = ema_spread
// 检测均线收束状态(所有均线距离很近)
emas_converged = ema_range <= max_ema_spread
emas_converged_prev = ema_range[1] <= max_ema_spread
// 简化的收束状态检测
was_converged = emas_converged[1] or emas_converged[2] // 前1-2根K线有收束状态即可
// 检测均线排列状态
// 多头排列:EMA1 > EMA2 > EMA3 > EMA4
bull_alignment_now = ema1 > ema2 and ema2 > ema3 and ema3 > ema4
bull_alignment = bull_alignment_now and bull_alignment_now[1] and bull_alignment_now[2] // 至少持续3个K线
// 空头排列:EMA1 < EMA2 < EMA3 < EMA4
bear_alignment_now = ema1 < ema2 and ema2 < ema3 and ema3 < ema4
bear_alignment = bear_alignment_now and bear_alignment_now[1] and bear_alignment_now[2] // 至少持续3个K线
// 检测均线同向趋势(通过斜率判断)
ema1_rising = ema1 > ema1[1]
ema2_rising = ema2 > ema2[1]
ema3_rising = ema3 > ema3[1]
ema4_rising = ema4 > ema4[1]
ema1_falling = ema1 < ema1[1]
ema2_falling = ema2 < ema2[1]
ema3_falling = ema3 < ema3[1]
ema4_falling = ema4 < ema4[1]
// 同向上升趋势
all_rising = ema1_rising and ema2_rising and ema3_rising and ema4_rising
// 同向下降趋势
all_falling = ema1_falling and ema2_falling and ema3_falling and ema4_falling
// 交易频率控制变量
var int last_trade_bar = 0
var float last_trade_price = 0.0
var int last_signal_bar = 0
// 价格过滤条件
price_above_ema60 = close > ema4 // 价格在EMA60上方
price_below_ema60 = close < ema4 // 价格在EMA60下方
// 交易间隔和价格变化检查
bars_since_last_trade = bar_index - last_trade_bar
sufficient_time_gap = bars_since_last_trade >= min_bars_between_trades
sufficient_price_change = last_trade_price == 0.0 or math.abs(close - last_trade_price) / last_trade_price >= min_price_change
// 检测均线开始发散(从收束状态开始向同一方向移动)
starting_divergence_up = was_converged and all_rising and not emas_converged // 从收束开始向上发散
starting_divergence_down = was_converged and all_falling and not emas_converged // 从收束开始向下发散
// 买入条件:均线从收束开始发散 + 价格过滤 + 频率控制
buy_long_condition = starting_divergence_up and price_above_ema60 and sufficient_time_gap and sufficient_price_change
buy_short_condition = starting_divergence_down and price_below_ema60 and sufficient_time_gap and sufficient_price_change
buy_condition = buy_long_condition or buy_short_condition
// 卖出条件:均线开口达到最大(这里用阈值判断)
// 使用历史最大开口的相对比较
var float max_opening = 0.0
if opening_magnitude > max_opening
max_opening := opening_magnitude
// 当开口超过阈值且达到近期高点时触发卖出
sell_condition = opening_magnitude >= opening_threshold and opening_magnitude >= max_opening * 0.9
// 重置最大开口(当开口显著收窄时)
if opening_magnitude < max_opening * 0.3
max_opening := opening_magnitude
// 执行交易
if buy_long_condition and strategy.position_size == 0
strategy.entry("多头买入", strategy.long)
last_trade_bar := bar_index
last_trade_price := close
if buy_short_condition and strategy.position_size == 0
strategy.entry("空头买入", strategy.short)
last_trade_bar := bar_index
last_trade_price := close
if sell_condition and strategy.position_size != 0
if strategy.position_size > 0
strategy.close("多头买入", comment="多头平仓")
else
strategy.close("空头买入", comment="空头平仓")
// 信号显示间隔控制
signal_gap_ok = bar_index - last_signal_bar >= min_bars_between_trades
// 显示信号 - 只在实际交易时显示
if show_signals
if buy_long_condition and strategy.position_size == 0 and sufficient_time_gap and sufficient_price_change and signal_gap_ok
label.new(bar_index, low, "买多", color=color.green, style=label.style_label_up, size=size.normal)
last_signal_bar := bar_index
if buy_short_condition and strategy.position_size == 0 and sufficient_time_gap and sufficient_price_change and signal_gap_ok
label.new(bar_index, high, "买空", color=color.red, style=label.style_label_down, size=size.normal)
last_signal_bar := bar_index
if sell_condition and strategy.position_size != 0
label.new(bar_index, close, "平仓", color=color.yellow, style=label.style_label_left, size=size.normal)
// 背景颜色指示
bgcolor(emas_converged ? color.new(color.yellow, 95) : na, title="均线收束背景")
bgcolor(starting_divergence_up ? color.new(color.green, 90) : na, title="向上发散背景")
bgcolor(starting_divergence_down ? color.new(color.red, 90) : na, title="向下发散背景")
// 信息表格
if barstate.islast
var table info_table = table.new(position.top_right, 2, 12, bgcolor=color.white, border_width=1)
table.cell(info_table, 0, 0, "4EMA收束发散策略", text_color=color.black, bgcolor=color.gray)
table.cell(info_table, 1, 0, "", text_color=color.black, bgcolor=color.gray)
table.cell(info_table, 0, 1, "均线间距", text_color=color.black)
table.cell(info_table, 1, 1, str.tostring(math.round(ema_range * 10000) / 100) + "%", text_color=color.black)
table.cell(info_table, 0, 2, "收束阈值", text_color=color.black)
table.cell(info_table, 1, 2, str.tostring(math.round(max_ema_spread * 10000) / 100) + "%", text_color=color.black)
table.cell(info_table, 0, 3, "当前收束", text_color=color.black)
table.cell(info_table, 1, 3, emas_converged ? "是" : "否", text_color=color.black)
table.cell(info_table, 0, 4, "之前收束", text_color=color.black)
table.cell(info_table, 1, 4, was_converged ? "是" : "否", text_color=color.black)
table.cell(info_table, 0, 5, "趋势方向", text_color=color.black)
table.cell(info_table, 1, 5, all_rising ? "同向上" : all_falling ? "同向下" : "分歧", text_color=color.black)
table.cell(info_table, 0, 6, "发散检测", text_color=color.black)
divergence_text = starting_divergence_up ? "向上发散" : starting_divergence_down ? "向下发散" : "无发散"
table.cell(info_table, 1, 6, divergence_text, text_color=color.black)
table.cell(info_table, 0, 7, "价格位置", text_color=color.black)
price_position = price_above_ema60 ? "EMA52上方" : price_below_ema60 ? "EMA52下方" : "EMA52附近"
table.cell(info_table, 1, 7, price_position, text_color=color.black)
table.cell(info_table, 0, 8, "时间间隔", text_color=color.black)
table.cell(info_table, 1, 8, sufficient_time_gap ? "满足" : "不足", text_color=color.black)
table.cell(info_table, 0, 9, "价格变化", text_color=color.black)
table.cell(info_table, 1, 9, sufficient_price_change ? "满足" : "不足", text_color=color.black)
table.cell(info_table, 0, 10, "买多条件", text_color=color.black)
table.cell(info_table, 1, 10, buy_long_condition ? "满足" : "不满足", text_color=color.black)
table.cell(info_table, 0, 11, "仓位状态", text_color=color.black)
position_text = strategy.position_size > 0 ? "多头" : strategy.position_size < 0 ? "空头" : "空仓"
table.cell(info_table, 1, 11, position_text, text_color=color.black)
+220
View File
@@ -0,0 +1,220 @@
# 缠论标准版 Pine Script 6.0 使用说明
## 概述
这是一个基于 TradingView Pine Script 6.0 开发的**完整标准缠论分析系统**,严格按照缠中说禅理论实现了缠论的所有核心概念:K线合并、分型、笔、线段、中枢和买卖点识别。
## 🔥 核心改进
### ✅ 新增功能
1. **K线合并处理** - 正确处理包含关系的K线
2. **标准分型识别** - 完整的顶底分型判断条件
3. **线段识别** - 实现线段破坏和确认逻辑
4. **智能买卖点** - 基于中枢突破的一买一卖点
5. **趋势追踪** - 实时显示当前趋势方向
## 核心功能详解
### 1. K线合并处理 🆕
- **理论基础**:缠论要求先处理K线包含关系,获得标准化序列
- **包含关系判断**
```
- K1包含K2K1.high ≥ K2.high 且 K1.low ≤ K2.low
- K2包含K1K2.high ≥ K1.high 且 K2.low ≤ K1.low
```
- **合并规则**
- **向上趋势**:取两根K线的最高价和较高低价
- **向下趋势**:取两根K线的最低价和较低高价
- **趋势未定**:根据第一根K线的阴阳性确定方向
- **显示**:橙色虚线连接合并K线的高低点
### 2. 标准分型识别 ✅
- **顶分型条件**:中间K线的高点和低点都比左右K线高
```
K2.high > K1.high 且 K2.high > K3.high
K2.low > K1.low 且 K2.low > K3.low
```
- **底分型条件**:中间K线的高点和低点都比左右K线低
```
K2.high < K1.high 且 K2.high < K3.high
K2.low < K1.low 且 K2.low < K3.low
```
- **基于合并K线**:分型识别基于处理后的合并K线序列
- **距离过滤**:相邻分型间必须有最小K线间隔(默认5根)
### 3. 笔的构建 ✅
- **定义**:连接相邻反向分型的线段
- **构建规则**
- 只连接不同类型的分型(顶→底 或 底→顶)
- 记录笔的方向(1为向上,-1为向下)
- 存储完整的笔段信息(起点、终点、方向)
- **显示**:蓝色实线,线宽2
### 4. 线段识别 🆕
- **定义**:由多个笔组成的更高级别结构
- **破坏条件**
- **向上线段破坏**:当前向下笔的低点破坏第三笔的高点
- **向下线段破坏**:当前向上笔的高点破坏第三笔的低点
- **确认机制**:线段破坏后确认并开始新线段
- **显示**:红色粗线,线宽3
### 5. 中枢识别 ✅
- **定义**:三笔及以上的重叠价格区间
- **计算方法**
```
重叠高点 = min(笔1高点, 笔2高点, 笔3高点)
重叠低点 = max(笔1低点, 笔2低点, 笔3低点)
```
- **形成条件**:重叠高点 > 重叠低点
- **显示**:灰色半透明方框,透明度85%
### 6. 买卖点识别 🆕
- **一买点**:价格跌破中枢下沿后出现的底分型
- **一卖点**:价格突破中枢上沿后出现的顶分型
- **确认条件**
- 分型价格与中枢边界的突破关系
- 与上一个信号的时间间隔(最少5根K线)
- **显示**:绿色"一买"标签向上,红色"一卖"标签向下
## 参数设置
### 显示设置
- ☑️ `显示合并K线`:显示K线合并的连线(橙色虚线)
- ☑️ `显示分型`:显示顶底分型标记
- ☑️ `显示笔`:显示笔的连线
- ☑️ `显示线段`:显示线段(高级别结构)
- ☑️ `显示中枢`:显示中枢方框
- ☑️ `显示买卖点`:显示交易信号
- ☑️ `调试模式`:禁用分型间隔过滤,显示所有分型
### 缠论参数
- `分型识别周期`1(标准设置,不建议修改)
- `分型最小间隔`5根K线(确保分型质量)
### 颜色设置
- 🔵 `笔的颜色`:蓝色(默认)
- 🔴 `线段颜色`:红色(默认)
- ⚫ `中枢颜色`:灰色(默认)
- 🟠 `合并K线颜色`:橙色(默认)
## 使用方法
### 1. 导入指标
1. 打开 TradingView
2. 进入 Pine Editor
3. 复制 `chan_theory_simple_v3.pine` 文件内容
4. 点击"添加到图表"
### 2. 参数调整
- **新手建议**:开启所有显示选项,完整学习缠论结构
- **实战使用**:可关闭合并K线显示,专注于笔和线段
- **调试学习**:开启调试模式查看所有分型
### 3. 分析流程
1. **观察K线合并** 🔍:理解价格的真实波动结构
2. **识别标准分型** 📍:确定准确的局部高低点
3. **跟踪笔的形成** 📈:观察价格波动的基本单位
4. **关注线段变化** 📊:把握趋势的转折信号
5. **识别中枢结构** ⬜:确定盘整和突破区间
6. **等待买卖信号** 💰:基于中枢突破的交易机会
## 信息面板 📊
右上角实时显示:
- 合并K线数量
- 分型数量
- 笔数量
- 线段数量
- 中枢数量
- 当前趋势方向(向上/向下/震荡)
- 各功能开关状态
## 技术优势
### 1. 理论完整性 ✅
- 严格按照缠中说禅原理实现
- 包含K线合并这一基础步骤
- 分型识别符合标准定义
- 线段识别逻辑准确
### 2. 实用性强 💪
- 自动识别所有缠论结构
- 实时生成交易信号
- 多层级结构同时显示
- 参数可调适应不同市场
### 3. 技术先进 🚀
- 使用Pine Script 6.0最新语法
- 优化的数据结构和算法
- 完善的内存管理机制
- 流畅的图形渲染性能
## 进阶使用技巧
### 1. 多周期分析 🔄
- 在不同时间周期应用指标
- 大周期线段指导小周期操作
- 寻找多周期结构共振点
### 2. 市场适应性 📈
- **股票市场**:关注日线和周线结构
- **外汇市场**:适用于4小时和日线
- **加密货币**:1小时和4小时效果良好
### 3. 交易策略 💡
- **趋势跟踪**:基于线段方向确定趋势
- **区间交易**:利用中枢上下沿做震荡
- **突破交易**:等待一买一卖点确认
## 注意事项
### 1. 理论学习 📚
- 建议先学习缠论基础理论
- 理解K线合并的重要性
- 掌握分型、笔、线段的递进关系
### 2. 实战运用 ⚠️
- 买卖点需结合具体走势确认
- 注意资金管理和风险控制
- 建议与其他技术指标结合使用
### 3. 系统限制 🔧
- Pine Script对象数量有限制
- 建议定期刷新图表清理历史数据
- 长周期历史数据可能影响性能
## 常见问题 FAQ
### Q: 为什么要先处理K线合并?
A: 缠论理论要求先消除K线包含关系,获得标准化序列,这是后续所有分析的基础。
### Q: 分型识别与传统高低点有什么区别?
A: 缠论分型要求中间K线的高低点都比左右K线高(或低),条件更严格,信号更可靠。
### Q: 线段和笔有什么区别?
A: 笔是连接相邻反向分型的线段,而线段是由多个笔组成的更高级别结构,代表更大的趋势变化。
### Q: 一买一卖点的成功率如何?
A: 这是基于缠论理论的客观信号,需要结合市场环境、资金管理等因素综合判断。
## 版本历史
### V3.0 标准版(当前版本)
- ✅ 新增K线合并处理
- ✅ 完善分型识别条件
- ✅ 实现线段识别功能
- ✅ 改进买卖点逻辑
- ✅ 优化代码结构和性能
### V2.0 简化版
- 基础分型和笔识别
- 简单中枢识别
- 基础买卖点提示
## 技术支持
如需更多帮助,请:
1. 参考缠中说禅《教你炒股票》系列文章
2. 学习缠论基础理论知识
3. 在实盘中逐步验证和优化
---
**重要声明**:此指标严格按照缠论理论实现,仅供学习和研究使用。投资有风险,入市需谨慎。建议结合基本面分析和风险管理原则使用。