admin 发表于 2026-2-22 09:45:59

rsi上涨继续,下跌继续源码

//+------------------------------------------------------------------+
//|                                             RSIOMA_Final.mq4   |
//|                                  Copyright © 2025, EarnForex.com |
//|      Chinese Label & Cooldown Modification by AI Assistant   |
//|      Based on indicator by Kalenzo bartlomiej.gorski@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2025, EarnForex.com"
#property link      "https://www.earnforex.com"
#property version   "2.01_Final_CN"
#property strict

#property description "RSIOMA显示一个基于MA相对强弱构建的RSI。"
#property description "核心信号: '续涨' 和 '续跌' 已在K线上标注。"

#property indicator_separate_window
#property indicator_buffers 8
#property indicator_color1 clrBlue
#property indicator_type1DRAW_LINE
#property indicator_width1 3
#property indicator_label1 "RSIOMA"
#property indicator_color2 clrRed
#property indicator_type2DRAW_HISTOGRAM
#property indicator_label2 "下跌趋势"
#property indicator_color3 clrGreen
#property indicator_type3DRAW_HISTOGRAM
#property indicator_label3 "上涨趋势"
#property indicator_color4 clrMagenta
#property indicator_type4DRAW_HISTOGRAM
#property indicator_label4 "顶部反转预警"
#property indicator_color5 clrDodgerBlue
#property indicator_type5DRAW_HISTOGRAM
#property indicator_label5 "底部反转预警"
#property indicator_color6 clrBlueViolet
#property indicator_type6DRAW_LINE
#property indicator_label6 "MA of RSIOMA"

#property indicator_minimum -10
#property indicator_maximum 100

// --- 中文标注输入参数 ---
input stringGroupName               = "--- 中文K线标注设置 ---";
input bool    EnableChineseLabels   = true;         // 启用中文K线标注
// vvvvvvvvvv这里是您要求的修改vvvvvvvvvv
input stringUpContinueText          = "续涨";       // 上涨继续文字
input color   UpContinueColor         = clrLimeGreen;   // 上涨文字颜色
input stringDownContinueText      = "续跌";       // 下跌继续文字
// ^^^^^^^^^^这里是您要求的修改^^^^^^^^^^
input color   DownContinueColor       = clrRed;         // 下跌文字颜色
input int   LabelDistance         = 20;         // 标签与K线的距离(点)
input int   SignalCooldown          = 10;         // 信号冷却K线数 (N根内只显示一次)
// --- 原始输入参数 ---
input stringOriginalGroupName       = "--- 原始指标参数 ---";
input int   RSIOMA                  = 14;         // RSIOMA 周期
input ENUM_MA_METHOD RSIOMA_MODE      = MODE_EMA;   // RSIOMA 模式
input ENUM_APPLIED_PRICE RSIOMA_PRICE = PRICE_CLOSE;// RSIOMA 应用价格
input int   Ma_RSIOMA               = 21;         // MA of RSIOMA 周期
input ENUM_MA_METHOD Ma_RSIOMA_MODE   = MODE_EMA;   // MA of RSIOMA 模式
input int   BuyTrigger            = 20;
input int   SellTrigger             = 80;
input int   MainTrendLong         = 50;
input int   MainTrendShort          = 50;
input bool    MainAlerts            = false;
input bool    AuxiliaryAlerts         = false;
input bool    EnableNativeAlerts      = false;
input bool    EnableEmailAlerts       = false;
input bool    EnablePushAlerts      = false;
input bool    EnableSoundAlerts       = false;
input stringSoundFile               = "alert.wav";
input ENUM_TIMEFRAMES TimeFrame      = PERIOD_CURRENT; // 时间周期

// Indicator buffers:
double RSIBuffer[];
double PosBuffer[];
double NegBuffer[];
double bdn[], bup[]; // bdn - Red(下跌), bup - Green(上涨)
double sdn[], sup[]; // sdn - Magenta(顶部预警), sup - DodgerBlue(底部预警)
double marsioma[];

