aNina
Download scriptThis script is a technical analysis tool designed to identify market trends and potential entry or exit points by analyzing price volatility and momentum. Instead of simply looking at where the price is going, it calculates how "stretched" the price has become relative to recent history.
Core Logic and Methodology
1. Volatility Measurement (WATR) The indicator begins by calculating a specialized volatility range. It looks back over a specific period (defined by the user) to determine the average movement of the market. By identifying the highest and lowest points during this window, it establishes a "normal" range for price fluctuations.
2. Dynamic Boundary Creation Based on that volatility, the script creates three distinct types of boundaries:
- Minimum Boundaries: Tight ranges that represent subtle movements.
- Maximum Boundaries: Wide ranges that represent extreme movements or high-volatility zones.
- Midpoint Boundaries: Balanced ranges that represent the average expected movement.
The script constantly compares the current closing price against these boundaries to determine the prevailing "Trend." If the price breaks significantly above or below these calculated levels, the logic adjusts its internal tracking to reflect a shift in market direction (Upward, Downward, or Neutral).
3. Momentum Tracking (Stochastic Mapping) The tool transforms these trends into a normalized visual scale. By comparing where the current trend sits relative to the maximum possible volatility range, it calculates two distinct momentum lines (LineMin and LineMid). These lines essentially tell you how "fast" and "far" the price is moving compared to its own historical limits.
4. Signal Generation The script identifies specific trading signals based on the interaction of these lines:
- Trend Crossovers: When the momentum lines cross each other, it suggests a potential change in the immediate short-term direction.
- Confirmation Filtering: To prevent "false alarms," the script doesn't just fire a signal on every crossover. It checks for additional confirmation by comparing the current momentum against a 50-period Moving Average and checking for "inverse" price actions.
- Visual Cues: When all conditions align—meaning the trend is confirmed, the moving average supports the direction, and the momentum lines have crossed—the script places visual markers (arrows) on the chart to suggest potential Buy or Sell opportunities.
Summary of Behavior
In simple terms, this indicator looks for "overextended" price movements. It calculates how much the market usually moves, identifies when the price is pushing outside of that normal behavior, and then looks for a specific moment where that momentum starts to shift back, providing the user with a visual alert for potential trades.
//+------------------------------------------------------------------+
//| Nina.mq4 |
//| Copyright © 2005, MetaQuotes Software Corp. |
//| http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, MetaQuotes Software Corp."
#property link "http://www.metaquotes.net"
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_color1 Brown
#property indicator_color2 DeepSkyBlue
#property indicator_color3 Green
#property indicator_color4 Red
#property indicator_color5 Blue
#property indicator_minimum 0
#property indicator_maximum 1
//---- input parameters
extern int PeriodWATR = 10;
extern double Kwatr = 1.0000;
extern int HighLow = 0;
extern int cbars = 1000;
extern int from = 0;
//---- indicator buffers
double LineMinBuffer[];
double LineMidBuffer[];
double LineBuyBuffer[];
double LineSellBuffer[];
double LineExitBuffer[];
double Ma50[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
string short_name;
IndicatorBuffers(6);
SetIndexBuffer(0, LineMinBuffer);
SetIndexBuffer(1, LineMidBuffer);
SetIndexBuffer(2, LineBuyBuffer);
SetIndexBuffer(3, LineSellBuffer);
SetIndexBuffer(4, LineExitBuffer);
SetIndexBuffer(5, Ma50);
//---- indicator line
SetIndexStyle(0, DRAW_LINE);
SetIndexStyle(1, DRAW_LINE);
SetIndexStyle(2, DRAW_ARROW, 0, 1);
SetIndexStyle(3, DRAW_ARROW, 0, 1);
SetIndexStyle(4, DRAW_ARROW, 0, 1);
SetIndexStyle(5, DRAW_NONE);
//----
SetIndexArrow(2, 233);
SetIndexArrow(3, 234);
SetIndexArrow(4, 174);
//----
SetIndexEmptyValue(2, 0);
SetIndexEmptyValue(3, 0);
SetIndexEmptyValue(4, 0);
SetIndexEmptyValue(5, 0);
//----
IndicatorDigits(Digits + 1);
//---- name for DataWindow and indicator subwindow label
short_name="Nina(" + PeriodWATR + "," + Kwatr + "," + HighLow + ")";
IndicatorShortName(short_name);
//----
SetIndexDrawBegin(0, PeriodWATR);
SetIndexDrawBegin(1, PeriodWATR);
//----
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int last_ind_inv(int shift, int dir)
{
if(dir != 0)
{
for(int i = shift; i < cbars; i++)
{
if(dir > 0)
{
if(iCustom(NULL, 0, "0_IndInverse", 2, cbars, 1, i) != 0)
return (i);
}
else
if(dir < 0)
{
if(iCustom(NULL, 0, "0_IndInverse", 2, cbars, 2, i) != 0)
return(-i);
}
}
}
//----
return (0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int start()
{
int i, shift, TrendMin, TrendMax, TrendMid;
double SminMin0, SmaxMin0, SminMin1, SmaxMin1, SumRange, dK, WATR0, WATRmax, WATRmin;
double WATRmid;
double SminMax0, SmaxMax0, SminMax1, SmaxMax1, SminMid0, SmaxMid0, SminMid1, SmaxMid1;
double linemin, linemax, linemid, Stoch1, Stoch2, bsmin, bsmax;
//----
int StepSizeMin, StepSizeMax, StepSizeMid;
double min, max, mid, h, l, c;
//----
int b = 0;
int last = 0, ma = 0;
//----
for(shift = cbars - 1; shift >= from; shift--)
{
SumRange = 0;
for(i = PeriodWATR - 1; i >= from; i--)
{
dK = 1 + 1.0*(PeriodWATR - i) / PeriodWATR;
SumRange += dK*MathAbs(High[i+shift] - Low[i+shift]);
}
WATR0 = SumRange / PeriodWATR;
WATRmax = MathMax(WATR0, WATRmax);
//----
if(shift == cbars - 1 - PeriodWATR)
WATRmin = WATR0;
WATRmin = MathMin(WATR0, WATRmin);
StepSizeMin = MathRound(Kwatr*WATRmin / Point);
StepSizeMax = MathRound(Kwatr*WATRmax / Point);
StepSizeMid = MathRound(Kwatr*0.5*(WATRmax + WATRmin) / Point);
min = Kwatr*WATRmin;
max = Kwatr*WATRmax;
mid = Kwatr*0.5*(WATRmax + WATRmin);
c = Close[shift];
h = High[shift];
l = Low[shift];
//----
if(HighLow > 0)
{
SmaxMin0 = l + 2*min;
SminMin0 = h - 2*min;
SmaxMax0 = l + 2*max;
SminMax0 = h - 2*max;
SmaxMid0 = l + 2*mid;
SminMid0 = h - 2*mid;
//----
if(c > SmaxMin1)
TrendMin = 1;
//----
if(c < SminMin1)
TrendMin = -1;
//----
if(c > SmaxMax1)
TrendMax = 1;
//----
if(c < SminMax1)
TrendMax = -1;
//----
if(c > SmaxMid1)
TrendMid = 1;
//----
if(c < SminMid1)
TrendMid = -1;
}
//----
if(HighLow == 0)
{
SmaxMin0 = c + 2*min;
SminMin0 = c - 2*min;
SmaxMax0 = c + 2*max;
SminMax0 = c - 2*max;
SmaxMid0 = c + 2*mid;
SminMid0 = c - 2*mid;
//----
if(c > SmaxMin1)
TrendMin = 1;
//----
if(c < SminMin1)
TrendMin = -1;
//----
if(c > SmaxMax1)
TrendMax = 1;
//----
if(c < SminMax1)
TrendMax = -1;
//----
if(c > SmaxMid1)
TrendMid = 1;
//----
if(c < SminMid1)
TrendMid = -1;
}
//----
if(TrendMin > 0 && SminMin0 < SminMin1)
SminMin0 = SminMin1;
//----
if(TrendMin < 0 && SmaxMin0 > SmaxMin1)
SmaxMin0 = SmaxMin1;
//----
if(TrendMax > 0 && SminMax0 < SminMax1)
SminMax0 = SminMax1;
//----
if(TrendMax < 0 && SmaxMax0 > SmaxMax1)
SmaxMax0 = SmaxMax1;
//----
if(TrendMid > 0 && SminMid0 < SminMid1)
SminMid0 = SminMid1;
//----
if(TrendMid < 0 && SmaxMid0 > SmaxMid1)
SmaxMid0 = SmaxMid1;
//----
if(TrendMin > 0)
linemin = SminMin0 + min;
//----
if(TrendMin < 0)
linemin = SmaxMin0 - min;
//----
if(TrendMax > 0)
linemax = SminMax0 + max;
//----
if(TrendMax < 0)
linemax = SmaxMax0 - max;
//----
if(TrendMid > 0)
linemid = SminMid0 + mid;
//----
if(TrendMid < 0)
linemid = SmaxMid0 - mid;
bsmin = linemax - max;
bsmax = linemax + max;
if((bsmax - bsmin) != 0)
{
Stoch1 = (linemin - bsmin) / (bsmax - bsmin);
Stoch2 = (linemid - bsmin) / (bsmax - bsmin);
LineMinBuffer[shift] = Stoch1;
LineMidBuffer[shift] = Stoch2;
}
SminMin1 = SminMin0;
SmaxMin1 = SmaxMin0;
SminMax1 = SminMax0;
SmaxMax1 = SmaxMax0;
SminMid1 = SminMid0;
SmaxMid1 = SmaxMid0;
//----
if((LineMinBuffer[shift] - LineMidBuffer[shift])*(LineMinBuffer[shift+1] -
LineMidBuffer[shift+1]) < 0)
{
LineExitBuffer[shift] = LineMidBuffer[shift];
// BUY or SELL
if(LineMinBuffer[shift] > LineMidBuffer[shift])
{
last = shift;
}
else
if(LineMinBuffer[shift] < LineMidBuffer[shift])
{
last = -shift;
}
}
//----
if(last != 0 && Ma50[shift+1] != 0)
{
if(last > 0 && ma > 0 && last_ind_inv(shift, 1) > 0)
LineBuyBuffer[shift] = LineMidBuffer[shift];
else
if(last < 0 && ma < 0 && last_ind_inv(shift, -1) < 0)
LineSellBuffer[shift] = LineMidBuffer[shift];
}
Ma50[shift] = iMA(NULL, 0, 50, 0, MODE_EMA, PRICE_MEDIAN, shift);
//----
if(Ma50[shift] >= MathMax(Close[shift], Open[shift]) - 2.5*Point ||
Ma50[shift] <= MathMin(Close[shift], Open[shift]) + 2.5*Point)
Ma50[shift] = 0;
else
{
if(Close[shift] > Open[shift])
{
ma = shift;
}
else
if(Close[shift] < Open[shift])
{
ma = -shift;
}
}
}
return(0);
}
//+------------------------------------------------------------------+
Comments