#_i_3D_Stochastic(2)

Download script
Author: Copyright � 2009, TigraVK
#_i_3D_Stochastic(2)

This script is designed to provide a sophisticated, multi-dimensional visual representation of the Stochastic Oscillator, a common technical analysis tool used to identify overbought or oversold conditions in financial markets.

Instead of displaying a single moving line, this tool generates a "3D" heatmap or "fan" effect on your chart. It achieves this by calculating and stacking multiple Stochastic variations simultaneously across different time horizons.

How the Logic Works

1. The Multi-Layered "Fan" Construction The core logic functions by calculating several different Stochastic indicators at once. It starts with a base setting (defined by the user) and then automatically increases the periods for these calculations in sequential steps.

  • Vertical Axis (Y): Each row in the visual display represents a different Stochastic variation with an increasing period. This allows you to see how short-term momentum compares to long-term trends at a single glance.
  • Horizontal Axis (X): This follows the standard timeline of your trading chart, showing how these values evolve over time.
  • Depth/Color (Z): The "third dimension" is represented by color. The script changes the colors of the visual blocks based on specific price conditions or movement behaviors.

2. Dynamic Visual Modes The user can choose between three distinct logic modes to change how the data is visualized:

  • Direction Mode: This focuses on momentum. It compares the current value against the previous one. If the value is rising, it uses one color (e.g., Green); if it is falling, it uses another (e.g., Red). It creates a visual "flow" of the market's movement.
  • Absolute Value Mode: This focuses on intensity. The script assigns specific colors based on where the Stochastic value sits within the 0–100 range. For example, it may use different shades for "Extreme Oversold" zones, "Neutral" zones, or "Extreme Overbought" zones, helping you spot high-risk areas instantly.
  • Acceleration Mode: This is the most complex logic. It calculates the speed of change (velocity) between data points. It identifies the fastest movement in the current set and uses a color gradient to show not just if the price is moving, but how fast it is accelerating. Green gradients represent upward acceleration, while red gradients represent downward acceleration.

3. User Interface & Layout The script includes logic to handle the visual organization of this data:

  • Shielding: It creates "rectangles" or "shields" to build the chart, ensuring the layout remains clean and organized.
  • Auto-Scaling: The script automatically detects the high and low points of your current price window to ensure the 3D fan fits perfectly on your screen.
  • Header System: It automatically generates a text header (like "Direction" or "Acceleration") based on your chosen mode so you always know what data you are viewing.
  • Shift Logic: There is a built-in "Draw Shift" feature, which allows you to place two different versions of this 3D fan side-by-side in the same window without them overlapping.

Summary for the User

In simple terms, this script takes a standard technical indicator and expands it into a comprehensive visual map. It allows you to see the "pulse" of the market by showing multiple timeframes at once, using color to tell you whether the market is speeding up, slowing down, or entering dangerous price territories.