// Global variables:
string   short_name;
string   obj_prefix; // 对象唯一前缀,用于清理
datetime LastAlertTime = D'01.01.1970';

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
{
    SetIndexBuffer(0, RSIBuffer);
    SetIndexBuffer(1, bdn);
    SetIndexBuffer(2, bup);
    SetIndexBuffer(3, sdn);
    SetIndexBuffer(4, sup);
    SetIndexBuffer(5, marsioma);
    SetIndexBuffer(6, PosBuffer);
    SetIndexBuffer(7, NegBuffer);

    SetIndexDrawBegin(0, RSIOMA);
    SetIndexDrawBegin(1, RSIOMA);
    SetIndexDrawBegin(2, RSIOMA);
    SetIndexDrawBegin(3, RSIOMA);
    SetIndexDrawBegin(4, RSIOMA);
    SetIndexDrawBegin(5, RSIOMA);

    short_name = StringConcatenate("RSIOMA(", RSIOMA, ")");
    IndicatorShortName(short_name);
    IndicatorSetInteger(INDICATOR_DIGITS, 2);

    // 创建唯一的对象前缀,防止不同图表/周期的对象冲突
    obj_prefix = short_name + "_" + (string)ChartID() + "_";
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                     |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    // 清理本指标实例创建的所有图表对象
    ObjectsDeleteAll(0, obj_prefix);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
    if(Bars <= RSIOMA) return(0);

    int limit;
    if(prev_calculated == 0 || rates_total < prev_calculated)
    {
      limit = rates_total - RSIOMA - 2;
    }
    else
    {
      limit = rates_total - prev_calculated;
    }

    for(int i = limit; i >= 0; i--)
    {
      double sumn = 0.0, sump = 0.0;
      double rel, negative, positive;

      double ccma = iMA(Symbol(), TimeFrame, RSIOMA, 0, RSIOMA_MODE, RSIOMA_PRICE, i);
      double ppma = iMA(Symbol(), TimeFrame, RSIOMA, 0, RSIOMA_MODE, RSIOMA_PRICE, i + 1);
      rel = ccma - ppma;

      if(rel > 0) sump = rel;
      else sumn = -rel;

      positive = (PosBuffer * (RSIOMA - 1) + sump) / RSIOMA;
      negative = (NegBuffer * (RSIOMA - 1) + sumn) / RSIOMA;

      PosBuffer = positive;
      NegBuffer = negative;

      bup = 0; bdn = 0; sdn = 0; sup = 0;

      if(negative != 0.0)
      {
            RSIBuffer = 100.0 - 100.0 / (1.0 + positive / negative);

            if(RSIBuffer > MainTrendLong) bup = -10;
            if(RSIBuffer < MainTrendShort) bdn = -10;
            if(RSIBuffer < BuyTrigger && RSIBuffer > RSIBuffer) sup = -10;
            if(RSIBuffer > SellTrigger && RSIBuffer < RSIBuffer) sdn = -10;
      }
      else
      {
            RSIBuffer = 0.0;
      }
    }

    for(int i = limit; i >= 0; i--)
    {
      marsioma = iMAOnArray(RSIBuffer, 0, Ma_RSIOMA, 0, Ma_RSIOMA_MODE, i);
    }

    // --- 中文标注和冷却逻辑 ---
    if(EnableChineseLabels)
    {
      static int upCooldown = 0;
      static int downCooldown = 0;

      int check_limit = rates_total - prev_calculated;
      if (prev_calculated == 0) check_limit = rates_total - 2;

      for(int i = check_limit; i >= 1; i--)
      {
         // 每一根K线都减少冷却计数器
         if(upCooldown > 0) upCooldown--;
         if(downCooldown > 0) downCooldown--;

         // 信号1: 上涨继续 (前一根洋红 -> 当前绿色) 并且冷却结束
         if(sdn != 0 && bup != 0 && upCooldown == 0)
         {
            string obj_name = obj_prefix + "UpCont_" + (string)Time;
            DrawLabel(obj_name, i, High + LabelDistance * _Point, UpContinueText, UpContinueColor, ANCHOR_LEFT);
            // 重置冷却计数器
            upCooldown = SignalCooldown;
         }

         // 信号2: 下跌继续 (前一根浅蓝 -> 当前红色) 并且冷却结束
         if(sup != 0 && bdn != 0 && downCooldown == 0)
         {
            string obj_name = obj_prefix + "DownCont_" + (string)Time;
            DrawLabel(obj_name, i, Low - LabelDistance * _Point, DownContinueText, DownContinueColor, ANCHOR_RIGHT);
            // 重置冷却计数器
            downCooldown = SignalCooldown;
         }
      }
    }

    // --- 原始警报逻辑 (保持不变) ---
    if(Time > LastAlertTime)
    {
      int candle = 1; // 检查已收盘的K线
      string Text;
      if (MainAlerts)
      {
            if ((RSIBuffer < SellTrigger) && (RSIBuffer >= SellTrigger))
            {
                Text = "RSIOMA: " + Symbol() + " - " + StringSubstr(EnumToString((ENUM_TIMEFRAMES)Period()), 7) + " - Crossed " + IntegerToString(SellTrigger) + " from above.";
                IssueAlerts(Text);
            }
            if ((RSIBuffer > BuyTrigger) && (RSIBuffer <= BuyTrigger))
            {
                Text = "RSIOMA: " + Symbol() + " - " + StringSubstr(EnumToString((ENUM_TIMEFRAMES)Period()), 7) + " - Crossed " + IntegerToString(BuyTrigger) + " from below.";
                IssueAlerts(Text);
            }
      }
      if (AuxiliaryAlerts)
      {
            if ((sdn != 0) && (sdn == 0))
            {
                Text = "RSIOMA: " + Symbol() + " - " + StringSubstr(EnumToString((ENUM_TIMEFRAMES)Period()), 7) + " - Bearish reversal imminent.";
                IssueAlerts(Text);
            }
            if ((sup != 0) && (sup == 0))
            {
                Text = "RSIOMA: " + Symbol() + " - " + StringSubstr(EnumToString((ENUM_TIMEFRAMES)Period()), 7) + " - Bullish reversal imminent.";
                IssueAlerts(Text);
            }
      }
    }

    return(rates_total);
}

