Плавное изменения цвета по ADX ..КАК ето реализовать ?? - страница 6

 

Может быть потребуется переменная:

double c=oB*0x100*0x100+oG*0x100+oR 

return(c) ;

 
Красиво. В чем же всё-таки заключается "выхлоп"? В чем польза то есть?
 
_new-rena:
Красиво. В чем же всё-таки заключается "выхлоп"? В чем польза то есть?

А вы не могли бы попробовать воздерживаться от таких вопросов?
 
Integer:

А вы не могли бы попробовать воздерживаться от таких вопросов?
Что мы видим - вот в чем вопрос?
 
Результат был, но автор удалил тот пост.
 
FAQ:
Результат был, но автор удалил тот пост.
Жаль, так долго ждал.... Результат был интересен.
 
_new-rena:
В чем же всё-таки заключается "выхлоп"? В чем польза то есть?


По мотивам этого топика, на стыке математики, рисования и торговли изобрёл спектральный фильтр. Вот механизм его действия:

 

Красная кривая - это функция-линза, параметр p это фокус линзы, который меняется от 0.1 до 10 с каждым кадром. Синие точки по вертикальной оси это проекция, или лучше сказать преломление точек горизонтальной оси с шагом 0.1 через функцию-линзу. Видно, что они сосредотачиваются или к середине, или по краям диапазона, в зависимости от значения p, или нормально равномерно распределены при p=1. Естественно, можно использовать не только для цветового спектра, но и для любого числового диапазона. То есть, если нам например надо увеличить нашу скорость реакции на середине какого-то диапазона и уменьшить скорость реакции на его краях, или наоборот, то можно использовать этот спектральный фильтр, который работает как собирающая или рассеивающая линза. Но, в качестве его презентации, приведу всё-таки пример с цветовым диапазоном Hue (для наглядности) и индикатором ADX:

 

 

Линия нижнего индикатора плавно меняет цвет по радуге с каждым тиком, ходя по ней туда-сюда. Цвет горизонтальных уровней показывает значение разности PLUSDI и MINUSDI (диапазон от -100 до +100), спроектированное на ось Hue (диапазон от 0 до 1). Цвет участка цены на верхней половине графика зависит от цвета своего уровня, достигнутого индикатором в нижней половине графика в текущий момент времени. Попробую попроще сказать: пестрота на верхней половине графика зависит от цвета своей линии, достигнутого индикатором в нижней половине. Теперь смотрите: видите разрежение посередине и скопление радуги по краям? Это значение фокуса, равное 0.4. Сам индикатор с нижней половины графика также был весь пропущен через этот же спектральный фильтр и также растянут в середине и сжат по краям. То, что он сам плавно меняет цвет по радуге с каждым тиком, это только лично его прибамбасы и к делу не относится. Если фокус ещё больше уменьшить, будет ещё большее сгущение по краям и ещё большее разрежение посередине. Если поставить его больше единицы, например 2, то будет, наоборот, сгущение посередине и разрежение по краям.

Здесь нужно заметить две вещи. Во-первых, фокусы верхней и нижней половин графика через глобальные переменные терминала не связаны. Можно пробежаться по фокусам и выбрать наиболее подходящий с нижним индикатором, а потом выставить его в настройках в верхней половине. Во-вторых, как торговать по такой системе. При таком раскладе цвет можно использовать как третью координату на плоскости, но нужно хорошо помнить хотя бы мнемоническое правило взаимного расположения цветов радуги "каждый охотник желает знать, где сидит фазан". Если по цвету видно, что значение индикатора (разности PLUSDI и MINUSDI) скакануло из красной части спектра в фиолетовую, значит цена будет расти. Если же наоборот, из фиолетовой в красную, значит цена будет падать. Тогда не нужны будут ни нижняя половина графика, ни стрелки на верхней его половине.

 Также можно заметить, что, вообще говоря, спектральный фильтр в примиенении именно к цветовым значения для стратегий пересечения (из которых мы здесь рассматриваем пересечение PLUSDI и MINUSDI) не очень удобен - поди попробуй по цвету догадаться, было пересечение или нет. Научиться можно, но существуют же альтернативы, зачем. Гораздо удобнее попробовать спектральный фильтр для стратегий приближения к границам диапазона. Возьмём например для пробы RSI: если его значение выше 70, то сигнал к продаже, если ниже 30 - сигнал к покупке.

 