Indicators Used
Stochastic oscillator
12 Views
0 Downloads
0 Favorites
#_i_3D_Stochastic(2)
//+---------------------------------------------------------------------+
//|                                        #_i_3D_Stochastic.mq4        |
//|                                    Copyright © 2009, TigraVK        |
//|                                                                     |
//|Èíäèêàòîð îòîáðàæàåò ïîâåäåíèå êëàññè÷åñêîãî ñòîõàñòèêà â            |
//|òðåõìåðíîé äèàãðàììå â îñíîâíîì îêíå ãðàôèêà òîðãîâîãî               |
//|èíñòðóìåíòà. Ïîñòðî÷íî îòáðàæàþòñÿ ñòîõàñòèêè ñ ïîøàãîâî             |
//|óâåëè÷èâàþùèìèñÿ ïåðèîäàìè %K, %D è ïðî÷. ïî æåëàíèþ ïîëüçîâàòåëÿ    |
//| ðåçóëüòàòå ïîëó÷àåòñÿ òðåõìåðíàÿ êàðòèíêà ñòîõààñòè÷åñêîãî âååðà   |
//|Â äàííîé âåðñèè èíäèêàòîðà âîçìîæíû ðåæèìû îòîáðàæåíèÿ               |
//|íàïðàâëåíèÿ äâèæåíèÿ ñòîõàñòè÷åñêîé êðèâîé;                          |
//|åå àáñîëþòíîãî çíà÷åíèÿ;                                             |
//|åå ñêîðîñòè ðîñòà èëè ñíèæåíèÿ.                                      |
//|                                                                     |
//|Êîîðäèíàòà Õ íà äèàãðàììå - âðåìÿ â ôîðìàòå ãðàôèêà òîðãîâîãî        |
//|èíñòðóìåíòà                                                          |
//|Êîîðäèíàòà Y íà äèàãðàììå - ñâåðõó âíèç ïîñëåäîâàòåëüíîå îòîáðàæåíèå |
//|ñòîõàñòèêîâ ñ ðàçëè÷íûìè ïàðàìåòðàìè                                 |
//|Êîîðäèíàòà Z îòðàæåíà ðàçëè÷íûìè öâåòàìè â çàâèñèìîñòè îò ñèòóàöèè   |
//|è ïîëîæåíèÿ ñòîõàñòèêà â äàííîé âðåìåííÎé òî÷êå                      |
//+---------------------------------------------------------------------+
#property copyright "Copyright © 2009, TigraVK"
#property link      "tigravk@yandex.ru"

#property indicator_chart_window
#include <stdlib.mqh>

#define ELEMENTS 40           //êîëè÷åñòâî îòîáðàæàåìûõ ñòðîê â äèàãðàììå
extern int IndMode = 1;       //îäèí èç òðåõ ðåæèìîâ îòðèñîâêè äèàãðàìì: 0-Íàïðàâëåíèå;1-àáñîëþòíîå çíà÷åíèå;2-áàðîâàÿ ñêîðîñòü èçìåíåíèÿ 
extern int Columns = 120;    //Êîëè÷åñòâî îòîáðàæàåìûõ ñòîëáöîâ äèàãðàììû
extern int Width = 1;         //Øèðèíà ñòîëáöà, â áàðàõ
extern int DrawShift = 0;     //Ñìåùåíèå íóëåâîãî ñòîëáöà (â áàðàõ) îòíîñèòåëüíî ïðàâîé ãðàíèöû îêíà ãðàôèêà
                              //ïðèìåíÿåòñÿ â ñëó÷àå âûâîäà äâóõ êîïèé èíäèêàòîðà ñ ðàçíûìè ïàðàìåòðàìè â îäíî îêíî
                              //äëÿ èñêëþ÷åíèÿ âèçóàëüíûõ ïåðåñå÷åíèé äèàãðàìì
                              //Íàïðèìåð, äëÿ âûâîäà âòîðîé äèàãðàììû êîððåêòíî áóäåò óñòàíîâèòü DrawShift=Columns+4

//-- Íà÷àëüíûå ïàðàìåòðû ñòîõàñòèêà è èõ ïðèðàùåíèÿ -----------
extern int Kp = 3;
extern int Kp_step = 3;
extern int Dp = 2;
extern int Dp_step = 1;
extern int Slowing = 2;
extern int Slowing_step = 1;
extern int Method = MODE_SMA;
extern int Price_field = 0;    //0 - Low/High èëè 1 - Close/Close
extern int Mode = MODE_SIGNAL; //MODE_MAIN 0 Îñíîâíàÿ ëèíèÿ; MODE_SIGNAL 1 Ñèãíàëüíàÿ ëèíèÿ 
//-------------------------------

