_MasterSlave
Download scriptThis technical script is designed as a versatile trading indicator for the MetaTrader platform. Its primary purpose is to take raw market data (such as price, volume, volatility, or standard deviation) and transform it into a normalized, readable visual format that helps traders identify trends and momentum more clearly.
Core Logic Overview
The script operates through a multi-step processing pipeline to turn "messy" market data into a clean signal:
1. Data Input Selection The tool allows you to choose exactly what kind of information you want to analyze. You can feed the script various types of data, including:
- Volume: Tracking the amount of trading activity.
- Price Types: Specific price points like the High, Low, Open, or various weighted averages.
- Volatility (ATR): Measuring how much the market is swinging.
- Standard Deviation: Calculating how much prices are deviating from their average.
2. Preliminary Processing (Filtering) Once the data is selected, the script applies a "Smoothing" layer. It uses Moving Averages (either Simple or Exponential) to filter out minor market "noise." This ensures that the final result reflects broader trends rather than momentary fluctuations. For standard deviation inputs, it performs extra smoothing to keep the values stable.
3. Calculation of Differences The logic then identifies the relationship between the smoothed data and the raw input. Essentially, it calculates the gap or the "distance" between the current price action and its moving average. This is key for identifying whether the market is overextended or gaining momentum.
4. Normalization (The "Scaling" Engine) This is the most sophisticated part of the script. Because different assets (like Gold vs. Forex) have different price scales, raw numbers aren't always easy to compare. The script performs "Normalization," which compresses the data into a standard range (typically 0 to 1).
- Dynamic Windows: It looks at a specific "window" of past data to determine the highest and lowest points.
- Sensitivity Control: You can adjust how sensitive the tool is to price changes, allowing it to react quickly to new movements or stay steady during slow periods.
5. Final Signal Generation The final output is a smoothed line (the "Signal") based on the normalized data.
- Directional Cues: If enabled, the script can display a histogram that uses positive and negative signs. This tells you not just the strength of the movement, but also whether it is aligned with the current price direction.
- Visual Clarity: By confining the data to a specific range, it prevents the indicator from jumping wildly across your screen, making it much easier for a human trader to interpret at a glance.
Summary for the User
Think of this script as a "Market Translator." It takes complex, raw market numbers, scrubs away the unnecessary noise through smoothing filters, scales everything down into a uniform 0–1 range so you can see relative strength easily, and then plots a clean, readable line that highlights the underlying momentum of your chosen data source.
#property indicator_separate_window // â ïîäîêíå
#property indicator_buffers 7
#property indicator_color1 Red // ñèãíàëüíàÿ
#property indicator_color6 Blue // ãèñòîãðàììà äèíàìèêè äëèíû âûáîðêè
#property indicator_maximum 1
#property indicator_minimum 0
// âõîäíûå ïàðàìåòðû
//-- ðåäêîþçàåìûå ïàðàìåòðû ñäåëàíû íå extern - ìîæíî ðàñøèðèòü ââîä ïðè æåëàíèè
extern int Source=1; // 0 - îáúåì; 1 - ñò.äåâèàöèÿ öåíû; 2 - ATR; 3 - öåíà;
int ApplPrice=0; // 0 - Close; 4 - (high+low)/2; 5 - (high+low+close)/3; 6 - (high+low+close+close)/4;
extern int SourcePeriod=88; // ïåðèîä âõîäíîãî èíäèêàòîðà
int Shift=0; // ñäâèã
bool MAtypeI=1; // 0 - SMA, 1 - EMA
int PrePeriod=1; // äëÿ äåâèàöèè äîïîëíèòåëüíîå ñãëàæèâàíèå, îñòàëüíûå - ìåäëåííàÿ MA äëÿ MACD
bool MAtypeP=1; // 0 - SMA, 1 - EMA
extern int Window=111; // äëèíà âûáîðêè íîðìèðîâàíèÿ
int WindowLimit=0; // ìíîæèòåëü îãðàíè÷åíèå äëèíû âûáîðêè íîðìèðîâàíèÿ
int WindowShift=0; // ñäâèã âûáîðêè íîðìèðîâàíèÿ
bool WindowMethod=0; // 0 - ôèêñèðîâàííàÿ âûáîðêà äëÿ íîðìèðîâàíèÿ, 1 - ïëàâàþùàÿ
extern double Sensitivity=0; // ÷óâñòâèòåëüíîñòü
bool abs=1; // âûâîä ÷åðåç áóôåð NP[] ñî çíàêîì äâèæåíèÿ ñò.äåâèàöèè
bool ToRange=1; // ïðèíóäèòåëüíîå îãðàíè÷åíèå äèàï. 0...1; èìååò ñìûñë òîëüêî ïðè WindowShift>0
double Power=1; // ñòåïåíü ïî íîðìèðîâàíèþ
extern int Signal=55; // ñãëàæèâàíèå íîðìèðîâàííîãî èíäèêàòîðà (ñèãíàëüíàÿ)
bool MAtypeS=1; // 0 - SMA, 1 - EMA
int SignalShift=0; // ñäâèã ñèãíàëüíîé
int History=0;
// èíäèêàòîðíûå áóôåðû
double Ind[], // íîðìèðóåìûé èíäèêàòîð
PR[], // ïðåôèëüòðàöèÿ
NORM[], // ðåçóëüòàòû íîðìèðîâàíèÿ
SM[], // ñèãíàëüíàÿ
Input[], // áóôåð àðãóìåíòîâ íîðìèðóåìîãî èíäèêàòîðà (öåíà èëè îáúåì)
MA[], // ÌÀ íîðìèðóåìîãî èíäèêàòîðà
NP[], // ïëàâàþùèé ïåðèîä íîðìèðîâàíèÿ - â âû÷èñëèíèÿõ íå ó÷àñòâóåò - äëÿ íàãëÿäíîñòè
SIGN[]; // åìóëèðîâàííûé áóôåð - âñïîìîãàòåëüíàÿ MA
double sens, // ÷óâñòâèòåëüíîñòü â ìàñøòàáå öåíû/îáúåìà
sensLimit, // ìèíèìàëüíàÿ ÷óâñâèòåëüíîñòü
sn,
IndPeriodK, // êîýôô. EMA äëÿ äåâèàöèè
PrePeriodK, // êîýôô. EMA äëÿ ïðåôèëüòðà
SignalK; // êîýôô. EMA äëÿ ñãëàæèâàíèÿ
bool Em=0; // ôëàã äëÿ ýìóëÿöèè âñïîìîãàòåëüíîé MA
//int WindowLimit; // îãðàíè÷åíèå äëèíû âûáîðêè íîðìèðîâàíèÿ
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
switch(Source) {
case 0: // Îáúåì
SetIndexStyle(2,DRAW_LINE,0,1,LimeGreen);
string ShortName="Volume(";
double punkt=1;
WindowShift++;
break;
case 3: // Ñòîõàñòèê
SetIndexStyle(2,DRAW_LINE,0,1,LightSeaGreen);
ShortName="MA(";
WindowMethod=1; // èñïîëüçîâàòü ïëàâàþùóþ äëèíó âûáîðêè íîðìèðîâàíèÿ
punkt=Point;
break;
case 2: // ñò.äåâèàöèÿ
SetIndexStyle(2,DRAW_LINE,0,1,MediumSeaGreen);
ShortName="StDev(";
punkt=Point;
break;
case 1: //ATR
SetIndexStyle(2,DRAW_LINE,0,1,DodgerBlue);
ShortName="ATR(";
punkt=Point;
}
if(WindowMethod) {
if(WindowLimit==0) WindowLimit=Window*10; // îãðàíè÷åíèå äëèíû âûáîðêè íîðìèðîâàíèÿ
else WindowLimit=MathMax(WindowLimit,Window);
}
ShortName=ShortName+_Price()+SourcePeriod;
if(Shift>0) ShortName=ShortName+"+"+Shift;
ShortName=ShortName+") ";
if(PrePeriod>1) ShortName=ShortName+PrePeriod+" ";
ShortName=ShortName+"["+Window;
if(WindowMethod && Sensitivity>0) ShortName=ShortName+"_"+WindowLimit;
if(WindowShift>0) ShortName=ShortName+"+"+WindowShift;
if(Sensitivity>0) ShortName=ShortName+"@"+DoubleToStr(Sensitivity,1);
ShortName=ShortName+"]";
if(Power!=1) ShortName=ShortName+"^"+DoubleToStr(Power,1);
if(Signal>1 || SignalShift>0) {
ShortName=ShortName+" ("+Signal;
if(SignalShift>0) ShortName=ShortName+"+"+SignalShift;
ShortName=ShortName+")";
}
IndicatorShortName(ShortName); // çàäàòü èìÿ èíäèêàòîðà â ïîäîêíå
//---- indicators
SetIndexBuffer(0,SM); // ñèãíàëüíàÿ
SetIndexStyle(0,DRAW_LINE);
SetIndexLabel(0,"Signal");
SetIndexBuffer(1,Ind); // èíäèêàòîð
SetIndexStyle(1,DRAW_NONE);
SetIndexLabel(1,NULL);
SetIndexBuffer(2,NORM); // ðåçóëüòàòû íîðìèðîâàíèÿ
SetIndexLabel(2,"Normed");
SetIndexBuffer(3,MA); // MA èíäèêàòîðà
SetIndexStyle(3,DRAW_NONE);
SetIndexLabel(3,NULL);
SetIndexBuffer(4,Input); // áóôåð âõîäíûõ äàííûõ (îáúåì èëè öåíà)
SetIndexStyle(4,DRAW_NONE);
SetIndexLabel(4,NULL);
SetIndexBuffer(5,NP); // ãèñòîãðàììà è âûâîä ñî çíàêîì ñò.äåâ.
if(Source==-3 && Sensitivity>0) // ïîêàçàòü äëèíó âûáîðêè íîðìèðîâàíèÿ
{
SetIndexStyle(5,DRAW_HISTOGRAM);
Source=-Source;
}
else SetIndexStyle(5,DRAW_NONE);
if(Source==3 && Sensitivity>0) SetIndexLabel(5,"Window");
else SetIndexLabel(5,NULL);
if(abs) SetIndexLabel(5,"NormSign");
else SetIndexLabel(5,NULL);
SetIndexBuffer(6,PR); // ðåçóëüòàòû ïðåôèëüòðàöèè èíäèêàòîðà (ïîäàþòñÿ â íîðìèðîâàíèå)
SetIndexStyle(6,DRAW_NONE);
SetIndexLabel(6,"Source");
//----
sensLimit=punkt/1000; // ìèíèìàëüíàÿ ÷óâñâèòåëüíîñòü
sens=MathMax(Sensitivity*punkt,sensLimit); // ÷óâñòâèòåëüíîñòü â ìàñøòàáå èíäèêàòîðà
if(WindowMethod) sn=sensLimit; // åñëè äèíàìè÷åñêîå íîðìèðîâàíèå
else sn=sens;
if(SourcePeriod<0) {MAtypeI=0; SourcePeriod=-SourcePeriod;} // SMA
else IndPeriodK=2.0/(SourcePeriod+1); // EMA
if(PrePeriod<0) {MAtypeP=0; PrePeriod=-PrePeriod;} // SMA
else PrePeriodK=2.0/(PrePeriod+1); // EMA
if(Signal<0) {MAtypeS=0; Signal=-Signal;} // SMA
else SignalK=2.0/(Signal+1); // EMA
if(Source==0 || Source==1) Em=1; // ôëàã äëÿ ýìóëÿöèè âñïîìîãàòåëüíîé MA
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
if(Em) EmBuff();
int ic=IndicatorCounted();
if(Bars-ic-1>1) {ic=reinit();}
int limit=Bars-ic-1; //BarsPrev=Bars; // êîë-âî ïåðåñ÷åòîâ
if(History!=0 && limit>History) limit=History-1; // êîë-âî ïåðåñ÷åòîâ ïî èñòîðèè
for(int i=limit; i>=0; i--) // öèêë ïî íåïîñ÷èòàííûì è ïðåäïîñëåäíåìó áàðàì
{
double ma;
int n;
int iShift=i+Shift;
if(Em) { // Ýìóëèðóåìàÿ ÌÀ
if(MAtypeI) // EMA
SIGN[i]=IndPeriodK*Price(4,iShift)+(1-IndPeriodK)*SIGN[i+1];
else { // SMA
int sh=iShift+SourcePeriod;
ma=SIGN[i+1]*SourcePeriod-Price(4,sh);
SIGN[i]=(ma+Close[iShift])/SourcePeriod;
}
}
// âûáîð èñòî÷íèêà
switch(Source) {
case 0: // îáúåì
Input[i]=Volume[iShift]; break;
case 3: // öåíà
Input[i]=Price(ApplPrice,iShift); break;
case 2:
Input[i]=Price(ApplPrice,iShift); break;
case 1: // ATR
Input[i]=MathMax(High[iShift],Close[iShift+1])-MathMin(Low[iShift],Close[iShift+1]);
}
// MA
if(MAtypeI) { // EMA
MA[i]=IndPeriodK*Input[i]+(1-IndPeriodK)*MA[i+1];
ma=MA[i];
}
else { // SMA
sh=i+SourcePeriod;
ma=MA[i+1]*SourcePeriod-Input[sh];
MA[i]=(ma+Input[i])/SourcePeriod;
ma=MA[i];
}
// ñò.äåâèàöèÿ
if(Source==2) // íîðìèðóåòñÿ äåâèàöèÿ
{
double std=0;
for(n=0; n<SourcePeriod; n++) {
double delta=Input[i+n]-ma;
std+=delta*delta; // ÷èñëèòåëü SourcePeriod(Price)
}
Ind[i]=MathSqrt(std/SourcePeriod);
//
if(PrePeriod==1) PR[i]=Ind[i];
else
if(MAtypeP)
PR[i]=PrePeriodK*Ind[i]+(1-PrePeriodK)*PR[i+1];
else {
sh=i+PrePeriod;
ma=PR[i+1]*PrePeriod-Ind[sh];
PR[i]=(ma+Ind[i])/PrePeriod;
}
}
else // MA (öåíà èëè îáúåì)
if(PrePeriod==1) PR[i]=MA[i];
else {
if(MAtypeP)
Ind[i]=PrePeriodK*Input[i]+(1-PrePeriodK)*Ind[i+1];
else {
sh=i+PrePeriod;
ma=PR[i+1]*PrePeriod-Input[sh];
Ind[i]=(ma+Input[i])/PrePeriod;
}
PR[i]=MA[i]-Ind[i];
if(abs) PR[i]=MathAbs(PR[i]);
}
// Íîðìèðîâàíèå
double max=PR[ArrayMaximum(PR,Window,i+WindowShift)];
double min=PR[ArrayMinimum(PR,Window,i+WindowShift)];
if(WindowMethod)
for(n=Window; max-min<sens && n<=WindowLimit; n++) {
int in=i+n+WindowShift;
max=MathMax(max,PR[in]);
min=MathMin(min,PR[in]);
}
double x=(PR[i]-min)/MathMax((max-min),sn);
if(Power!=1 && Power>0) x=MathPow(x,Power);
NORM[i]=x;
if(ToRange) // ïðè ñäâèãå âûáîðêè óáðàòü çíà÷åíèÿ âíå äèàï.0...1
{NORM[i]=MathMax(NORM[i],0); NORM[i]=MathMin(NORM[i],1);}
if(abs) // âûâîä íîðìèðîâàíèÿ ñî çíàêîì
if(Em) // åñëè îáúåì èëè ATR
{if(Close[i]>SIGN[i+3]) NP[i]=NORM[i]; else NP[i]=-NORM[i];}
else // åñëè ñò.äåâ.
{if(Close[i]>MA[i+3]) NP[i]=NORM[i]; else NP[i]=-NORM[i];}
// Ñãëàæèâàíèå .
if(Signal==1) SM[i]=NORM[i+SignalShift];
else
if(MAtypeS) // EMA
SM[i]=SignalK*NORM[i+SignalShift]+(1-SignalK)*SM[i+1];
else { // SMA
sh=i+SignalShift+Signal;
ma=SM[i+1]*Signal-NORM[sh];
SM[i]=(ma+NORM[i+SignalShift])/Signal;
}
}
//----
return(0);
}
//----------------------------------------------------
// ô-ÿ äîïîëíèòåëüíîé èíèöèàëèçàöèè
int reinit()
{
ArrayInitialize(Input,0.0);
ArrayInitialize(Ind,0.0);
ArrayInitialize(PR,0.0);
ArrayInitialize(NORM,0.0);
ArrayInitialize(SM,0.0);
ArrayInitialize(MA,0.0);
ArrayInitialize(NP,0.0);
return(0);
}
double Price(int ApplPrice,int i) {
switch(ApplPrice) {
case 0: return(Close[i]);
case 1: return(Open[i]);
case 2: return(High[i]);
case 3: return(Low[i]);
case 4: return((High[i]+Low[i])/2);
case 5: return((High[i]+Low[i]+Close[i])/3);
case 6: return((High[i]+Low[i]+2*Close[i])/4);
default: return(Close[i]);
}
}
string _Price() {
switch(ApplPrice) {
case 0: return("");
case 1: return("O");
case 2: return("H");
case 3: return("L");
case 4: return("M");
case 5: return("T");
case 6: return("W");
default: return("");
}
}
void EmBuff()
{
static int NewSize;
if(NewSize==Bars) return;
NewSize=Bars;
ArraySetAsSeries(SIGN,0); ArrayResize(SIGN,NewSize); ArraySetAsSeries(SIGN,1);
}
//+------------------------------------------------------------------+
Comments