317 lines
15 KiB
Plaintext
317 lines
15 KiB
Plaintext
//@version=6
|
||
indicator(title="EMA+MACD 三态趋势判断", shorttitle="EMA+MACD趋势", overlay=true, max_labels_count=500)
|
||
|
||
// ========================= 输入参数 =========================
|
||
// EMA 参数
|
||
ema1_len = input.int(9, "EMA1 快线周期", minval=1, inline="ema1")
|
||
ema2_len = input.int(21, "EMA2 中线周期", minval=1, inline="ema2")
|
||
ema3_len = input.int(55, "EMA3 慢线周期", minval=1, inline="ema3")
|
||
ema4_len = input.int(200, "EMA4 超慢线周期", minval=1, inline="ema4")
|
||
use_ema4 = input.bool(true, "启用第4条均线(EMA200)", inline="ema4")
|
||
|
||
// MACD 参数
|
||
macd_fast = input.int(12, "MACD快线周期", minval=1, group="MACD设置")
|
||
macd_slow = input.int(26, "MACD慢线周期", minval=1, group="MACD设置")
|
||
macd_signal = input.int(9, "MACD信号线周期", minval=1, group="MACD设置")
|
||
|
||
// 趋势判断参数
|
||
ema_spread_thresh = input.float(0.3, "EMA收束阈值(%)", minval=0.1, maxval=2.0, step=0.1, group="趋势判断") / 100
|
||
macd_zero_zone = input.float(0.1, "MACD零轴区域(%)", minval=0.01, maxval=0.5, step=0.01, group="趋势判断") / 100
|
||
confirm_bars = input.int(2, "趋势确认周期", minval=1, maxval=5, group="趋势判断")
|
||
|
||
// 显示设置
|
||
show_ema = input.bool(true, "显示EMA线", group="显示设置")
|
||
show_signals = input.bool(true, "显示状态切换信号", group="显示设置")
|
||
show_background = input.bool(true, "背景着色", group="显示设置")
|
||
show_info_panel = input.bool(true, "显示信息面板", group="显示设置")
|
||
|
||
// 颜色设置
|
||
col_uptrend = input.color(color.new(color.teal, 80), "上涨趋势颜色", group="颜色设置")
|
||
col_downtrend = input.color(color.new(color.red, 80), "下跌趋势颜色", group="颜色设置")
|
||
col_consolidation = input.color(color.new(color.gray, 85), "盘整趋势颜色", group="颜色设置")
|
||
|
||
// ========================= 指标计算 =========================
|
||
// EMA计算
|
||
ema1 = ta.ema(close, ema1_len)
|
||
ema2 = ta.ema(close, ema2_len)
|
||
ema3 = ta.ema(close, ema3_len)
|
||
ema4 = use_ema4 ? ta.ema(close, ema4_len) : na
|
||
|
||
// MACD计算
|
||
[macdLine, signalLine, histLine] = ta.macd(close, macd_fast, macd_slow, macd_signal)
|
||
macd_normalized = macdLine / close // 归一化MACD便于比较
|
||
|
||
// ========================= EMA排列判断 =========================
|
||
// 多头排列: EMA1 > EMA2 > EMA3 (> EMA4 if enabled)
|
||
bull_alignment_3 = ema1 > ema2 and ema2 > ema3
|
||
bull_alignment = use_ema4 ? (bull_alignment_3 and ema3 > ema4) : bull_alignment_3
|
||
|
||
// 空头排列: EMA1 < EMA2 < EMA3 (< EMA4 if enabled)
|
||
bear_alignment_3 = ema1 < ema2 and ema2 < ema3
|
||
bear_alignment = use_ema4 ? (bear_alignment_3 and ema3 < ema4) : bear_alignment_3
|
||
|
||
// EMA方向一致性(斜率判断)
|
||
ema1_rising = ema1 > ema1[1]
|
||
ema2_rising = ema2 > ema2[1]
|
||
ema3_rising = ema3 > ema3[1]
|
||
ema4_rising = use_ema4 ? ema4 > ema4[1] : true
|
||
|
||
ema1_falling = ema1 < ema1[1]
|
||
ema2_falling = ema2 < ema2[1]
|
||
ema3_falling = ema3 < ema3[1]
|
||
ema4_falling = use_ema4 ? ema4 < ema4[1] : true
|
||
|
||
all_rising = ema1_rising and ema2_rising and ema3_rising and (not use_ema4 or ema4_rising)
|
||
all_falling = ema1_falling and ema2_falling and ema3_falling and (not use_ema4 or ema4_falling)
|
||
|
||
// EMA收束程度(判断盘整)
|
||
max_ema = math.max(math.max(ema1, ema2), ema3)
|
||
min_ema = math.min(math.min(ema1, ema2), ema3)
|
||
ema_spread = (max_ema - min_ema) / close
|
||
emas_converged = ema_spread < ema_spread_thresh
|
||
|
||
// ========================= MACD状态判断 =========================
|
||
// MACD方向
|
||
macd_bullish = macdLine > signalLine
|
||
macd_bearish = macdLine < signalLine
|
||
|
||
// MACD位置
|
||
macd_above_zero = macdLine > 0
|
||
macd_below_zero = macdLine < 0
|
||
macd_near_zero = math.abs(macd_normalized) < macd_zero_zone
|
||
|
||
// MACD柱状图趋势
|
||
hist_expanding_up = histLine > histLine[1] and histLine > 0
|
||
hist_expanding_down = histLine < histLine[1] and histLine < 0
|
||
hist_shrinking = math.abs(histLine) < math.abs(histLine[1])
|
||
|
||
// MACD综合强度评分 (-2 到 +2)
|
||
macd_score = 0
|
||
macd_score := macd_bullish ? macd_score + 1 : macd_score - 1
|
||
macd_score := macd_above_zero ? macd_score + 1 : macd_below_zero ? macd_score - 1 : macd_score
|
||
|
||
// ========================= 综合趋势判断 =========================
|
||
// 上涨趋势条件:
|
||
// 1. EMA多头排列 OR (EMA方向一致向上 AND 价格在EMA上方)
|
||
// 2. MACD评分 >= 1 (至少看涨)
|
||
price_above_emas = close > ema1 and close > ema2 and close > ema3
|
||
uptrend_ema = bull_alignment or (all_rising and price_above_emas)
|
||
uptrend_macd = macd_score >= 1 or (macd_bullish and not macd_near_zero)
|
||
uptrend_raw = uptrend_ema and uptrend_macd
|
||
|
||
// 下跌趋势条件:
|
||
// 1. EMA空头排列 OR (EMA方向一致向下 AND 价格在EMA下方)
|
||
// 2. MACD评分 <= -1 (至少看跌)
|
||
price_below_emas = close < ema1 and close < ema2 and close < ema3
|
||
downtrend_ema = bear_alignment or (all_falling and price_below_emas)
|
||
downtrend_macd = macd_score <= -1 or (macd_bearish and not macd_near_zero)
|
||
downtrend_raw = downtrend_ema and downtrend_macd
|
||
|
||
// 盘整趋势条件:
|
||
// 1. EMA收束 OR 无明确排列
|
||
// 2. MACD在零轴附近 OR 柱状图收缩
|
||
consolidation_ema = emas_converged or (not bull_alignment and not bear_alignment)
|
||
consolidation_macd = macd_near_zero or hist_shrinking
|
||
consolidation_raw = (consolidation_ema and consolidation_macd) or (not uptrend_raw and not downtrend_raw)
|
||
|
||
// ========================= 连续确认计数 =========================
|
||
var int uptrend_count = 0
|
||
var int downtrend_count = 0
|
||
var int consolidation_count = 0
|
||
|
||
uptrend_count := uptrend_raw ? uptrend_count + 1 : 0
|
||
downtrend_count := downtrend_raw ? downtrend_count + 1 : 0
|
||
consolidation_count := consolidation_raw ? consolidation_count + 1 : 0
|
||
|
||
// 确认后的趋势信号
|
||
uptrend_confirmed = uptrend_count >= confirm_bars
|
||
downtrend_confirmed = downtrend_count >= confirm_bars
|
||
consolidation_confirmed = consolidation_count >= confirm_bars
|
||
|
||
// ========================= 状态机 =========================
|
||
// 状态: 0=盘整, 1=上涨, -1=下跌
|
||
var int trend_state = 0
|
||
prev_state = nz(trend_state[1], 0)
|
||
|
||
// 状态转换逻辑
|
||
int new_state = prev_state
|
||
|
||
if prev_state == 0 // 当前盘整
|
||
if uptrend_confirmed
|
||
new_state := 1
|
||
else if downtrend_confirmed
|
||
new_state := -1
|
||
|
||
else if prev_state == 1 // 当前上涨
|
||
if downtrend_confirmed
|
||
new_state := -1
|
||
else if consolidation_confirmed and not uptrend_raw
|
||
new_state := 0
|
||
|
||
else if prev_state == -1 // 当前下跌
|
||
if uptrend_confirmed
|
||
new_state := 1
|
||
else if consolidation_confirmed and not downtrend_raw
|
||
new_state := 0
|
||
|
||
// 仅在K线收盘时更新状态
|
||
trend_state := barstate.isconfirmed ? new_state : prev_state
|
||
|
||
// ========================= 可视化 =========================
|
||
// 绘制EMA线
|
||
plot(show_ema ? ema1 : na, "EMA1 快线", color=color.new(color.red, 30), linewidth=1)
|
||
plot(show_ema ? ema2 : na, "EMA2 中线", color=color.new(color.orange, 30), linewidth=1)
|
||
plot(show_ema ? ema3 : na, "EMA3 慢线", color=color.new(color.blue, 30), linewidth=2)
|
||
plot(show_ema and use_ema4 ? ema4 : na, "EMA4 超慢线", color=color.new(color.purple, 30), linewidth=2)
|
||
|
||
// 背景着色
|
||
bg_color = trend_state == 1 ? col_uptrend : trend_state == -1 ? col_downtrend : col_consolidation
|
||
bgcolor(show_background ? bg_color : na, title="趋势背景")
|
||
|
||
// 状态切换信号
|
||
entered_up = barstate.isconfirmed and trend_state == 1 and prev_state != 1
|
||
entered_down = barstate.isconfirmed and trend_state == -1 and prev_state != -1
|
||
entered_consolidation = barstate.isconfirmed and trend_state == 0 and prev_state != 0
|
||
exit_up = barstate.isconfirmed and prev_state == 1 and trend_state != 1
|
||
exit_down = barstate.isconfirmed and prev_state == -1 and trend_state != -1
|
||
|
||
// ========================= 类缠论笔的绘制 =========================
|
||
// 趋势线宽度
|
||
trend_line_width = input.int(2, "趋势笔宽度", minval=1, maxval=5, group="显示设置")
|
||
|
||
// 上涨笔:记录起点
|
||
var int up_start_bar = na
|
||
var float up_start_price = na
|
||
|
||
// 下跌笔:记录起点
|
||
var int down_start_bar = na
|
||
var float down_start_price = na
|
||
|
||
// 上涨趋势开始 - 记录起点
|
||
if entered_up
|
||
up_start_bar := bar_index
|
||
up_start_price := low
|
||
|
||
// 上涨趋势结束 - 画笔(终点 = 结束时的K线)
|
||
if exit_up and show_signals and not na(up_start_bar)
|
||
line.new(up_start_bar, up_start_price, bar_index, close, color=color.teal, width=trend_line_width, style=line.style_solid)
|
||
|
||
// 下跌趋势开始 - 记录起点
|
||
if entered_down
|
||
down_start_bar := bar_index
|
||
down_start_price := high
|
||
|
||
// 下跌趋势结束 - 画笔(终点 = 结束时的K线)
|
||
if exit_down and show_signals and not na(down_start_bar)
|
||
line.new(down_start_bar, down_start_price, bar_index, close, color=color.red, width=trend_line_width, style=line.style_solid)
|
||
|
||
// 当前进行中的笔(实时显示)
|
||
var line current_up_line = na
|
||
var line current_down_line = na
|
||
|
||
if show_signals
|
||
if not na(current_up_line)
|
||
line.delete(current_up_line)
|
||
if not na(current_down_line)
|
||
line.delete(current_down_line)
|
||
|
||
// 上涨中 - 画到当前K线
|
||
if trend_state == 1 and not na(up_start_bar)
|
||
current_up_line := line.new(up_start_bar, up_start_price, bar_index, close, color=color.new(color.teal, 40), width=trend_line_width, style=line.style_dotted)
|
||
|
||
// 下跌中 - 画到当前K线
|
||
if trend_state == -1 and not na(down_start_bar)
|
||
current_down_line := line.new(down_start_bar, down_start_price, bar_index, close, color=color.new(color.red, 40), width=trend_line_width, style=line.style_dotted)
|
||
|
||
// ========================= 信息面板 =========================
|
||
if show_info_panel and barstate.islast
|
||
var table info_table = table.new(position.top_right, 2, 10, bgcolor=color.new(color.black, 80), border_width=1)
|
||
|
||
// 标题
|
||
table.cell(info_table, 0, 0, "EMA+MACD趋势", text_color=color.white, bgcolor=color.new(color.gray, 60), text_size=size.small)
|
||
table.cell(info_table, 1, 0, "", bgcolor=color.new(color.gray, 60))
|
||
|
||
// 当前状态
|
||
state_text = trend_state == 1 ? "📈 上涨趋势" : trend_state == -1 ? "📉 下跌趋势" : "📊 盘整趋势"
|
||
state_color = trend_state == 1 ? color.teal : trend_state == -1 ? color.red : color.gray
|
||
table.cell(info_table, 0, 1, "当前状态", text_color=color.white, text_size=size.small)
|
||
table.cell(info_table, 1, 1, state_text, text_color=state_color, text_size=size.small)
|
||
|
||
// EMA排列
|
||
ema_text = bull_alignment ? "多头排列" : bear_alignment ? "空头排列" : "无序排列"
|
||
ema_color = bull_alignment ? color.teal : bear_alignment ? color.red : color.gray
|
||
table.cell(info_table, 0, 2, "EMA排列", text_color=color.white, text_size=size.small)
|
||
table.cell(info_table, 1, 2, ema_text, text_color=ema_color, text_size=size.small)
|
||
|
||
// EMA收束度
|
||
spread_text = str.tostring(math.round(ema_spread * 10000) / 100, "#.##") + "%"
|
||
spread_color = emas_converged ? color.orange : color.white
|
||
table.cell(info_table, 0, 3, "EMA间距", text_color=color.white, text_size=size.small)
|
||
table.cell(info_table, 1, 3, spread_text + (emas_converged ? " 收束" : ""), text_color=spread_color, text_size=size.small)
|
||
|
||
// EMA方向
|
||
dir_text = all_rising ? "全部上升" : all_falling ? "全部下降" : "方向分歧"
|
||
dir_color = all_rising ? color.teal : all_falling ? color.red : color.gray
|
||
table.cell(info_table, 0, 4, "EMA方向", text_color=color.white, text_size=size.small)
|
||
table.cell(info_table, 1, 4, dir_text, text_color=dir_color, text_size=size.small)
|
||
|
||
// MACD状态
|
||
macd_status = macd_bullish ? "看涨" : "看跌"
|
||
macd_pos = macd_above_zero ? " (零上)" : macd_below_zero ? " (零下)" : " (零轴)"
|
||
macd_color = macd_bullish and macd_above_zero ? color.teal : macd_bearish and macd_below_zero ? color.red : color.orange
|
||
table.cell(info_table, 0, 5, "MACD状态", text_color=color.white, text_size=size.small)
|
||
table.cell(info_table, 1, 5, macd_status + macd_pos, text_color=macd_color, text_size=size.small)
|
||
|
||
// MACD数值
|
||
table.cell(info_table, 0, 6, "MACD值", text_color=color.white, text_size=size.small)
|
||
table.cell(info_table, 1, 6, str.tostring(macdLine, "#.####"), text_color=macdLine > 0 ? color.teal : color.red, text_size=size.small)
|
||
|
||
// 柱状图状态
|
||
hist_text = hist_expanding_up ? "放大(多)" : hist_expanding_down ? "放大(空)" : hist_shrinking ? "收缩" : "平稳"
|
||
hist_color = hist_expanding_up ? color.teal : hist_expanding_down ? color.red : color.gray
|
||
table.cell(info_table, 0, 7, "柱状图", text_color=color.white, text_size=size.small)
|
||
table.cell(info_table, 1, 7, hist_text, text_color=hist_color, text_size=size.small)
|
||
|
||
// MACD综合评分
|
||
score_text = macd_score > 0 ? "+" + str.tostring(macd_score) : str.tostring(macd_score)
|
||
score_color = macd_score > 0 ? color.teal : macd_score < 0 ? color.red : color.gray
|
||
table.cell(info_table, 0, 8, "MACD评分", text_color=color.white, text_size=size.small)
|
||
table.cell(info_table, 1, 8, score_text + " / 2", text_color=score_color, text_size=size.small)
|
||
|
||
// 价格位置
|
||
price_pos = price_above_emas ? "均线上方" : price_below_emas ? "均线下方" : "均线之间"
|
||
price_color = price_above_emas ? color.teal : price_below_emas ? color.red : color.gray
|
||
table.cell(info_table, 0, 9, "价格位置", text_color=color.white, text_size=size.small)
|
||
table.cell(info_table, 1, 9, price_pos, text_color=price_color, text_size=size.small)
|
||
|
||
// ========================= 告警 =========================
|
||
alertcondition(entered_up, title="上涨趋势开始", message="{{ticker}} {{interval}} 进入上涨趋势 价格:{{close}}")
|
||
alertcondition(entered_down, title="下跌趋势开始", message="{{ticker}} {{interval}} 进入下跌趋势 价格:{{close}}")
|
||
alertcondition(entered_consolidation, title="盘整趋势开始", message="{{ticker}} {{interval}} 进入盘整趋势 价格:{{close}}")
|
||
|
||
// ========================= 指标说明 =========================
|
||
// 【EMA+MACD三态趋势判断指标】
|
||
//
|
||
// 核心逻辑:
|
||
// 1. 使用4条EMA(9/21/55/200)判断均线排列和方向
|
||
// 2. 结合MACD的位置、方向和柱状图状态
|
||
// 3. 综合判断市场处于三种状态之一
|
||
//
|
||
// 📈 上涨趋势判定:
|
||
// - EMA多头排列(快>中>慢>超慢)或均线同向上升+价格在上方
|
||
// - MACD看涨(MACD线>信号线 或 MACD在零轴上方)
|
||
//
|
||
// 📉 下跌趋势判定:
|
||
// - EMA空头排列(快<中<慢<超慢)或均线同向下降+价格在下方
|
||
// - MACD看跌(MACD线<信号线 或 MACD在零轴下方)
|
||
//
|
||
// 📊 盘整趋势判定:
|
||
// - EMA线收束(间距小于阈值)或无明确排列
|
||
// - MACD在零轴附近 或 柱状图收缩
|
||
// - 不满足上涨/下跌条件时自动判定为盘整
|
||
//
|
||
// 参数建议:
|
||
// - 短线交易:EMA 5/10/20/50, 确认周期1-2
|
||
// - 中线交易:EMA 9/21/55/200, 确认周期2-3(默认)
|
||
// - 长线交易:EMA 20/50/100/200, 确认周期3-5
|