#define COLUMNS_DOP 3   //êîë-âî äîïîëíèòåëüíûõ êîëîíîê â ìàññèâå STOCH[][] (òèïà, âû÷èñëèòåëüíûé çàïàñ)
#define HEADER 2        //ìåñòî ïîä çàãîëîâîê (èçìåðÿåòñÿ âûñîòîé ýëåìåòà äèàãðàììû)
#define GAP 0           //ïðîáåë (â áàðàõ) ìåæäó ýëåìåíòàìè äèàãðàììû â ãîðèçîíòàëè
#define GAP_PERCENT 20  //ïðîáåë (â ïðîöåíòàõ îò âûñîòû ýëåìåíòà äèàãðàììû) ìåæäó ýëåìåíòàìè äèàãðàììû â âåðòèêàëè

double STOCH[][ELEMENTS];//ìàññèâ êàðòà äàííûõ ñ äàííûìè âñåõ ñòîõàñòèêîâ
double Top;
double Bottom;
int    FreeBars;
string el_name;
string indname = "#_i_3D_Stochastic";
datetime tm;
int shift;

//+------------------------------------------------------------------+
int init()
{
   tm=Time[0];
   shift=DrawShift*(Width+GAP);
   Top    =WindowPriceMax(0);
   Bottom =WindowPriceMin(0);
   FreeBars=WindowBarsPerChart()-WindowFirstVisibleBar()-shift;
   if(IndMode==0)
   {
      el_name = "RCTDIR";
      CreateHeader("Direction", Top, Width, Columns, FreeBars, Yellow);
   }
   else if(IndMode==1)
   {
      el_name = "RCTABS";
      CreateHeader("Absolute", Top, Width, Columns, FreeBars, Yellow);
   }
   else if(IndMode==2)
   {
      el_name = "RCTACC";
      CreateHeader("Acceleration", Top, Width, Columns, FreeBars, Yellow);
   }
   else
   {
      el_name = "RCT";
      CreateHeader("NONE", Top, Width, Columns, FreeBars, Yellow);
   }
   
   IndicatorShortName(indname);
   
   ArrayResize(STOCH,Columns+COLUMNS_DOP);
   ArrayInitialize(STOCH, 0.0);
   
   //ñîçäàåì êâàäðàòèêè
   for(int i=0; i<Columns; i++)
      CreateShield(el_name+i+"_", Top, Bottom, Width, FreeBars-(Width+GAP)*i, Gray);

   return(0);
}
//+------------------------------------------------------------------+
int deinit()
{
   DeleteIndicatorObject(el_name);
   return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   int i;
   int limit;
   double top    =WindowPriceMax(0);
   double bottom =WindowPriceMin(0);
   int free_bars =WindowBarsPerChart()-WindowFirstVisibleBar()-shift;
   
   int counted_bars=IndicatorCounted();
   limit=Bars-counted_bars;
   if(limit>Columns+COLUMNS_DOP) limit=Columns+COLUMNS_DOP;


   //Ïðîöåäóðà ïåðåðèñîâêè äèàãðàììû ïðè ñìåíå òåêóùåãî áàðà èëè ðàçìåðîâ ýêðàííîé îáëàñòè ãðàôèêà
   if(Top!=top || Bottom!=bottom || FreeBars!=free_bars || tm!=Time[0])
   {
      Top=top; Bottom=bottom; FreeBars=free_bars; tm=Time[0];
      for(i=0; i<Columns; i++)
      {
         if(MoveShield(el_name+i+"_", Top, Bottom, Width, FreeBars-(Width+GAP)*i)<0)
         {
            DeleteIndicatorObject(el_name+i+"_");
            CreateShield(el_name+i+"_", Top, Bottom, Width, FreeBars-(Width+GAP)*i, Gray);
         }
      }
      MoveHeader(Top, Width, Columns, FreeBars, Yellow);
   }



   if(limit>=Columns+COLUMNS_DOP) //ïîëíàÿ îòðèñîâêà ïðè çàïóñêå èíäèêàòîðà
   {
      StochDATA_fill(STOCH, limit, 0, 0);
      if(IndMode==0)      StochasticWeerDirection(STOCH, Columns);
      else if(IndMode==1) StochasticWeerAbsolute(STOCH, Columns);
      else if(IndMode==2) StochasticWeerAcceleration(STOCH, Columns);
   }
   else if(limit>1 && limit<Columns+COLUMNS_DOP) //ïåðåðèñîâêà ïðè ñìåíå áàðà
   {
      StochDATA_leftShift(STOCH, Columns+COLUMNS_DOP, limit-1);
      StochDATA_fill(STOCH, limit-1, 0, 0);
      if(IndMode==0)      StochasticWeerDirection(STOCH, Columns);
      else if(IndMode==1) StochasticWeerAbsolute(STOCH, Columns);
      else if(IndMode==2) StochasticWeerAcceleration(STOCH, Columns);
   }
   else //ïåðåðèñîâêà òîëüêî òåêóùåãî áàðà
   {
      StochDATA_fill(STOCH, limit, 0, 0);
      if(IndMode==0)      StochasticWeerDirection(STOCH, limit);
      else if(IndMode==1) StochasticWeerAbsolute(STOCH, limit);
      else if(IndMode==2) StochasticWeerAcceleration(STOCH, Columns);
   }
   err("Start:  ");
   return(0);
}


