添加新的策略
This commit is contained in:
+330
-385
@@ -28,7 +28,7 @@ use_macd_filter = input.bool(false, "MACD过滤分型", tooltip="顶分型要
|
||||
ema1_len = input.int(24, "EMA1周期", minval=5, maxval=100, group="均线参数", tooltip="最快均线,默认24")
|
||||
ema2_len = input.int(52, "EMA2周期", minval=10, maxval=200, group="均线参数", tooltip="次快均线,默认52")
|
||||
ema3_len = input.int(104, "EMA3周期", minval=20, maxval=300, group="均线参数", tooltip="次慢均线,默认104")
|
||||
ema4_len = input.int(156, "EMA4周期", minval=30, maxval=500, group="均线参数", tooltip="最慢均线,默认156")
|
||||
ema4_len = input.int(156, "EMA4周期", minval=30, maxval=500, group="均线参数", tooltip="EMA156仅用于显示,不参与三均线排列/交叉")
|
||||
trend_confirm_bars = input.int(3, "趋势确认K线数", minval=1, maxval=20, group="均线参数", tooltip="排列持续N根K线才确认趋势,增大可减少震荡假信号")
|
||||
|
||||
color_bi_up = input.color(color.red, "上升笔颜色", group="颜色设置")
|
||||
@@ -59,28 +59,29 @@ plot(show_ema24 ? ema24 : na, "EMA24", color=color_ema24, linewidth=2)
|
||||
plot(show_ema52 ? ema52 : na, "EMA52", color=color_ema52, linewidth=2)
|
||||
plot(show_ema104 ? ema104 : na, "EMA104", color=color_ema104, linewidth=2)
|
||||
plot(show_ema156 ? ema156 : na, "EMA156", color=color_ema156, linewidth=2)
|
||||
// 趋势/排列与交叉仅使用三条均线:EMA24, EMA52, EMA104(EMA156仅显示)
|
||||
|
||||
// ============================================================================
|
||||
// 四均线趋势排列检测
|
||||
// 三均线趋势排列检测
|
||||
// ============================================================================
|
||||
// 多头排列:EMA1 > EMA2 > EMA3 > EMA4(从上到下依次排列)
|
||||
// 空头排列:EMA1 < EMA2 < EMA3 < EMA4(从下到上依次排列)
|
||||
// 多头排列:EMA1 > EMA2 > EMA3(从上到下依次排列)
|
||||
// 空头排列:EMA1 < EMA2 < EMA3(从下到上依次排列)
|
||||
|
||||
is_bullish_aligned = ema24 > ema52 and ema52 > ema104 and ema104 > ema156
|
||||
is_bearish_aligned = ema24 < ema52 and ema52 < ema104 and ema104 < ema156
|
||||
is_bullish_aligned = ema24 > ema52 and ema52 > ema104
|
||||
is_bearish_aligned = ema24 < ema52 and ema52 < ema104
|
||||
|
||||
// 中枢震荡区间:均线未形成多头或空头排列(均线纠缠状态)
|
||||
is_in_oscillation = not is_bullish_aligned and not is_bearish_aligned
|
||||
|
||||
// EMA交叉检测(52和156)
|
||||
ema_golden_cross = ta.crossover(ema52, ema156) // 金叉:EMA52上穿EMA156
|
||||
ema_death_cross = ta.crossunder(ema52, ema156) // 死叉:EMA52下穿EMA156
|
||||
// EMA交叉检测(52和104)
|
||||
ema_golden_cross = ta.crossover(ema52, ema104) // 金叉:EMA52上穿EMA104
|
||||
ema_death_cross = ta.crossunder(ema52, ema104) // 死叉:EMA52下穿EMA104
|
||||
|
||||
// 绘制交叉点(中枢震荡区间不显示)
|
||||
plotshape(show_ema52 and show_ema156 and ema_golden_cross and not is_in_oscillation, title="EMA金叉",
|
||||
plotshape(show_ema52 and show_ema104 and ema_golden_cross and not is_in_oscillation, title="EMA金叉",
|
||||
style=shape.triangleup, location=location.belowbar,
|
||||
color=color.lime, size=size.small, text="金叉")
|
||||
plotshape(show_ema52 and show_ema156 and ema_death_cross and not is_in_oscillation, title="EMA死叉",
|
||||
plotshape(show_ema52 and show_ema104 and ema_death_cross and not is_in_oscillation, title="EMA死叉",
|
||||
style=shape.triangledown, location=location.abovebar,
|
||||
color=color.red, size=size.small, text="死叉")
|
||||
|
||||
@@ -543,11 +544,15 @@ if barstate.islast
|
||||
bi_color = bi_dir == 1 ? color_bi_up : color_bi_down
|
||||
line.new(s_bar, s_price, e_bar, e_price, color=bi_color, width=2)
|
||||
|
||||
// ==================== 构建线段(特征序列法) ====================
|
||||
// 缠论线段规则:
|
||||
// ==================== 构建线段(标准特征序列法) ====================
|
||||
// 缠论线段标准规则:
|
||||
// 1. 线段至少包含3笔
|
||||
// 2. 特征序列由反向笔组成
|
||||
// 3. 特征序列出现分型且确认,线段结束
|
||||
// 2. 特征序列由与线段方向相反的笔组成
|
||||
// 3. 特征序列要先做包含处理(与K线包含处理同理)
|
||||
// 4. 包含处理后的特征序列出现分型,线段才结束
|
||||
// - 上升线段:特征序列(向下笔)出现顶分型 → 线段结束(第一种情况)
|
||||
// - 下降线段:特征序列(向上笔)出现底分型 → 线段结束(第一种情况)
|
||||
// 5. 第二种情况:特征序列无分型,但出现反向缺口(gap)确认反转
|
||||
|
||||
var int[] xd_start_bars = array.new<int>()
|
||||
var float[] xd_start_prices = array.new<float>()
|
||||
@@ -562,20 +567,31 @@ if barstate.islast
|
||||
array.clear(xd_dirs)
|
||||
|
||||
if bi_count >= 3
|
||||
// 从分型列表构建线段更直接
|
||||
// 线段连接相邻的"线段端点分型"
|
||||
// 特征序列存储(包含处理前的原始序列)
|
||||
var float[] feat_raw_highs = array.new<float>()
|
||||
var float[] feat_raw_lows = array.new<float>()
|
||||
var int[] feat_raw_end_bars = array.new<int>()
|
||||
var float[] feat_raw_end_prices = array.new<float>()
|
||||
array.clear(feat_raw_highs)
|
||||
array.clear(feat_raw_lows)
|
||||
array.clear(feat_raw_end_bars)
|
||||
array.clear(feat_raw_end_prices)
|
||||
|
||||
// 特征序列存储
|
||||
var float[] feat_highs = array.new<float>()
|
||||
var float[] feat_lows = array.new<float>()
|
||||
array.clear(feat_highs)
|
||||
array.clear(feat_lows)
|
||||
// 特征序列包含处理后的序列
|
||||
var float[] feat_merged_highs = array.new<float>()
|
||||
var float[] feat_merged_lows = array.new<float>()
|
||||
var int[] feat_merged_end_bars = array.new<int>()
|
||||
var float[] feat_merged_end_prices = array.new<float>()
|
||||
array.clear(feat_merged_highs)
|
||||
array.clear(feat_merged_lows)
|
||||
array.clear(feat_merged_end_bars)
|
||||
array.clear(feat_merged_end_prices)
|
||||
|
||||
// 线段状态
|
||||
xd_start_bar = array.get(bi_start_bars, 0)
|
||||
xd_start_price = array.get(bi_start_prices, 0)
|
||||
xd_dir = array.get(bi_dirs, 0) // 第一笔方向就是第一个线段方向
|
||||
xd_bi_count = 1 // 当前线段包含的笔数
|
||||
xd_dir = array.get(bi_dirs, 0)
|
||||
xd_bi_count = 1
|
||||
|
||||
// 极值追踪
|
||||
xd_high = math.max(array.get(bi_start_prices, 0), array.get(bi_end_prices, 0))
|
||||
@@ -604,42 +620,108 @@ if barstate.islast
|
||||
xd_low := curr_bi_low
|
||||
xd_low_bar := curr_bi_dir == -1 ? curr_bi_end_bar : curr_bi_start_bar
|
||||
|
||||
// 反向笔加入特征序列
|
||||
// 反向笔加入特征序列(上升线段收集向下笔,下降线段收集向上笔)
|
||||
if curr_bi_dir != xd_dir
|
||||
array.push(feat_highs, curr_bi_high)
|
||||
array.push(feat_lows, curr_bi_low)
|
||||
array.push(feat_raw_highs, curr_bi_high)
|
||||
array.push(feat_raw_lows, curr_bi_low)
|
||||
array.push(feat_raw_end_bars, curr_bi_end_bar)
|
||||
array.push(feat_raw_end_prices, curr_bi_end_price)
|
||||
|
||||
// === 特征序列包含处理 ===
|
||||
// 与K线包含处理原理相同:
|
||||
// 上升线段的特征序列(向下笔):包含处理方向看前一个特征元素
|
||||
// 高点升→向上处理(取高高低低);低点降→向下处理(取低低高高)
|
||||
fm_size = array.size(feat_merged_highs)
|
||||
if fm_size == 0
|
||||
array.push(feat_merged_highs, curr_bi_high)
|
||||
array.push(feat_merged_lows, curr_bi_low)
|
||||
array.push(feat_merged_end_bars, curr_bi_end_bar)
|
||||
array.push(feat_merged_end_prices, curr_bi_end_price)
|
||||
else
|
||||
fm_prev_h = array.get(feat_merged_highs, fm_size - 1)
|
||||
fm_prev_l = array.get(feat_merged_lows, fm_size - 1)
|
||||
|
||||
// 检查是否存在包含关系
|
||||
has_contain = (fm_prev_h >= curr_bi_high and fm_prev_l <= curr_bi_low) or (curr_bi_high >= fm_prev_h and curr_bi_low <= fm_prev_l)
|
||||
|
||||
if has_contain
|
||||
// 确定包含处理方向
|
||||
fm_trend = 0
|
||||
if fm_size >= 2
|
||||
fm_prev2_h = array.get(feat_merged_highs, fm_size - 2)
|
||||
fm_prev2_l = array.get(feat_merged_lows, fm_size - 2)
|
||||
fm_trend := fm_prev_h > fm_prev2_h ? 1 : (fm_prev_l < fm_prev2_l ? -1 : 0)
|
||||
|
||||
// 向上处理:取高高低低;向下处理:取低低高高
|
||||
if fm_trend >= 0
|
||||
array.set(feat_merged_highs, fm_size - 1, math.max(fm_prev_h, curr_bi_high))
|
||||
array.set(feat_merged_lows, fm_size - 1, math.max(fm_prev_l, curr_bi_low))
|
||||
else
|
||||
array.set(feat_merged_highs, fm_size - 1, math.min(fm_prev_h, curr_bi_high))
|
||||
array.set(feat_merged_lows, fm_size - 1, math.min(fm_prev_l, curr_bi_low))
|
||||
// 更新end信息为最新的笔
|
||||
array.set(feat_merged_end_bars, fm_size - 1, curr_bi_end_bar)
|
||||
array.set(feat_merged_end_prices, fm_size - 1, curr_bi_end_price)
|
||||
else
|
||||
// 无包含关系,直接加入
|
||||
array.push(feat_merged_highs, curr_bi_high)
|
||||
array.push(feat_merged_lows, curr_bi_low)
|
||||
array.push(feat_merged_end_bars, curr_bi_end_bar)
|
||||
array.push(feat_merged_end_prices, curr_bi_end_price)
|
||||
|
||||
// 至少3笔后检查线段是否结束
|
||||
xd_broken = false
|
||||
xd_break_bar = 0
|
||||
xd_break_price = 0.0
|
||||
|
||||
if xd_bi_count >= 3
|
||||
feat_size = array.size(feat_highs)
|
||||
fm_size = array.size(feat_merged_highs)
|
||||
|
||||
xd_broken = false
|
||||
|
||||
if feat_size >= 2
|
||||
// 简化判断:反向笔突破前高/前低
|
||||
// === 第一种情况:特征序列包含处理后出现分型 ===
|
||||
if fm_size >= 3
|
||||
fm_h1 = array.get(feat_merged_highs, fm_size - 3)
|
||||
fm_h2 = array.get(feat_merged_highs, fm_size - 2)
|
||||
fm_h3 = array.get(feat_merged_highs, fm_size - 1)
|
||||
fm_l1 = array.get(feat_merged_lows, fm_size - 3)
|
||||
fm_l2 = array.get(feat_merged_lows, fm_size - 2)
|
||||
fm_l3 = array.get(feat_merged_lows, fm_size - 1)
|
||||
|
||||
if xd_dir == 1
|
||||
// 上升线段:向下笔低点创新低
|
||||
if curr_bi_dir == -1 and curr_bi_end_price < xd_start_price
|
||||
// 上升线段:特征序列(向下笔)出现顶分型 → 线段结束
|
||||
// 顶分型:中间元素高点最高
|
||||
if fm_h2 > fm_h1 and fm_h2 > fm_h3
|
||||
xd_broken := true
|
||||
// 或者连续两个特征序列元素低点下移
|
||||
if feat_size >= 2
|
||||
prev_feat_l = array.get(feat_lows, feat_size - 2)
|
||||
curr_feat_l = array.get(feat_lows, feat_size - 1)
|
||||
if curr_feat_l < prev_feat_l and curr_bi_end_price < array.get(bi_start_prices, i - 1)
|
||||
xd_broken := true
|
||||
else
|
||||
// 下降线段:向上笔高点创新高
|
||||
if curr_bi_dir == 1 and curr_bi_end_price > xd_start_price
|
||||
// 下降线段:特征序列(向上笔)出现底分型 → 线段结束
|
||||
// 底分型:中间元素低点最低
|
||||
if fm_l2 < fm_l1 and fm_l2 < fm_l3
|
||||
xd_broken := true
|
||||
|
||||
// === 第二种情况:特征序列不满足分型条件,但出现缺口确认反转 ===
|
||||
// 上升线段:如果某向下笔的低点直接跌破前一向上笔的高点(缺口),确认反转
|
||||
// 下降线段:如果某向上笔的高点直接突破前一向下笔的低点(缺口),确认反转
|
||||
if not xd_broken and fm_size >= 2
|
||||
if xd_dir == 1
|
||||
// 上升线段第二种情况:最近两个特征元素(向下笔),
|
||||
// 后者低点 < 前者低点,且后者高点 < 前者低点(缺口)
|
||||
fm_prev_h2 = array.get(feat_merged_highs, fm_size - 2)
|
||||
fm_prev_l2 = array.get(feat_merged_lows, fm_size - 2)
|
||||
fm_curr_h2 = array.get(feat_merged_highs, fm_size - 1)
|
||||
fm_curr_l2 = array.get(feat_merged_lows, fm_size - 1)
|
||||
if fm_curr_h2 < fm_prev_l2
|
||||
xd_broken := true
|
||||
else
|
||||
// 下降线段第二种情况:
|
||||
// 后者高点 > 前者高点,且后者低点 > 前者高点(缺口)
|
||||
fm_prev_h2 = array.get(feat_merged_highs, fm_size - 2)
|
||||
fm_prev_l2 = array.get(feat_merged_lows, fm_size - 2)
|
||||
fm_curr_h2 = array.get(feat_merged_highs, fm_size - 1)
|
||||
fm_curr_l2 = array.get(feat_merged_lows, fm_size - 1)
|
||||
if fm_curr_l2 > fm_prev_h2
|
||||
xd_broken := true
|
||||
// 或者连续两个特征序列元素高点上移
|
||||
if feat_size >= 2
|
||||
prev_feat_h = array.get(feat_highs, feat_size - 2)
|
||||
curr_feat_h = array.get(feat_highs, feat_size - 1)
|
||||
if curr_feat_h > prev_feat_h and curr_bi_end_price > array.get(bi_start_prices, i - 1)
|
||||
xd_broken := true
|
||||
|
||||
if xd_broken
|
||||
// 保存线段
|
||||
// 保存线段:上升线段终点取最高点,下降线段终点取最低点
|
||||
xd_end_bar = xd_dir == 1 ? xd_high_bar : xd_low_bar
|
||||
xd_end_price = xd_dir == 1 ? xd_high : xd_low
|
||||
|
||||
@@ -649,7 +731,7 @@ if barstate.islast
|
||||
array.push(xd_end_prices, xd_end_price)
|
||||
array.push(xd_dirs, xd_dir)
|
||||
|
||||
// 新线段
|
||||
// 新线段开始
|
||||
xd_start_bar := xd_end_bar
|
||||
xd_start_price := xd_end_price
|
||||
xd_dir := xd_dir == 1 ? -1 : 1
|
||||
@@ -662,14 +744,19 @@ if barstate.islast
|
||||
xd_low_bar := curr_bi_dir == -1 ? curr_bi_end_bar : curr_bi_start_bar
|
||||
|
||||
// 清空特征序列
|
||||
array.clear(feat_highs)
|
||||
array.clear(feat_lows)
|
||||
array.clear(feat_raw_highs)
|
||||
array.clear(feat_raw_lows)
|
||||
array.clear(feat_raw_end_bars)
|
||||
array.clear(feat_raw_end_prices)
|
||||
array.clear(feat_merged_highs)
|
||||
array.clear(feat_merged_lows)
|
||||
array.clear(feat_merged_end_bars)
|
||||
array.clear(feat_merged_end_prices)
|
||||
|
||||
i += 1
|
||||
|
||||
// 最后一个线段:只有在特征序列有至少2个元素时才保存(说明有足够的反向笔)
|
||||
// 未确认的线段不画出,避免误导
|
||||
feat_final_size = array.size(feat_highs)
|
||||
// 最后一个未完成线段:特征序列包含处理后至少有2个元素才保存
|
||||
feat_final_size = array.size(feat_merged_highs)
|
||||
if xd_bi_count >= 3 and feat_final_size >= 2
|
||||
xd_end_bar = xd_dir == 1 ? xd_high_bar : xd_low_bar
|
||||
xd_end_price = xd_dir == 1 ? xd_high : xd_low
|
||||
@@ -696,10 +783,12 @@ if barstate.islast
|
||||
xd_color = xd_dir_draw == 1 ? color.green : color.red
|
||||
line.new(s_bar, s_price, e_bar, e_price, color=xd_color, width=4)
|
||||
|
||||
// ==================== 构建笔中枢 ====================
|
||||
// 笔中枢必须在同一线段内,不能跨线段
|
||||
// 下跌线段中只有下跌笔中枢(上-下-上)
|
||||
// 上涨线段中只有上涨笔中枢(下-上-下)
|
||||
// ==================== 构建笔中枢(线段内部) ====================
|
||||
// 缠论标准:笔中枢必须在同一条线段内部构建
|
||||
// 中枢方向 = 所在线段的方向(上涨线段内 → 上涨中枢,下跌线段内 → 下跌中枢)
|
||||
// 中枢由线段内任意连续3笔的价格重叠区间构成
|
||||
// ZG = min(3笔高点),ZD = max(3笔低点),ZG > ZD 则构成中枢
|
||||
// 中枢延伸:同一线段内后续笔与中枢[ZD, ZG]有重叠,则时间扩展,区间不变
|
||||
var int[] bi_zs_start_bars = array.new<int>()
|
||||
var int[] bi_zs_end_bars = array.new<int>()
|
||||
var float[] bi_zs_highs = array.new<float>()
|
||||
@@ -712,99 +801,75 @@ if barstate.islast
|
||||
array.clear(bi_zs_lows)
|
||||
array.clear(bi_zs_types)
|
||||
|
||||
// 遍历每个线段,在线段内寻找笔中枢
|
||||
if xd_count > 0 and bi_count >= 3
|
||||
// 遍历每条线段,在线段内部寻找笔中枢
|
||||
for xd_idx = 0 to xd_count - 1
|
||||
xd_s_bar = array.get(xd_start_bars, xd_idx)
|
||||
xd_e_bar = array.get(xd_end_bars, xd_idx)
|
||||
xd_direction = array.get(xd_dirs, xd_idx)
|
||||
|
||||
// 找出该线段范围内的笔索引
|
||||
int[] xd_bi_indices = array.new<int>()
|
||||
// 收集该线段范围内的笔索引
|
||||
var int[] xd_bi_indices = array.new<int>()
|
||||
array.clear(xd_bi_indices)
|
||||
for bi_idx = 0 to bi_count - 1
|
||||
bi_s_bar = array.get(bi_start_bars, bi_idx)
|
||||
bi_e_bar = array.get(bi_end_bars, bi_idx)
|
||||
// 笔在线段范围内
|
||||
if bi_s_bar >= xd_s_bar and bi_e_bar <= xd_e_bar
|
||||
bi_s = array.get(bi_start_bars, bi_idx)
|
||||
bi_e = array.get(bi_end_bars, bi_idx)
|
||||
// 笔的起点和终点都在线段范围内
|
||||
if bi_s >= xd_s_bar and bi_e <= xd_e_bar
|
||||
array.push(xd_bi_indices, bi_idx)
|
||||
|
||||
xd_bi_count_local = array.size(xd_bi_indices)
|
||||
local_bi_count = array.size(xd_bi_indices)
|
||||
|
||||
// 在线段内寻找符合条件的三笔组合
|
||||
if xd_bi_count_local >= 3
|
||||
if local_bi_count >= 3
|
||||
j = 0
|
||||
while j <= xd_bi_count_local - 3
|
||||
while j <= local_bi_count - 3
|
||||
idx1 = array.get(xd_bi_indices, j)
|
||||
idx2 = array.get(xd_bi_indices, j + 1)
|
||||
idx3 = array.get(xd_bi_indices, j + 2)
|
||||
|
||||
bi1_dir = array.get(bi_dirs, idx1)
|
||||
bi2_dir = array.get(bi_dirs, idx2)
|
||||
bi3_dir = array.get(bi_dirs, idx3)
|
||||
bi1_h = math.max(array.get(bi_start_prices, idx1), array.get(bi_end_prices, idx1))
|
||||
bi1_l = math.min(array.get(bi_start_prices, idx1), array.get(bi_end_prices, idx1))
|
||||
bi2_h = math.max(array.get(bi_start_prices, idx2), array.get(bi_end_prices, idx2))
|
||||
bi2_l = math.min(array.get(bi_start_prices, idx2), array.get(bi_end_prices, idx2))
|
||||
bi3_h = math.max(array.get(bi_start_prices, idx3), array.get(bi_end_prices, idx3))
|
||||
bi3_l = math.min(array.get(bi_start_prices, idx3), array.get(bi_end_prices, idx3))
|
||||
|
||||
// 根据线段方向确定要找的中枢类型
|
||||
// 下跌线段(-1):找下跌笔中枢 (1, -1, 1)
|
||||
// 上涨线段(1):找上涨笔中枢 (-1, 1, -1)
|
||||
bool is_valid_zs = false
|
||||
if xd_direction == -1
|
||||
// 下跌线段,找下跌笔中枢(以上升笔开始)
|
||||
is_valid_zs := bi1_dir == 1 and bi2_dir == -1 and bi3_dir == 1
|
||||
else
|
||||
// 上涨线段,找上涨笔中枢(以下降笔开始)
|
||||
is_valid_zs := bi1_dir == -1 and bi2_dir == 1 and bi3_dir == -1
|
||||
zg = math.min(bi1_h, math.min(bi2_h, bi3_h))
|
||||
zd = math.max(bi1_l, math.max(bi2_l, bi3_l))
|
||||
|
||||
if is_valid_zs
|
||||
bi1_s_p = array.get(bi_start_prices, idx1)
|
||||
bi1_e_p = array.get(bi_end_prices, idx1)
|
||||
bi2_s_p = array.get(bi_start_prices, idx2)
|
||||
bi2_e_p = array.get(bi_end_prices, idx2)
|
||||
bi3_s_p = array.get(bi_start_prices, idx3)
|
||||
bi3_e_p = array.get(bi_end_prices, idx3)
|
||||
if zg > zd
|
||||
zs_start = array.get(bi_start_bars, idx1)
|
||||
zs_end = array.get(bi_end_bars, idx3)
|
||||
zs_type = xd_direction // 中枢方向 = 线段方向
|
||||
|
||||
bi1_h = math.max(bi1_s_p, bi1_e_p)
|
||||
bi1_l = math.min(bi1_s_p, bi1_e_p)
|
||||
bi2_h = math.max(bi2_s_p, bi2_e_p)
|
||||
bi2_l = math.min(bi2_s_p, bi2_e_p)
|
||||
bi3_h = math.max(bi3_s_p, bi3_e_p)
|
||||
bi3_l = math.min(bi3_s_p, bi3_e_p)
|
||||
// 中枢延伸:同一线段内后续笔与中枢有重叠
|
||||
last_ext = j + 2
|
||||
if j + 3 < local_bi_count
|
||||
for ext_j = j + 3 to local_bi_count - 1
|
||||
ext_idx = array.get(xd_bi_indices, ext_j)
|
||||
ext_h = math.max(array.get(bi_start_prices, ext_idx), array.get(bi_end_prices, ext_idx))
|
||||
ext_l = math.min(array.get(bi_start_prices, ext_idx), array.get(bi_end_prices, ext_idx))
|
||||
if ext_l < zg and ext_h > zd
|
||||
zs_end := array.get(bi_end_bars, ext_idx)
|
||||
last_ext := ext_j
|
||||
else
|
||||
break
|
||||
|
||||
zg = math.min(bi1_h, math.min(bi2_h, bi3_h))
|
||||
zd = math.max(bi1_l, math.max(bi2_l, bi3_l))
|
||||
// 避免与上一个中枢重叠
|
||||
should_add_zs = true
|
||||
zs_arr_size = array.size(bi_zs_start_bars)
|
||||
if zs_arr_size > 0
|
||||
last_zs_end = array.get(bi_zs_end_bars, zs_arr_size - 1)
|
||||
if zs_start <= last_zs_end
|
||||
should_add_zs := false
|
||||
|
||||
if zg > zd
|
||||
zs_start = array.get(bi_start_bars, idx1)
|
||||
zs_end = array.get(bi_end_bars, idx3)
|
||||
zs_type = xd_direction // 中枢类型与线段方向一致
|
||||
|
||||
should_add_zs = true
|
||||
zs_arr_size = array.size(bi_zs_start_bars)
|
||||
|
||||
if zs_arr_size > 0
|
||||
last_zs_start = array.get(bi_zs_start_bars, zs_arr_size - 1)
|
||||
last_zs_end = array.get(bi_zs_end_bars, zs_arr_size - 1)
|
||||
last_zs_h = array.get(bi_zs_highs, zs_arr_size - 1)
|
||||
last_zs_l = array.get(bi_zs_lows, zs_arr_size - 1)
|
||||
|
||||
// 检查上一个中枢是否在同一线段内
|
||||
last_zs_in_same_xd = last_zs_start >= xd_s_bar and last_zs_end <= xd_e_bar
|
||||
|
||||
if zs_start <= last_zs_end and last_zs_in_same_xd
|
||||
should_add_zs := false
|
||||
|
||||
// 中枢扩展:只有在同一线段内才能扩展
|
||||
if last_zs_in_same_xd and zg >= last_zs_l and zd <= last_zs_h and zs_start <= last_zs_end + 50
|
||||
array.set(bi_zs_end_bars, zs_arr_size - 1, zs_end)
|
||||
should_add_zs := false
|
||||
|
||||
if should_add_zs
|
||||
array.push(bi_zs_start_bars, zs_start)
|
||||
array.push(bi_zs_end_bars, zs_end)
|
||||
array.push(bi_zs_highs, zg)
|
||||
array.push(bi_zs_lows, zd)
|
||||
array.push(bi_zs_types, zs_type)
|
||||
j += 3
|
||||
else
|
||||
j += 1
|
||||
if should_add_zs
|
||||
array.push(bi_zs_start_bars, zs_start)
|
||||
array.push(bi_zs_end_bars, zs_end)
|
||||
array.push(bi_zs_highs, zg)
|
||||
array.push(bi_zs_lows, zd)
|
||||
array.push(bi_zs_types, zs_type)
|
||||
j := last_ext + 1
|
||||
else
|
||||
j += 1
|
||||
else
|
||||
@@ -813,8 +878,10 @@ if barstate.islast
|
||||
bi_zs_count = array.size(bi_zs_start_bars)
|
||||
|
||||
// ==================== 构建线段中枢 ====================
|
||||
// 跌出上一个中枢 → 新的下跌中枢以上涨线段开始 (1, -1, 1)
|
||||
// 涨出上一个中枢 → 新的上涨中枢以下降线段开始 (-1, 1, -1)
|
||||
// 上涨中枢:以下跌线段开始、下跌线段结束 (-1, 1, -1)
|
||||
// 下跌中枢:以上涨线段开始、上涨线段结束 (1, -1, 1)
|
||||
// ZG = min(各线段高点),ZD = max(各线段低点),ZG > ZD 则构成中枢
|
||||
// 中枢延伸:后续线段与中枢有重叠,则时间扩展,区间不变
|
||||
var int[] xd_zs_start_bars = array.new<int>()
|
||||
var int[] xd_zs_end_bars = array.new<int>()
|
||||
var float[] xd_zs_highs = array.new<float>()
|
||||
@@ -828,52 +895,19 @@ if barstate.islast
|
||||
array.clear(xd_zs_types)
|
||||
|
||||
if xd_count >= 3
|
||||
// 跟踪上一个中枢信息
|
||||
last_zs_high = 0.0
|
||||
last_zs_low = 0.0
|
||||
last_zs_end_idx = -1 // 上一个中枢结束的线段索引
|
||||
|
||||
i = 0
|
||||
while i <= xd_count - 3
|
||||
// 获取三个线段的方向
|
||||
// 检查线段方向模式
|
||||
xd1_dir = array.get(xd_dirs, i)
|
||||
xd2_dir = array.get(xd_dirs, i + 1)
|
||||
xd3_dir = array.get(xd_dirs, i + 2)
|
||||
|
||||
// 检查是否符合中枢形态
|
||||
// 下跌中枢:上升-下降-上升 (1, -1, 1) - 以上升线段开始和结束
|
||||
// 上涨中枢:下降-上升-下降 (-1, 1, -1) - 以下降线段开始和结束
|
||||
is_down_xd_zs = xd1_dir == 1 and xd2_dir == -1 and xd3_dir == 1
|
||||
// 上涨中枢: (-1, 1, -1) 下跌线段开始下跌线段结束
|
||||
is_up_xd_zs = xd1_dir == -1 and xd2_dir == 1 and xd3_dir == -1
|
||||
// 下跌中枢: (1, -1, 1) 上涨线段开始上涨线段结束
|
||||
is_down_xd_zs = xd1_dir == 1 and xd2_dir == -1 and xd3_dir == 1
|
||||
|
||||
// 检查是否符合离开方向的要求
|
||||
bool type_matches = false
|
||||
if last_zs_end_idx < 0
|
||||
// 没有上一个中枢,任意类型都可以
|
||||
type_matches := is_down_xd_zs or is_up_xd_zs
|
||||
else
|
||||
// 检查从上一个中枢到当前位置之间,是否有线段离开了上一个中枢
|
||||
// 找到离开上一个中枢的方向
|
||||
leave_direction = 0 // 0=未离开, 1=向上离开, -1=向下离开
|
||||
for check_idx = last_zs_end_idx to i
|
||||
if check_idx < xd_count
|
||||
check_price = array.get(xd_end_prices, check_idx)
|
||||
if check_price < last_zs_low and leave_direction != -1
|
||||
leave_direction := -1 // 向下离开
|
||||
else if check_price > last_zs_high and leave_direction != 1
|
||||
leave_direction := 1 // 向上离开
|
||||
|
||||
if leave_direction == -1
|
||||
// 向下离开,期望下跌中枢
|
||||
type_matches := is_down_xd_zs
|
||||
else if leave_direction == 1
|
||||
// 向上离开,期望上涨中枢
|
||||
type_matches := is_up_xd_zs
|
||||
else
|
||||
// 未离开中枢,不形成新中枢
|
||||
type_matches := false
|
||||
|
||||
if type_matches and (is_down_xd_zs or is_up_xd_zs)
|
||||
if is_up_xd_zs or is_down_xd_zs
|
||||
xd1_s_p = array.get(xd_start_prices, i)
|
||||
xd1_e_p = array.get(xd_end_prices, i)
|
||||
xd2_s_p = array.get(xd_start_prices, i + 1)
|
||||
@@ -896,20 +930,26 @@ if barstate.islast
|
||||
zs_end_xd = array.get(xd_end_bars, i + 2)
|
||||
xd_zs_type = is_up_xd_zs ? 1 : -1
|
||||
|
||||
// 中枢延伸:后续线段与中枢有重叠,则延伸时间范围
|
||||
last_ext_xd = i + 2
|
||||
if i + 3 < xd_count
|
||||
for ext_idx = i + 3 to xd_count - 1
|
||||
ext_s_p = array.get(xd_start_prices, ext_idx)
|
||||
ext_e_p = array.get(xd_end_prices, ext_idx)
|
||||
ext_h = math.max(ext_s_p, ext_e_p)
|
||||
ext_l = math.min(ext_s_p, ext_e_p)
|
||||
if ext_l < zg_xd and ext_h > zd_xd
|
||||
zs_end_xd := array.get(xd_end_bars, ext_idx)
|
||||
last_ext_xd := ext_idx
|
||||
else
|
||||
break
|
||||
|
||||
should_add_xd_zs = true
|
||||
xd_zs_arr_size = array.size(xd_zs_start_bars)
|
||||
|
||||
if xd_zs_arr_size > 0
|
||||
last_xd_zs_end = array.get(xd_zs_end_bars, xd_zs_arr_size - 1)
|
||||
|
||||
if zs_start_xd <= last_xd_zs_end
|
||||
should_add_xd_zs := false
|
||||
|
||||
// 中枢扩展(同类型中枢且有重叠)
|
||||
last_xd_zs_type = array.get(xd_zs_types, xd_zs_arr_size - 1)
|
||||
if xd_zs_type == last_xd_zs_type and zg_xd >= last_zs_low and zd_xd <= last_zs_high and zs_start_xd <= last_xd_zs_end + 100
|
||||
array.set(xd_zs_end_bars, xd_zs_arr_size - 1, zs_end_xd)
|
||||
should_add_xd_zs := false
|
||||
|
||||
if should_add_xd_zs
|
||||
array.push(xd_zs_start_bars, zs_start_xd)
|
||||
@@ -917,13 +957,7 @@ if barstate.islast
|
||||
array.push(xd_zs_highs, zg_xd)
|
||||
array.push(xd_zs_lows, zd_xd)
|
||||
array.push(xd_zs_types, xd_zs_type)
|
||||
|
||||
// 更新上一个中枢信息
|
||||
last_zs_high := zg_xd
|
||||
last_zs_low := zd_xd
|
||||
last_zs_end_idx := i + 2
|
||||
|
||||
i += 3
|
||||
i := last_ext_xd + 1
|
||||
else
|
||||
i += 1
|
||||
else
|
||||
@@ -934,7 +968,7 @@ if barstate.islast
|
||||
xd_zs_count = array.size(xd_zs_start_bars)
|
||||
|
||||
// ==================== 绘制笔中枢 ====================
|
||||
// 上涨中枢用绿色,下跌中枢用红色
|
||||
// 上涨中枢(1)=绿色,下跌中枢(-1)=红色
|
||||
if show_bi_zhongshu and bi_zs_count > 0
|
||||
for i = 0 to bi_zs_count - 1
|
||||
zs_start = array.get(bi_zs_start_bars, i)
|
||||
@@ -944,16 +978,13 @@ if barstate.islast
|
||||
zs_type = array.get(bi_zs_types, i)
|
||||
|
||||
if bar_index - zs_start <= 5000
|
||||
// 上涨中枢(1)=绿色边框,下跌中枢(-1)=红色边框
|
||||
zs_border = zs_type == 1 ? color.green : color.red
|
||||
zs_bg = zs_type == 1 ? color.new(color.green, 85) : color.new(color.red, 85)
|
||||
box.new(zs_start, zs_h, zs_end, zs_l,
|
||||
border_color=zs_border,
|
||||
bgcolor=zs_bg,
|
||||
border_width=1)
|
||||
border_color=zs_border, bgcolor=zs_bg, border_width=1)
|
||||
|
||||
// ==================== 绘制线段中枢 ====================
|
||||
// 上涨中枢用绿色,下跌中枢用红色
|
||||
// 上涨中枢(1)=绿色,下跌中枢(-1)=红色
|
||||
if show_xd_zhongshu and xd_zs_count > 0
|
||||
for i = 0 to xd_zs_count - 1
|
||||
zs_start = array.get(xd_zs_start_bars, i)
|
||||
@@ -963,189 +994,137 @@ if barstate.islast
|
||||
xd_zs_type = array.get(xd_zs_types, i)
|
||||
|
||||
if bar_index - zs_start <= 5000
|
||||
// 上涨中枢(1)=绿色边框,下跌中枢(-1)=红色边框
|
||||
xd_zs_border = xd_zs_type == 1 ? color.lime : color.maroon
|
||||
xd_zs_bg = xd_zs_type == 1 ? color.new(color.lime, 80) : color.new(color.maroon, 80)
|
||||
box.new(zs_start, zs_h, zs_end, zs_l,
|
||||
border_color=xd_zs_border,
|
||||
bgcolor=xd_zs_bg,
|
||||
border_width=2)
|
||||
border_color=xd_zs_border, bgcolor=xd_zs_bg, border_width=2)
|
||||
|
||||
// ==================== 买卖点(缠论标准三类买卖点) ====================
|
||||
// 第一类:趋势背驰点(离开中枢后与进入中枢前的走势发生MACD背驰)
|
||||
// 第二类:第一类之后回调/反弹不破第一类
|
||||
// 第三类:离开中枢后回调/反弹不回到中枢内部
|
||||
// ==================== 买卖点(缠论标准三类买卖点 - 与笔中枢方向对应) ====================
|
||||
// 笔中枢方向 = 线段方向
|
||||
// 下跌中枢(-1):在中枢下方找一买(底背驰)
|
||||
// 上涨中枢(1):在中枢上方找一卖(顶背驰)
|
||||
// 三买三卖:离开中枢后回调/反弹不回到中枢内部
|
||||
|
||||
// 存储已标记的买卖点,避免重复
|
||||
var int[] bs_bars = array.new<int>()
|
||||
var int[] bs_types = array.new<int>() // 正数=买点,负数=卖点,绝对值=类型
|
||||
var int[] bs_types = array.new<int>()
|
||||
var float[] bs_prices = array.new<float>()
|
||||
|
||||
array.clear(bs_bars)
|
||||
array.clear(bs_types)
|
||||
array.clear(bs_prices)
|
||||
|
||||
max_zs_to_process = math.min(bi_zs_count, 15)
|
||||
zs_start_idx = bi_zs_count - max_zs_to_process
|
||||
|
||||
if show_buy_sell and bi_zs_count > 0 and fx_count >= 2
|
||||
// 遍历笔中枢,寻找买卖点
|
||||
for j = 0 to bi_zs_count - 1
|
||||
for j = zs_start_idx to bi_zs_count - 1
|
||||
zs_start = array.get(bi_zs_start_bars, j)
|
||||
zs_end = array.get(bi_zs_end_bars, j)
|
||||
zs_h = array.get(bi_zs_highs, j)
|
||||
zs_l = array.get(bi_zs_lows, j)
|
||||
zs_type = array.get(bi_zs_types, j) // 1=上涨中枢, -1=下跌中枢
|
||||
|
||||
// ========== 寻找第一类买卖点(背驰)==========
|
||||
// 找中枢前最后一个同向极值分型(作为背驰比较基准)
|
||||
float prev_extreme_price = na
|
||||
float prev_extreme_macd = na
|
||||
// 找中枢前最后一个底分型(用于一买背驰比较)
|
||||
float prev_bottom_price = na
|
||||
float prev_bottom_macd = na
|
||||
|
||||
for i = 0 to fx_count - 1
|
||||
// 找中枢前最后一个顶分型(用于一卖背驰比较)
|
||||
float prev_top_price = na
|
||||
float prev_top_macd = na
|
||||
|
||||
for i = fx_count - 1 to 0
|
||||
fx_b = array.get(fx_bars, i)
|
||||
fx_p = array.get(fx_prices, i)
|
||||
if fx_b >= zs_start
|
||||
continue
|
||||
fx_t = array.get(fx_types, i)
|
||||
fx_p = array.get(fx_prices, i)
|
||||
fx_m = array.get(fx_macds, i)
|
||||
if fx_b < zs_start
|
||||
// 下跌中枢(需要一买):找之前的底分型
|
||||
if zs_type == -1 and fx_t == -1
|
||||
prev_extreme_price := fx_p
|
||||
prev_extreme_macd := fx_m
|
||||
// 上涨中枢(需要一卖):找之前的顶分型
|
||||
else if zs_type == 1 and fx_t == 1
|
||||
prev_extreme_price := fx_p
|
||||
prev_extreme_macd := fx_m
|
||||
if fx_t == -1 and na(prev_bottom_price)
|
||||
prev_bottom_price := fx_p
|
||||
prev_bottom_macd := fx_m
|
||||
if fx_t == 1 and na(prev_top_price)
|
||||
prev_top_price := fx_p
|
||||
prev_top_macd := fx_m
|
||||
if not na(prev_bottom_price) and not na(prev_top_price)
|
||||
break
|
||||
|
||||
// 找中枢后的极值分型(离开中枢的点)
|
||||
// 找中枢后的分型
|
||||
float leave_price = na
|
||||
float leave_macd = na
|
||||
int leave_bar = na
|
||||
bool has_left_zs = false // 是否已经离开中枢
|
||||
bool has_left_zs = false
|
||||
bool found_1st = false
|
||||
|
||||
for i = 0 to fx_count - 1
|
||||
if found_1st and has_left_zs
|
||||
break
|
||||
fx_bar = array.get(fx_bars, i)
|
||||
if fx_bar <= zs_end
|
||||
continue
|
||||
|
||||
fx_price = array.get(fx_prices, i)
|
||||
fx_type = array.get(fx_types, i)
|
||||
fx_macd = array.get(fx_macds, i)
|
||||
|
||||
if fx_bar <= zs_end
|
||||
continue
|
||||
if bar_index - fx_bar > 5000
|
||||
continue
|
||||
|
||||
// MACD过滤
|
||||
macd_valid = not use_macd_filter or (fx_type == 1 and fx_macd > 0) or (fx_type == -1 and fx_macd < 0)
|
||||
|
||||
// ========== 第一类买点(一买)==========
|
||||
// 下跌中枢 + 底分型跌破中枢下沿 + MACD背驰
|
||||
if zs_type == -1 and fx_type == -1 and fx_price < zs_l and macd_valid
|
||||
// 背驰:价格更低,但MACD柱状图绝对值更小(负值更大)
|
||||
is_divergence = not na(prev_extreme_macd) and not na(prev_extreme_price) and fx_price < prev_extreme_price and fx_macd > prev_extreme_macd
|
||||
if is_divergence
|
||||
already_marked = false
|
||||
if array.size(bs_bars) > 0
|
||||
for k = 0 to array.size(bs_bars) - 1
|
||||
if array.get(bs_bars, k) == fx_bar
|
||||
already_marked := true
|
||||
break
|
||||
if not already_marked
|
||||
label.new(fx_bar, fx_price * 0.998, "1买",
|
||||
color=color.lime,
|
||||
style=label.style_label_up,
|
||||
textcolor=color.black,
|
||||
size=size.tiny)
|
||||
array.push(bs_bars, fx_bar)
|
||||
array.push(bs_types, 1)
|
||||
array.push(bs_prices, fx_price)
|
||||
// 一买:下跌中枢(-1)下方的底分型背驰
|
||||
if not found_1st and zs_type == -1 and fx_type == -1 and fx_price < zs_l and macd_valid
|
||||
if not na(prev_bottom_macd) and not na(prev_bottom_price) and fx_price < prev_bottom_price and fx_macd > prev_bottom_macd
|
||||
label.new(fx_bar, fx_price * 0.998, "1买", color=color.lime, style=label.style_label_up, textcolor=color.black, size=size.tiny)
|
||||
array.push(bs_bars, fx_bar)
|
||||
array.push(bs_types, 1)
|
||||
array.push(bs_prices, fx_price)
|
||||
found_1st := true
|
||||
|
||||
// ========== 第一类卖点(一卖)==========
|
||||
// 上涨中枢 + 顶分型突破中枢上沿 + MACD背驰
|
||||
if zs_type == 1 and fx_type == 1 and fx_price > zs_h and macd_valid
|
||||
// 背驰:价格更高,但MACD柱状图更小
|
||||
is_divergence = not na(prev_extreme_macd) and not na(prev_extreme_price) and fx_price > prev_extreme_price and fx_macd < prev_extreme_macd
|
||||
if is_divergence
|
||||
already_marked = false
|
||||
if array.size(bs_bars) > 0
|
||||
for k = 0 to array.size(bs_bars) - 1
|
||||
if array.get(bs_bars, k) == fx_bar
|
||||
already_marked := true
|
||||
break
|
||||
if not already_marked
|
||||
label.new(fx_bar, fx_price * 1.002, "1卖",
|
||||
color=color.red,
|
||||
style=label.style_label_down,
|
||||
textcolor=color.white,
|
||||
size=size.tiny)
|
||||
array.push(bs_bars, fx_bar)
|
||||
array.push(bs_types, -1)
|
||||
array.push(bs_prices, fx_price)
|
||||
// 一卖:上涨中枢(1)上方的顶分型背驰
|
||||
if not found_1st and zs_type == 1 and fx_type == 1 and fx_price > zs_h and macd_valid
|
||||
if not na(prev_top_macd) and not na(prev_top_price) and fx_price > prev_top_price and fx_macd < prev_top_macd
|
||||
label.new(fx_bar, fx_price * 1.002, "1卖", color=color.red, style=label.style_label_down, textcolor=color.white, size=size.tiny)
|
||||
array.push(bs_bars, fx_bar)
|
||||
array.push(bs_types, -1)
|
||||
array.push(bs_prices, fx_price)
|
||||
found_1st := true
|
||||
|
||||
// 记录离开中枢的极值点(用于判断三买三卖)
|
||||
if fx_type == 1 and fx_price > zs_h and not has_left_zs
|
||||
// 顶分型突破中枢上沿 = 向上离开
|
||||
leave_price := fx_price
|
||||
leave_bar := fx_bar
|
||||
has_left_zs := true
|
||||
if fx_type == -1 and fx_price < zs_l and not has_left_zs
|
||||
// 底分型跌破中枢下沿 = 向下离开
|
||||
leave_price := fx_price
|
||||
leave_bar := fx_bar
|
||||
has_left_zs := true
|
||||
// 记录离开中枢点
|
||||
if not has_left_zs
|
||||
if zs_type == -1 and fx_type == 1 and fx_price > zs_h
|
||||
// 下跌中枢向上离开
|
||||
leave_price := fx_price
|
||||
leave_bar := fx_bar
|
||||
has_left_zs := true
|
||||
if zs_type == 1 and fx_type == -1 and fx_price < zs_l
|
||||
// 上涨中枢向下离开
|
||||
leave_price := fx_price
|
||||
leave_bar := fx_bar
|
||||
has_left_zs := true
|
||||
|
||||
// ========== 第三类买卖点 ==========
|
||||
// 需要先离开中枢,再回调/反弹不回到中枢
|
||||
// 三买三卖
|
||||
if has_left_zs and not na(leave_bar)
|
||||
for i = 0 to fx_count - 1
|
||||
fx_bar = array.get(fx_bars, i)
|
||||
if fx_bar <= leave_bar
|
||||
continue
|
||||
fx_price = array.get(fx_prices, i)
|
||||
fx_type = array.get(fx_types, i)
|
||||
fx_macd = array.get(fx_macds, i)
|
||||
|
||||
if fx_bar <= leave_bar
|
||||
continue
|
||||
if bar_index - fx_bar > 5000
|
||||
continue
|
||||
|
||||
macd_valid = not use_macd_filter or (fx_type == 1 and fx_macd > 0) or (fx_type == -1 and fx_macd < 0)
|
||||
|
||||
// 三买:向上离开后,回调底分型不跌破中枢上沿
|
||||
if leave_price > zs_h and fx_type == -1 and fx_price > zs_h and macd_valid
|
||||
already_marked = false
|
||||
if array.size(bs_bars) > 0
|
||||
for k = 0 to array.size(bs_bars) - 1
|
||||
if array.get(bs_bars, k) == fx_bar
|
||||
already_marked := true
|
||||
break
|
||||
if not already_marked
|
||||
label.new(fx_bar, fx_price * 0.998, "3买",
|
||||
color=color.new(color.lime, 30),
|
||||
style=label.style_label_up,
|
||||
textcolor=color.black,
|
||||
size=size.tiny)
|
||||
array.push(bs_bars, fx_bar)
|
||||
array.push(bs_types, 3)
|
||||
array.push(bs_prices, fx_price)
|
||||
break // 只找第一个三买
|
||||
// 三买:下跌中枢向上离开后,回调底分型不跌破中枢上沿
|
||||
if zs_type == -1 and leave_price > zs_h and fx_type == -1 and fx_price > zs_h and macd_valid
|
||||
label.new(fx_bar, fx_price * 0.998, "3买", color=color.new(color.lime, 30), style=label.style_label_up, textcolor=color.black, size=size.tiny)
|
||||
array.push(bs_bars, fx_bar)
|
||||
array.push(bs_types, 3)
|
||||
array.push(bs_prices, fx_price)
|
||||
break
|
||||
|
||||
// 三卖:向下离开后,反弹顶分型不涨过中枢下沿
|
||||
if leave_price < zs_l and fx_type == 1 and fx_price < zs_l and macd_valid
|
||||
already_marked = false
|
||||
if array.size(bs_bars) > 0
|
||||
for k = 0 to array.size(bs_bars) - 1
|
||||
if array.get(bs_bars, k) == fx_bar
|
||||
already_marked := true
|
||||
break
|
||||
if not already_marked
|
||||
label.new(fx_bar, fx_price * 1.002, "3卖",
|
||||
color=color.new(color.red, 30),
|
||||
style=label.style_label_down,
|
||||
textcolor=color.white,
|
||||
size=size.tiny)
|
||||
array.push(bs_bars, fx_bar)
|
||||
array.push(bs_types, -3)
|
||||
array.push(bs_prices, fx_price)
|
||||
break // 只找第一个三卖
|
||||
// 三卖:上涨中枢向下离开后,反弹顶分型不涨过中枢下沿
|
||||
if zs_type == 1 and leave_price < zs_l and fx_type == 1 and fx_price < zs_l and macd_valid
|
||||
label.new(fx_bar, fx_price * 1.002, "3卖", color=color.new(color.red, 30), style=label.style_label_down, textcolor=color.white, size=size.tiny)
|
||||
array.push(bs_bars, fx_bar)
|
||||
array.push(bs_types, -3)
|
||||
array.push(bs_prices, fx_price)
|
||||
break
|
||||
|
||||
// ========== 第二类买卖点 ==========
|
||||
// 遍历已标记的第一类买卖点,寻找第二类
|
||||
// 二买二卖
|
||||
bs_count = array.size(bs_bars)
|
||||
if bs_count > 0
|
||||
for k = 0 to bs_count - 1
|
||||
@@ -1153,83 +1132,49 @@ if barstate.islast
|
||||
bs_type = array.get(bs_types, k)
|
||||
bs_price = array.get(bs_prices, k)
|
||||
|
||||
// 第二类买点:一买之后,反弹形成顶分型,再回落形成底分型,且不破一买低点
|
||||
if bs_type == 1
|
||||
// 找一买之后的顶分型(反弹高点)
|
||||
if bs_type == 1 // 一买后找二买
|
||||
int bounce_bar = na
|
||||
for i = 0 to fx_count - 1
|
||||
fx_b = array.get(fx_bars, i)
|
||||
if fx_b <= bs_bar
|
||||
continue
|
||||
fx_t = array.get(fx_types, i)
|
||||
if fx_b > bs_bar and fx_t == 1
|
||||
if na(bounce_bar) and fx_t == 1
|
||||
bounce_bar := fx_b
|
||||
break
|
||||
|
||||
// 找反弹后的底分型(二买候选),且必须不破一买
|
||||
if not na(bounce_bar)
|
||||
for i = 0 to fx_count - 1
|
||||
fx_b = array.get(fx_bars, i)
|
||||
continue
|
||||
if not na(bounce_bar) and fx_t == -1
|
||||
fx_p = array.get(fx_prices, i)
|
||||
fx_t = array.get(fx_types, i)
|
||||
fx_m = array.get(fx_macds, i)
|
||||
|
||||
if fx_b > bounce_bar and fx_t == -1 and fx_p > bs_price
|
||||
already_marked = false
|
||||
if array.size(bs_bars) > 0
|
||||
for m = 0 to array.size(bs_bars) - 1
|
||||
if array.get(bs_bars, m) == fx_b
|
||||
already_marked := true
|
||||
break
|
||||
|
||||
if fx_p > bs_price
|
||||
fx_m = array.get(fx_macds, i)
|
||||
macd_valid = not use_macd_filter or fx_m < 0
|
||||
if not already_marked and macd_valid and bar_index - fx_b <= 5000
|
||||
label.new(fx_b, fx_p * 0.998, "2买",
|
||||
color=color.new(color.lime, 50),
|
||||
style=label.style_label_up,
|
||||
textcolor=color.black,
|
||||
size=size.tiny)
|
||||
if macd_valid
|
||||
label.new(fx_b, fx_p * 0.998, "2买", color=color.new(color.lime, 50), style=label.style_label_up, textcolor=color.black, size=size.tiny)
|
||||
array.push(bs_bars, fx_b)
|
||||
array.push(bs_types, 2)
|
||||
array.push(bs_prices, fx_p)
|
||||
break
|
||||
break
|
||||
|
||||
// 第二类卖点:一卖之后,回调形成底分型,再上涨形成顶分型,且不过一卖高点
|
||||
if bs_type == -1
|
||||
// 找一卖之后的底分型(回调低点)
|
||||
if bs_type == -1 // 一卖后找二卖
|
||||
int pullback_bar = na
|
||||
for i = 0 to fx_count - 1
|
||||
fx_b = array.get(fx_bars, i)
|
||||
if fx_b <= bs_bar
|
||||
continue
|
||||
fx_t = array.get(fx_types, i)
|
||||
if fx_b > bs_bar and fx_t == -1
|
||||
if na(pullback_bar) and fx_t == -1
|
||||
pullback_bar := fx_b
|
||||
break
|
||||
|
||||
// 找回调后的顶分型(二卖候选),且必须不过一卖
|
||||
if not na(pullback_bar)
|
||||
for i = 0 to fx_count - 1
|
||||
fx_b = array.get(fx_bars, i)
|
||||
continue
|
||||
if not na(pullback_bar) and fx_t == 1
|
||||
fx_p = array.get(fx_prices, i)
|
||||
fx_t = array.get(fx_types, i)
|
||||
fx_m = array.get(fx_macds, i)
|
||||
|
||||
if fx_b > pullback_bar and fx_t == 1 and fx_p < bs_price
|
||||
already_marked = false
|
||||
if array.size(bs_bars) > 0
|
||||
for m = 0 to array.size(bs_bars) - 1
|
||||
if array.get(bs_bars, m) == fx_b
|
||||
already_marked := true
|
||||
break
|
||||
|
||||
if fx_p < bs_price
|
||||
fx_m = array.get(fx_macds, i)
|
||||
macd_valid = not use_macd_filter or fx_m > 0
|
||||
if not already_marked and macd_valid and bar_index - fx_b <= 5000
|
||||
label.new(fx_b, fx_p * 1.002, "2卖",
|
||||
color=color.new(color.red, 50),
|
||||
style=label.style_label_down,
|
||||
textcolor=color.white,
|
||||
size=size.tiny)
|
||||
if macd_valid
|
||||
label.new(fx_b, fx_p * 1.002, "2卖", color=color.new(color.red, 50), style=label.style_label_down, textcolor=color.white, size=size.tiny)
|
||||
array.push(bs_bars, fx_b)
|
||||
array.push(bs_types, -2)
|
||||
array.push(bs_prices, fx_p)
|
||||
break
|
||||
break
|
||||
|
||||
// ==================== 信息面板 ====================
|
||||
var table info_panel = table.new(position.top_right, 2, 8,
|
||||
|
||||
Reference in New Issue
Block a user