//+------------------------------------------------------------------+
//| Helper functions                                                 |
//+------------------------------------------------------------------+
void IssueAlerts(string text)
{
    if (EnableNativeAlerts) Alert(text);
    if (EnableEmailAlerts) SendMail("RSIOMA Alert", text);
    if (EnablePushAlerts) SendNotification(text);
    if (EnableSoundAlerts) PlaySound(SoundFile);
    LastAlertTime = Time;
}

void DrawLabel(string obj_name, int bar, double price, string text, color clr, ENUM_ANCHOR_POINT anchor)
{
    if(ObjectFind(0, obj_name) < 0)
    {
      ObjectCreate(0, obj_name, OBJ_TEXT, 0, Time, price);
      ObjectSetString(0, obj_name, OBJPROP_TEXT, text);
      ObjectSetInteger(0, obj_name, OBJPROP_COLOR, clr);
      ObjectSetInteger(0, obj_name, OBJPROP_FONTSIZE, 10);
      ObjectSetString(0, obj_name, OBJPROP_FONT, "Arial");
      ObjectSetInteger(0, obj_name, OBJPROP_ANCHOR, anchor);
      ObjectSetInteger(0, obj_name, OBJPROP_SELECTABLE, false);
    }
}
//+------------------------------------------------------------------+


页: [1]
查看完整版本: rsi上涨继续,下跌继续源码

人生者,生存也。
生存所需,财(钱)官(权)也。
财自食伤(子孙福德爻)生,
印星生身荫护,官财印全,适合人间生存也。
若命缺财,缺官,则失去生存权。
一旦脱离父母养育,将天天面临,
从绝望中醒来,又从绝望中睡去。来去如烟!