//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
void StochDATA_fill(double& DATA[][], int recount_columns, int start_columns, int historyBarShift)
{
   int i,j;
   int kp=Kp;
   int dp=Dp;
   int sl=Slowing;
   
   for(j=start_columns; j<recount_columns+start_columns; j++)
   {
      kp=Kp; dp=Dp; sl=Slowing;
      for(i=0; i<ELEMENTS; i++)
      {
         DATA[j][i] = iStochastic(NULL, 0, kp, dp, sl, Method, Price_field, Mode, j+historyBarShift);
         kp=kp+Kp_step;
         dp=dp+Dp_step;
         sl=sl+Slowing_step;
      }
   }
   return;
}

//+------------------------------------------------------------------+
void StochDATA_leftShift(double& DATA[][], int columns, int shift_columns_count)
{
   int i,j,k;
   for(k=1; k<=shift_columns_count; k++)
   {   
      for(j=columns-1; j>0; j--)
      {
         for(i=0; i<ELEMENTS; i++)
            DATA[j][i] = DATA[j-1][i];
      }
      for(i=0; i<ELEMENTS; i++)
         DATA[0][i] = 0.0;
   }
}

//+------------------------------------------------------------------+
void StochasticWeerDirection(double& DATA[][], int recount_columns)
{
   int i,j;
   for(j=recount_columns; j>0; j--)
   {
      for(i=0; i<ELEMENTS; i++)
      {
         if(DATA[j-1][i]-DATA[j][i]>0.0) ObjectSet(el_name+DoubleToStr(j-1,0)+"_"+i, OBJPROP_COLOR, LightGreen);
         else                            ObjectSet(el_name+DoubleToStr(j-1,0)+"_"+i, OBJPROP_COLOR, Red);
      }
   }
}

//+------------------------------------------------------------------+
void StochasticWeerAbsolute(double& DATA[][], int recount_columns)
{
   int i,j;
   double s0;
   color clr;

   for(j=recount_columns; j>0; j--)
   {
      for(i=0; i<ELEMENTS; i++)
      {
         if(DATA[j][i]>=50 && DATA[j][i]<80)
         {
            clr = ColorGradient(DATA[j][i], 50, 80, 1); //çåëåíûé
            ObjectSet(el_name+DoubleToStr(j-1,0)+"_"+i, OBJPROP_COLOR, clr);
         }
         else if(DATA[j][i]>=80 && DATA[j][i]<90)
            ObjectSet(el_name+DoubleToStr(j-1,0)+"_"+i, OBJPROP_COLOR, Chocolate);
         else if(DATA[j][i]>=90 && DATA[j][i]<=100)
            ObjectSet(el_name+DoubleToStr(j-1,0)+"_"+i, OBJPROP_COLOR, Maroon);
         else if(DATA[j][i]<50 && DATA[j][i]>=20)
         {
            clr = ColorGradient(-DATA[j][i], -50, -20, 2); //ñèíèé
            ObjectSet(el_name+DoubleToStr(j-1,0)+"_"+i, OBJPROP_COLOR, clr);
         }
         else if(DATA[j][i]<20 && DATA[j][i]>=10)
            ObjectSet(el_name+DoubleToStr(j-1,0)+"_"+i, OBJPROP_COLOR, Navy);
         else if(DATA[j][i]<10 && DATA[j][i]>=0)
            ObjectSet(el_name+DoubleToStr(j-1,0)+"_"+i, OBJPROP_COLOR, Black);
      }
   }
}

