WPR
Download scriptThis script functions as a technical analysis tool designed to measure the momentum and relative position of a financial asset's price within a specific timeframe. It provides visual data on a separate window, helping traders identify potential overbought or oversold conditions.
Core Logic and Methodology
Price Range Analysis The tool operates by looking at a defined number of past price bars (the period). For every point in time, it identifies two key pieces of information:
- The highest price reached during that period.
- The lowest price reached during that period.
By comparing the current closing price against these highs and lows, the script calculates where the price currently sits as a percentage. This allows you to see if the price is hugging the top of its recent range (indicating high demand/potential exhaustion) or the bottom of its recent range (indicating high supply/potential recovery).
Visual Representation The result is plotted as a line graph ranging from -100 to 0.
- A value closer to -100 suggests that the price is currently near the bottom of its recent range, often interpreted by traders as an "oversold" condition.
- A value closer to 0 suggests that the price is currently near the top of its recent range, often interpreted as an "overbought" condition.
Automated Notifications (Alert System)
Beyond just providing a visual graph, the script includes an intelligent alert system designed to notify the user in real-time:
- Dynamic Timeframe Detection: The script automatically detects which timeframe you are currently viewing (e.g., 1-minute, 1-hour, Daily) and includes this information in any notification.
- Customizable Thresholds: Users can define specific "Bull" and "Bear" levels. When the indicator value crosses these pre-set boundaries, the script triggers a notification.
- Smart Timing: To prevent the system from sending constant repetitive notifications, the logic is designed to only trigger an alert once per new candle (bar). This ensures that you are notified of a significant movement at the start of a new price period rather than being overwhelmed by alerts during every small tick of price movement.
Summary for the User
Essentially, this tool acts as a "momentum thermometer." It tells you how far the price has moved relative to its recent extremes and proactively pings you when the price reaches extreme territory, allowing for more efficient monitoring of market trends without needing to watch the charts constantly.
//+------------------------------------------------------------------+
//| Williams Percent Range.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_minimum -100
#property indicator_maximum 0
#property indicator_buffers 1
#property indicator_color1 DodgerBlue
#property indicator_level1 -5
#property indicator_level2 -95
#property indicator_level3 -50
//---- input parameters
extern int ExtWPRPeriod = 30;
extern string note = "turn on Alert = true; turn off = false";
extern bool AlertOn = true;
extern int BullLevel=-99;
extern int BearLevel=-2;
//---- buffers
double ExtWPRBuffer[];
// Show regular timeframe string (HCY)
string AlertPrefix;
string GetTimeFrameStr() {
switch(Period())
{
case 1 : string TimeFrameStr="M1"; break;
case 5 : TimeFrameStr="M5"; break;
case 15 : TimeFrameStr="M15"; break;
case 30 : TimeFrameStr="M30"; break;
case 60 : TimeFrameStr="H1"; break;
case 240 : TimeFrameStr="H4"; break;
case 1440 : TimeFrameStr="D1"; break;
case 10080 : TimeFrameStr="W1"; break;
case 43200 : TimeFrameStr="MN1"; break;
default : TimeFrameStr="CUR";
}
return (TimeFrameStr);
}
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
string sShortName;
//---- indicator buffer mapping
SetIndexBuffer(0, ExtWPRBuffer);
//---- indicator line
SetIndexStyle(0, DRAW_LINE);
//---- name for DataWindow and indicator subwindow label
sShortName="%R(" + ExtWPRPeriod + ")";
IndicatorShortName(sShortName);
SetIndexLabel(0, sShortName);
//---- first values aren't drawn
SetIndexDrawBegin(0, ExtWPRPeriod);
//----
AlertPrefix=Symbol()+" ("+GetTimeFrameStr()+"): ";
return(0);
}
//+------------------------------------------------------------------+
//| Williams Percent Range |
//+------------------------------------------------------------------+
int start()
{
int i, nLimit, nCountedBars;
//---- insufficient data
if(Bars <= ExtWPRPeriod)
return(0);
//---- bars count that does not changed after last indicator launch.
nCountedBars = IndicatorCounted();
//----Williams Percent Range calculation
i = Bars - ExtWPRPeriod - 1;
if(nCountedBars > ExtWPRPeriod)
i = Bars - nCountedBars - 1;
while(i >= 0)
{
double dMaxHigh = High[Highest(NULL, 0, MODE_HIGH, ExtWPRPeriod, i)];
double dMinLow = Low[Lowest(NULL, 0, MODE_LOW, ExtWPRPeriod, i)];
if(!CompareDouble((dMaxHigh - dMinLow), 0.0))
ExtWPRBuffer[i] = -100*(dMaxHigh - Close[i]) / (dMaxHigh - dMinLow);
i--;
}
//----
// ======= Alert =========
if(AlertOn && NewBar()){
if((ExtWPRBuffer[0] <= BullLevel) && (ExtWPRBuffer[0] <=-indicator_minimum))
Alert(AlertPrefix+" %R("+ExtWPRPeriod+") Buy Alert "+ ExtWPRBuffer[0]);
else
if((ExtWPRBuffer[0] >= BearLevel) && (ExtWPRBuffer[0] <=indicator_maximum))
Alert(AlertPrefix+" %R("+ExtWPRPeriod+") Sell Alert "+ ExtWPRBuffer[0]);
}
// ======= Alert Ends =========
return(0);
}
//+------------------------------------------------------------------+
//| Ôóíêöèÿ ñðàíåíèÿ äâóõ âåùåñòâåííûõ ÷èñåë. |
//+------------------------------------------------------------------+
bool CompareDouble(double Number1, double Number2)
{
bool Compare = NormalizeDouble(Number1 - Number2, 8) == 0;
return(Compare);
}
//+------------------------------------------------------------------+
bool NewBar()
{
static datetime lastbar;
datetime curbar = Time[0];
//Print("NewBar(). lastbar="+TimeToStr(lastbar,TIME_DATE|TIME_MINUTES)+" curbar="+TimeToStr(curbar,TIME_DATE|TIME_MINUTES));
if(lastbar!=curbar)
{
lastbar=curbar;
return (true);
}
else
{
return(false);
}
}
Comments