//@version=6 indicator('ma200_p', shorttitle='ma200_p', overlay=true) // ————————————— 输入参数 ————————————— exponential = input.bool(true, title='使用指数移动平均线 (EMA)') default_dist = input.float(3.0, title='默认 MA200 距离阈值 (USD)', minval=0.1, step=0.1) btc_dist = input.float(150.0, title='BTCUSD MA200 距离阈值 (USD)', minval=0.1, step=0.1) xau_dist = input.float(3.0, title='XAUUSD MA200 距离阈值 (USD)', minval=0.1, step=0.1) eth_dist = input.float(8.0, title='ETHUSD MA200 距离阈值 (USD)', minval=0.1, step=0.1) gbp_dist = input.float(0.3, title='GBPJPY MA200 距离阈值 (USD)', minval=0.1, step=0.1) flatness_period = input.int(20, title='MA200 波动回看周期', minval=1) flatness_threshold = input.float(0.5, title='MA200 平坦度阈值 (USD)', minval=0.01, step=0.01) oscillation_bars = input.int(10, title='价格波动回看周期', minval=1) oscillation_threshold = input.float(5.0, title='价格波动范围阈值 (USD)', minval=0.1, step=0.1) // ————————————— 自定义MA(xx)参数 ————————————— ma_custom_period = input.int(30, title='自定义MA周期', minval=1, maxval=500) ma_custom_color = input.color(color.orange, title='自定义MA颜色') ma_custom_linewidth = input.int(2, title='自定义MA线段粗细', minval=1, maxval=10) // ————————————— 计算移动平均线 ————————————— src = close ma50 = exponential ? ta.ema(src, 50) : ta.sma(src, 50) ma100 = exponential ? ta.ema(src, 100) : ta.sma(src, 100) ma200 = exponential ? ta.ema(src, 200) : ta.sma(src, 200) ma_custom = exponential ? ta.ema(src, ma_custom_period) : ta.sma(src, ma_custom_period) // ————————————— 移动平均线颜色函数 ————————————— maColor(ma, ref) => ma > ref ? color.lime : color.red // ————————————— 绘制 MA50/MA100/MA200/自定义MA ————————————— plot(ma50, color=maColor(ma50, ma100), linewidth=2, title='MA50', display=display.all) plot(ma100, color=maColor(ma100, ma200), linewidth=2, title='MA100', display=display.all) plot(ma200, color=color.rgb(25, 58, 243), linewidth=4, title='MA200', display=display.all) plot(ma_custom, color=ma_custom_color, linewidth=ma_custom_linewidth, title='MA自定义', display=display.all) // ————————————— 价格标签(单行 label.new) ————————————— var label lbl50 = na var label lbl100 = na var label lbl200 = na var label lbl_custom = na if barstate.islast if na(lbl50) lbl50 := label.new(x=time, y=ma50, text='MA50: ' + str.tostring(ma50, '#.####'), xloc=xloc.bar_time, yloc=yloc.price, style=label.style_label_left, color=color.lime, textcolor=color.white) else label.set_xy(lbl50, x=time, y=ma50), label.set_text(lbl50, 'MA50: ' + str.tostring(ma50, '#.####')) if na(lbl100) lbl100 := label.new(x=time, y=ma100, text='MA100: ' + str.tostring(ma100, '#.####'), xloc=xloc.bar_time, yloc=yloc.price, style=label.style_label_left, color=color.white, textcolor=color.black) else label.set_xy(lbl100, x=time, y=ma100), label.set_text(lbl100, 'MA100: ' + str.tostring(ma100, '#.####')) if na(lbl200) lbl200 := label.new(x=time, y=ma200, text='MA200: ' + str.tostring(ma200, '#.####'), xloc=xloc.bar_time, yloc=yloc.price, style=label.style_label_left, color=color.white, textcolor=color.black) else label.set_xy(lbl200, x=time, y=ma200), label.set_text(lbl200, 'MA200: ' + str.tostring(ma200, '#.####')) if na(lbl_custom) lbl_custom := label.new(x=time, y=ma_custom, text='MA自定义: ' + str.tostring(ma_custom, '#.####'), xloc=xloc.bar_time, yloc=yloc.price, style=label.style_label_left, color=ma_custom_color, textcolor=color.white) else label.set_xy(lbl_custom, x=time, y=ma_custom), label.set_text(lbl_custom, 'MA自定义: ' + str.tostring(ma_custom, '#.####')) // ————————————— 阈值切换(异常交易对) ————————————— sym = ticker.standard(syminfo.tickerid) distance_threshold = sym == 'TICKMILL:BTCUSD' ? btc_dist : sym == 'TICKMILL:XAUUSD' ? xau_dist : sym == 'TICKMILL:ETHUSD' ? eth_dist : sym == 'TICKMILL:GBPJPY' ? gbp_dist : default_dist // ————————————— 警报计算 ————————————— distance_usd = math.abs(close - ma200) is_near_ma200 = distance_usd <= distance_threshold ma200_max = ta.highest(ma200, flatness_period) ma200_min = ta.lowest(ma200, flatness_period) ma200_flatness = ma200_max - ma200_min is_flat = ma200_flatness < flatness_threshold cross_above = ta.crossover(close, ma200) cross_below = ta.crossunder(close, ma200) price_max = ta.highest(close, oscillation_bars) price_min = ta.lowest(close, oscillation_bars) is_oscillating = (price_max - price_min) < oscillation_threshold and (cross_above or cross_below) is_above_ma200 = close > ma200 is_below_ma200 = close < ma200 // ————————————— 绘制供数据窗口使用 ————————————— plot(ma200, title='MA200', display=display.data_window) plot(ma_custom, title='MA自定义', display=display.data_window) plot(distance_usd, title='Distance USD', display=display.data_window) plot(ma200_flatness, title='Flatness USD', display=display.data_window) // ===== 统一警报系统 ===== // 统一警报系统 - 只需添加一次警报即可捕获所有信号 // 警报频率限制 - 每分钟只触发一次 var int last_alert_near_ma200 = 0 var int last_alert_ma200_flat = 0 var int last_alert_oscillating = 0 var int last_alert_cross_above = 0 var int last_alert_cross_below = 0 var int last_alert_above_ma200 = 0 var int last_alert_below_ma200 = 0 // 获取当前时间(分钟级别) current_minute = math.floor(timenow / 60000) // 检测所有警报条件并生成对应的JSON消息 alert_message = "" // 价格靠近 MA200 - 每分钟限制 if is_near_ma200 and current_minute > last_alert_near_ma200 alert_message := '{"指标名称":"MA200","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MA50":"' + str.tostring(ma50, '#.####') + '","MA100":"' + str.tostring(ma100, '#.####') + '","MA200":"' + str.tostring(ma200, '#.####') + '","距离(美元)":"' + str.tostring(distance_usd, '#.##') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格靠近MA200","位置":"靠近MA200"}' alert(alert_message, alert.freq_once_per_bar_close) last_alert_near_ma200 := current_minute // // MA200 波动较小 - 每分钟限制 // if is_flat and current_minute > last_alert_ma200_flat // alert_message := '{"指标名称":"MA200","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MA50":"' + str.tostring(ma50, '#.####') + '","MA100":"' + str.tostring(ma100, '#.####') + '","MA200":"' + str.tostring(ma200, '#.####') + '","距离(美元)":"' + str.tostring(distance_usd, '#.##') + '","波动范围":"' + str.tostring(ma200_flatness, '#.##') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"MA200波动较小","位置":"MA200波动很小"}' // alert(alert_message, alert.freq_once_per_bar_close) // last_alert_ma200_flat := current_minute // // 价格在 MA200 附近上下波动 - 每分钟限制 // if is_oscillating and current_minute > last_alert_oscillating // alert_message := '{"指标名称":"MA200","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MA50":"' + str.tostring(ma50, '#.####') + '","MA100":"' + str.tostring(ma100, '#.####') + '","MA200":"' + str.tostring(ma200, '#.####') + '","距离(美元)":"' + str.tostring(distance_usd, '#.##') + '","波动范围":"' + str.tostring(ma200_flatness, '#.##') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格在MA200上下波动","位置":"MA200附近波动"}' // alert(alert_message, alert.freq_once_per_bar_close) // last_alert_oscillating := current_minute // 价格穿越 MA200 信号 - 每分钟限制 // if cross_above and current_minute > last_alert_cross_above // alert_message := '{"指标名称":"MA200","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MA50":"' + str.tostring(ma50, '#.####') + '","MA100":"' + str.tostring(ma100, '#.####') + '","MA200":"' + str.tostring(ma200, '#.####') + '","距离(美元)":"' + str.tostring(distance_usd, '#.##') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格上穿MA200","信号":"buy","位置":"突破MA200"}' // alert(alert_message, alert.freq_once_per_bar_close) // last_alert_cross_above := current_minute // if cross_below and current_minute > last_alert_cross_below // alert_message := '{"指标名称":"MA200","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MA50":"' + str.tostring(ma50, '#.####') + '","MA100":"' + str.tostring(ma100, '#.####') + '","MA200":"' + str.tostring(ma200, '#.####') + '","距离(美元)":"' + str.tostring(distance_usd, '#.##') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格下穿MA200","信号":"sell","位置":"跌破MA200"}' // alert(alert_message, alert.freq_once_per_bar_close) // last_alert_cross_below := current_minute // 价格位置状态警报 - 每分钟限制 if is_above_ma200 and current_minute > last_alert_above_ma200 alert_message := '{"指标名称":"MA200","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MA50":"' + str.tostring(ma50, '#.####') + '","MA100":"' + str.tostring(ma100, '#.####') + '","MA200":"' + str.tostring(ma200, '#.####') + '","距离(美元)":"' + str.tostring(distance_usd, '#.##') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格在MA200以上","位置":"MA200以上"}' alert(alert_message, alert.freq_once_per_bar) last_alert_above_ma200 := current_minute if is_below_ma200 and current_minute > last_alert_below_ma200 alert_message := '{"指标名称":"MA200","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MA50":"' + str.tostring(ma50, '#.####') + '","MA100":"' + str.tostring(ma100, '#.####') + '","MA200":"' + str.tostring(ma200, '#.####') + '","距离(美元)":"' + str.tostring(distance_usd, '#.##') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格在MA200以下","位置":"MA200以下"}' alert(alert_message, alert.freq_once_per_bar) last_alert_below_ma200 := current_minute // ===== 传统警报条件(保留兼容性)===== // 注意:使用统一警报系统时,建议只使用上面的alert()函数 // 以下alertcondition保留用于需要单独设置警报的情况 // 创建用于警报的plot变量 plot(ma50, title = 'MA50值', display = display.none) plot(ma100, title = 'MA100值', display = display.none) plot(ma200, title = 'MA200值', display = display.none) plot(ma_custom, title = 'MA自定义值', display = display.none) plot(distance_usd, title = '距离美元', display = display.none) plot(ma200_flatness, title = 'MA200波动范围', display = display.none) // 价格靠近MA200警报 alertcondition(is_near_ma200, title = '价格靠近MA200', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("距离美元")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格靠近MA200","位置":"靠近MA200","信号":"near_ma200"}') // MA200波动较小警报 // alertcondition(is_flat, title = 'MA200波动较小', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("距离美元")}}","波动范围":"{{plot("MA200波动范围")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"MA200波动较小","位置":"MA200波动很小","信号":"ma200_flat"}') // // 价格在MA200上下波动警报 // alertcondition(is_oscillating, title = '价格在MA200上下波动', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("距离美元")}}","波动范围":"{{plot("MA200波动范围")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格在MA200上下波动","位置":"MA200附近波动","信号":"oscillating_ma200"}') // // 价格穿越MA200警报 // alertcondition(cross_above, title = '价格上穿MA200', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("距离美元")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿MA200","信号":"buy","位置":"突破MA200"}') // alertcondition(cross_below, title = '价格下穿MA200', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("距离美元")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿MA200","信号":"sell","位置":"跌破MA200"}') // 价格位置状态警报 alertcondition(is_above_ma200, title = '价格在MA200以上', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("距离美元")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格在MA200以上","位置":"MA200以上","信号":"above_ma200"}') alertcondition(is_below_ma200, title = '价格在MA200以下', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("距离美元")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格在MA200以下","位置":"MA200以下","信号":"below_ma200"}') // MA50和MA100穿越警报 // alertcondition(ta.crossover(ma50, ma100), title = 'MA50上穿MA100', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("距离美元")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"MA50上穿MA100","信号":"ma50_cross_above_ma100","位置":"MA50突破MA100"}') // alertcondition(ta.crossunder(ma50, ma100), title = 'MA50下穿MA100', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("距离美元")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"MA50下穿MA100","信号":"ma50_cross_below_ma100","位置":"MA50跌破MA100"}') // alertcondition(ta.crossover(ma100, ma200), title = 'MA100上穿MA200', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("距离美元")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"MA100上穿MA200","信号":"ma100_cross_above_ma200","位置":"MA100突破MA200"}') // alertcondition(ta.crossunder(ma100, ma200), title = 'MA100下穿MA200', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("距离美元")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"MA100下穿MA200","信号":"ma100_cross_below_ma200","位置":"MA100跌破MA200"}') // 综合移动平均线排列警报 alertcondition(ma50 > ma100 and ma100 > ma200, title = '多头排列', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("距离美元")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"多头排列","信号":"bullish_alignment","位置":"MA50>MA100>MA200"}') alertcondition(ma50 < ma100 and ma100 < ma200, title = '空头排列', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("距离美元")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"空头排列","信号":"bearish_alignment","位置":"MA50