//+------------------------------------------------------------------+
void StochasticWeerAcceleration(double& DATA[][], int columns)
{
   int i,j;
   color clr;
   double max_vel;
   double VEL[][ELEMENTS];
   ArrayResize(VEL, columns);
     
   //Íàðèñóåì ìàòðèöó ñêîðîñòåé
   for(j=columns; j>0; j--)
      for(i=0; i<ELEMENTS; i++)
         VEL[j-1][i]=DATA[j-1][i]-DATA[j][i];
   
   //çà ïåðèîä Columns ñàìàÿ ñèëüíàÿ àáñîëþòíàÿ áàðîâàÿ ñêîðîñòü
   for(i=0; i<ELEMENTS; i++)
   {
      max_vel=-10000;
      for(j=0; j<columns; j++)
            max_vel=MathMax(max_vel, MathAbs(VEL[j][i]));
   
      //Ñêîðîñòü âíèç - êðàñíûé ãðàäèåíò; ñêîðîñòü ââåðõ - çåëåíûé
      for(j=0; j<columns; j++)
      {
         if(VEL[j][i]>=0)   
         {
            clr = ColorGradient(VEL[j][i], 0, max_vel, 1); //çåëåíûé
            ObjectSet(el_name+j+"_"+i, OBJPROP_COLOR, clr);
         }
         else
         {
            clr = ColorGradient(-VEL[j][i], 0, max_vel, 0); //êðàñíûé
            ObjectSet(el_name+j+"_"+i, OBJPROP_COLOR, clr);
         }
      }
   }
}


//+------------------------------------------------------------------+
color ColorGradient(double current_vol, double min_vol, double max_vol, int maincolor)
{
   int R,G,B;
   int cur;
   if(current_vol<min_vol) current_vol=min_vol;    
   if(current_vol>max_vol) current_vol=max_vol;    

   cur = 255-255*(current_vol-min_vol)/(max_vol-min_vol);
   if(maincolor==0)  //RED
   { R=255; G=cur; B=cur; }
   else if(maincolor==1) //GREEN
   { R=cur; G=255; B=cur; }
   else if(maincolor==2) //BLUE
   { R=cur; G=cur; B=255; }
   else {R=0;G=0;B=0;}   
   
   G<<=8;
   B<<=16;
   return(R+G+B);
}

//+------------------------------------------------------------------+
void CreateShield(string name_mask, double top, double bottom, int width, int freebars, color clr)
{
   double high, gap, y1, y2;
   datetime fut0, fut1;

   high = (top-bottom)/(ELEMENTS*1.0);
   gap= high*GAP_PERCENT/100.0;
   bottom=bottom+gap;
   top=top-HEADER*high;
   high = (top-bottom)/(ELEMENTS*1.0);
   gap= high*GAP_PERCENT/100.0;
   high=high-gap;
   
   if(freebars>0)
   {
      fut0=Time[0]+Period()*freebars*60;
      fut1=Time[width]+Period()*freebars*60;
   }
   else
   {
      fut0=iTime(NULL,0,-freebars);
      fut1=iTime(NULL,0,-freebars+width);
   }
   y2=top;
   for(int i=0; i<ELEMENTS; i++)
   {
      y1=y2-gap;
      y2=y1-high;
      ObjectCreate(name_mask+i, OBJ_RECTANGLE, 0, fut0, y1, fut1, y2);
      ObjectSet(name_mask+i, OBJPROP_COLOR, clr);
   }
   return;
}