Значение фокуса 1.8. Слишком зелёная линия - сигнал к  покупке, а слишком синяя - сигнал к продаже.

 

Значение фокуса 0.8. Слишком фиолетовая линия -  сигнал к продаже, слишком жёлтая линия - сигнал к покупке. Код индикаторов следующий:

 

 Нижний:

//+------------------------------------------------------------------+
//|                                           RSI color separate.mq4 |
//|                                                            Gyfto |
//|                                       ООО "Цыганские технологии" |
//+------------------------------------------------------------------+
#property indicator_separate_window
extern int periodRSI=14;
extern bool image=true;//если выключено, горизонтальные линии рисоваться не будут
extern double focus=1.8;
//если кому будет всё слишком пёстро, можно приглушить цвета. Или наоборот - по вкусу.
extern double Staturation=1.0;//значение насыщенности
extern double Lightness=0.5;//значение светлоты
double ExtMapBuffer1[];
double ExtMapBuffer2[];
bool b=true;
bool up=true;
double Hue;

int init()
  {
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,ExtMapBuffer1);
   focus=MathAbs(focus); if (focus<0.1) focus=0.1; if (focus>10) focus=10;//защита от дурака (деление на ноль) и ограничения диапазона изменения фокуса
   return(0);
  }

int deinit()
  {
   ObjectsDeleteAll(WindowOnDropped(), OBJ_HLINE);
   return(0);
  }

int start()
  {
//блок рисования горизонтальных линий уровня. Не выношу в init(), потому что WindowOnDropped() определён только в start()
   if(image){
      if(b){
         for(int i=0; i<=100; i++){
            double x=i; x/=100;
            double hue=SpectralFilter(x, focus);
            color RGB=HSLtoRGB(hue, Staturation, Lightness);
            string name=DoubleToStr(hue,8);
            ObjectCreate(name,OBJ_HLINE,WindowOnDropped(),0,hue);
            ObjectSet(name, OBJPROP_COLOR, RGB);
            ObjectSet(name, OBJPROP_STYLE, STYLE_SOLID);
            ObjectSet(name, OBJPROP_WIDTH, 1);
         }
         b=false;
      }
   }else{
      ObjectsDeleteAll(WindowOnDropped(),OBJ_HLINE);
   }//Рисуем две сигнальные линии на 0.3 и 0.7
   hue=SpectralFilter(0.3,focus); ObjectCreate("alert 0.3", OBJ_HLINE, WindowOnDropped(), 0, hue);
   hue=SpectralFilter(0.7,focus); ObjectCreate("alert 0.7", OBJ_HLINE, WindowOnDropped(), 0, hue);
   ObjectSet("alert 0.3", OBJPROP_COLOR, Silver); ObjectSet("alert 0.7", OBJPROP_COLOR, Silver);
   ObjectSet("alert 0.3", OBJPROP_STYLE, STYLE_SOLID); ObjectSet("alert 0.7", OBJPROP_STYLE, STYLE_SOLID);
   ObjectSet("alert 0.3", OBJPROP_WIDTH, 2); ObjectSet("alert 0.7", OBJPROP_WIDTH, 2);
   //блок для ходьбы цвета индикатора туда-сюда по радуге. Отмечу: СНАЧАЛА установка цвета линии, ПОТОМ её рисование
   RGB = HSLtoRGB(Hue/256, 1.0, 0.5);
   SetIndexStyle(0, DRAW_LINE, EMPTY, EMPTY, RGB);
   if(up) Hue++; else Hue--;
   if((Hue==255.0)||(Hue==0.0)) up=!up;
   int counted_bars=IndicatorCounted();//переходим к обычному рисованию индикаторной линии
   if(counted_bars>0) counted_bars--;
   int limit=Bars-counted_bars;
   for(i=0; i<limit; i++){
      double variable=iRSI(NULL, 0, periodRSI, PRICE_CLOSE, i);
      variable/=100;//переводим диапазон от 0 до +100 в диапазон от 0 до +1
      variable=SpectralFilter(variable, focus);//Пропускаем значение через спектральный фильтр
      ExtMapBuffer1[i]=variable;
   }   
   return(0);
  }

double Hue_To_RGB(double P,double Q,double Tc){
        if(Tc<0) Tc+=1.0;
        if(Tc>1.0) Tc-=1.0;
        if(Tc<1.0/6.0) return(P+(Q-P)*6.0*Tc);
        if(Tc<1.0/2.0) return(Q);
        if(Tc<2.0/3.0) return(P+(Q-P)*((2.0/3.0)-Tc)*6.0);
        return(P);
}

color HSLtoRGB(double aH,double aS,double aL){
        if(aS==0){
                double oR=aL*255;
                double oG=aL*255;
                double oB=aL*255;
        }else{
                double Q;
                if(aL<0.5) Q=aL*(1.0+aS); else Q=(aL+aS)-(aS*aL);
                double P=2.0*aL-Q;
                oR=255.0*Hue_To_RGB(P,Q,aH+(1.0/3.0));
                oG=255.0*Hue_To_RGB(P,Q,aH);
                oB=255.0*Hue_To_RGB(P,Q,aH-(1.0/3.0));
        }
        return(0x100*0x100*DoubleToInt(oB)+0x100*DoubleToInt(oG)+DoubleToInt(oR));
}
int DoubleToInt(double var){return(var);}

double SpectralFilter(double var, double focus){
   if (var<0.5) var=MathPow((MathPow(0.5,focus)-MathPow(MathAbs(var-0.5),focus)),1/focus);
   else var=1-MathPow((MathPow(0.5,focus)-MathPow(MathAbs(var-0.5),focus)),1/focus);
   return(var);
}

 Верхний:

//+------------------------------------------------------------------+
//|                                                    RSI color.mq4 |
//|                                                            Gyfto |
//|                                       ООО "Цыганские технологии" |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Red
#property indicator_color2 Blue
extern int periodRSI=14;
extern double focus=1.8;
//если кому будет всё слишком пёстро, можно приглушить цвета. Или наоборот - по вкусу.
extern double Staturation=1.0;//значение насыщенности
extern double Lightness=0.5;//значение светлоты
int time;

int init()
  {
   focus=MathAbs(focus); if (focus<0.1) focus=0.1; if (focus>10) focus=10;//защита от дурака (деление на ноль) и ограничения диапазона изменения фокуса
   for(int i=Bars-1; i>0; i--) ColorDash(i);//в цикле по всей истории перерисовываем линию цены
   time=Minute();
   return(0);
  }

int deinit()
  {
   ObjectsDeleteAll(0, OBJ_TREND);//в деинициализации также в цикле удаляем все OBJ_TREND
   return(0);
  }

int start()
  {
   ObjectDelete(StringConcatenate("DashRSI ", TimeToStr(Time[0], TIME_DATE|TIME_MINUTES)));
   ColorDash(0);
   //далее: перестраховка, если черта уйдёт не в ту сторону:
   if (time!=Minute() && ObjectGet(StringConcatenate("DashRSI ", TimeToStr(Time[1], TIME_DATE|TIME_MINUTES)), OBJPROP_PRICE1)!=Close[1]){
      ObjectSet(StringConcatenate("DashRSI ", TimeToStr(Time[1], TIME_DATE|TIME_MINUTES)), OBJPROP_PRICE1, Close[1]);
      time=Minute();
   }
   return(0);
  }