//+------------------------------------------------------------------+
int MoveShield(string name_mask, double top, double bottom, int width, int freebars)
{
   double high, gap, y1, y2;
   datetime fut0, fut1;

   high = (top-bottom)/(ELEMENTS*1.0);
   gap= high*GAP_PERCENT/100.0;
   bottom=bottom+gap;
   top=top-HEADER*high;
   high = (top-bottom)/(ELEMENTS*1.0);
   gap= high*GAP_PERCENT/100.0;
   high=high-gap;
   
   if(freebars>0)
   {
      fut0=Time[0]+Period()*freebars*60;
      fut1=Time[width]+Period()*freebars*60;
   }
   else
   {
      fut0=iTime(NULL,0,-freebars);
      fut1=iTime(NULL,0,-freebars+width);
   }
   y2=top;
   for(int i=0; i<ELEMENTS; i++)
   {
      y1=y2-gap;
      y2=y1-high;
      if(ObjectMove(name_mask+i, 0, fut0, y1)==false) return(-1);
      ObjectMove(name_mask+i, 1, fut1, y2);
   }
   return(0);
}

//+------------------------------------------------------------------+
void CreateHeader(string text, double top, int width, int columns, int freebars, color clr)
{
   datetime time_center;
   int allbars;
   if(freebars<0) {Print("ERROR CreateHeader: freebars<0"); return;}   
   allbars = columns*(width+GAP); //ñòîëüêî íóæíî áàðîâ ïîä äèàãðàììó
   if(allbars/2<freebars) //öåíòð çàãîëîâêà óìåùàåòñÿ â çîíå çà ãðàôèêîì ñïðàâà
      time_center=Time[0] + 60*Period()*(freebars - columns*(width+GAP)/2);
   else   //îòðèñîâêà ÷àñòè÷íî çàõâàòûâàåò èñòîðè÷åñêóþ çîíó
      time_center = iTime(NULL, 0, allbars/2-freebars);
   ObjectCreate(el_name+"_HEAD", OBJ_TEXT, 0, time_center, top);
   ObjectSetText(el_name+"_HEAD", text, 14, "Areal", clr);
   return;
}

//+------------------------------------------------------------------+
void MoveHeader(double top, int width, int columns, int freebars, color clr)
{
   datetime time_center;
   int allbars;
   if(freebars<0) {Print("ERROR CreateHeader: freebars<0"); return;}   
   allbars = columns*(width+GAP); //ñòîëüêî íóæíî áàðîâ ïîä äèàãðàììó
   if(allbars/2<freebars) //öåíòð çàãîëîâêà óìåùàåòñÿ â çîíå çà ãðàôèêîì ñïðàâà
      time_center=Time[0] + 60*Period()*(freebars - columns*(width+GAP)/2);
   else   //îòðèñîâêà ÷àñòè÷íî çàõâàòûâàåò èñòîðè÷åñêóþ çîíó
      time_center = iTime(NULL, 0, allbars/2-freebars);
   ObjectMove(el_name+"_HEAD", 0, time_center, top);
}

//+------------------------------------------------------------------+
void DeleteIndicatorObject(string mask)
{
   int obj_total, i, out;
   string name;
   out=1;
   while(out>0)
   {   
      obj_total=ObjectsTotal();
      out=0;
      for(i=0;i<obj_total;i++)
      {
         name = ObjectName(i);
         if(StringFind(name,mask)>=0) { ObjectDelete(name); out++; }
      }
   }
}
//+------------------------------------------------------------------+
void err(string name)
{
   int err=GetLastError();
   if(err!=0)  Print(name," ERROR(",err,"): ",ErrorDescription(err));
}

Comments