void ColorDash(int index){//функция перекрашивания линии цены
        double variable = iRSI(NULL, 0, periodRSI, PRICE_CLOSE, index);
        variable/=100;//область допустимых значений RSI 0...100 переводим в О.Д.З. 0...1.
        double Hue=SpectralFilter(variable,focus);//Пропускаем значение через спектральный фильтр
        color RGB = HSLtoRGB(Hue, Staturation, Lightness);//конвертируем цветовую модель HSL в цветовую модель RGB
        string name=StringConcatenate("dashRSI ", TimeToStr(Time[index], TIME_DATE|TIME_MINUTES));//формируем имя линии
        if(index==0){ ObjectCreate(name, OBJ_TREND, 0, Time[0], Bid, Time[1], Close[1]);//создаём OBJ_TREND длинной в толщину одной свечи
        }else{ ObjectCreate(name, OBJ_TREND, 0, Time[index], Close[index], Time[index+1], Close[index+1]);}//аналогично. Используется в старте.
        ObjectSet(name, OBJPROP_COLOR, RGB);//и меняем цвет OBJ_TREND в зависимости от значения RSI
        ObjectSet(name, OBJPROP_STYLE, STYLE_SOLID);//а также выполняем следующие перестраховки: это сплошная линия (не пунктирная и прочее)
        ObjectSet(name, OBJPROP_WIDTH, 2);//также она имеет ширину 2 пикселя (как и обычная линия цены)
        ObjectSet(name, OBJPROP_RAY, false);//и нарисованная трендовая линия это не луч, а отрезок
}

double Hue_To_RGB(double P,double Q,double Tc){//используем функции из библиотеки Integer
        if(Tc<0) Tc+=1.0;
        if(Tc>1.0) Tc-=1.0;
        if(Tc<1.0/6.0) return(P+(Q-P)*6.0*Tc);
        if(Tc<1.0/2.0) return(Q);
        if(Tc<2.0/3.0) return(P+(Q-P)*((2.0/3.0)-Tc)*6.0);
        return(P);
}

color HSLtoRGB(double aH,double aS,double aL){
        if(aS==0){
                double oR=aL*255;
                double oG=aL*255;
                double oB=aL*255;
        }else{
                double Q;
                if(aL<0.5) Q=aL*(1.0+aS); else Q=(aL+aS)-(aS*aL);
                double P=2.0*aL-Q;
                oR=255.0*Hue_To_RGB(P,Q,aH+(1.0/3.0));
                oG=255.0*Hue_To_RGB(P,Q,aH);
                oB=255.0*Hue_To_RGB(P,Q,aH-(1.0/3.0));
        }
        return(0x100*0x100*DoubleToInt(oB)+0x100*DoubleToInt(oG)+DoubleToInt(oR));
}
int DoubleToInt(double var){return(var);}

double SpectralFilter(double var, double focus){
   if (var<0.5) var=MathPow((MathPow(0.5,focus)-MathPow(MathAbs(var-0.5),focus)),1/focus);
   else var=1-MathPow((MathPow(0.5,focus)-MathPow(MathAbs(var-0.5),focus)),1/focus);
   return(var);
}

 ADX и RSI все прикрепляю к сообщению. Для удобства выбора значений светлоты и насыщенности написал отдельно индикатором "выбор радуги.mq4", также его прикрепляю, всё в одном  архиве.

Подведём итоги. Из динамики изменения цветового диапазона спектральным фильтром видно, что он также выборочно может изменять числовой диапазон, что также может использоваться в технических индикаторах. Также можно повторить, что цвет может использоваться в качестве третьей координаты на плоскости, если мы работаем с каким-то числовым диапазоном, но не со всей числовой осью.

Вообще говоря, я сначала ошибся. Задавшись целью получить спектральный фильтр, я пошёл не той дорогой, дошёл до конца разработки, и только дойдя до конца, понял, что можно было сделать проще. Сравните вот эту мою же портянку

 

  - и первую картинку-гифку. А всё почему? Неграмотность, необразованность, вот она и вылазит.  Меня никто не учил про n-степенной эллипс, я этого не знал. Если же я осёл и велосипед изобрёл, то так и скажите.

Файлы:
Причина обращения: