This script is an automated charting tool designed to identify and visually highlight specific price action "boxes" based on historical market data. It is primarily used by traders to identify breakout opportunities by marking key price boundaries during specific sessions of the trading day.
Core Functionality
The primary logic revolves around identifying the highest and lowest prices reached during two distinct time periods (referred to as Period A and Period B). By calculating these extremes, the script draws visual rectangles on your chart that represent "price zones."
How the Logic Works
- Time Filtering: The user defines specific start and end times for two different periods. For example, one period might cover a morning opening session, while the second covers an afternoon closing session.
- Price Extremes Calculation: For each of these defined timeframes, the script automatically scans the market history to find the absolute highest price reached and the absolute lowest price reached.
- Visual Mapping: Once the high and low prices are found for those specific times, the script draws a rectangle on the chart. This allows you to see exactly where the "boundaries" of the market were for that day.
- Historical Tracking: The script is designed to look back over a set number of days (customizable by the user) and draw these boxes consistently across your historical chart, rather than just showing the current day.
Key Features for the User
- Automated Drawing: Instead of manually drawing boxes every day to see where price "broke out," the script handles all the measurements automatically based on the time settings you provide.
- Customizable Visuals: You can choose whether the boxes are solid (filled) or just outlines, and you can select different colors for different types of zones.
- Cross-Day Handling: The logic includes special instructions to handle scenarios where a trading period might start on one day and end on the next (such as sessions spanning across midnight).
- Smart Cleanup: The script is designed to be "clean." It automatically removes old objects when it initializes or shuts down, and it avoids drawing any data on Sundays to keep the chart tidy.
- Unique Identification: It uses a unique ID system, which allows you to run multiple versions of the tool on the same chart without them interfering with each other's drawings.
Summary for Trading
Essentially, this tool automates the "Box Breakout" strategy. By drawing these rectangles, it highlights the price range of a specific session. Traders use these boxes to see when the market moves outside of its established "normal" boundaries, which often serves as a signal for a new trend or a significant price breakout.
//+------------------------------------------------------------------+
//| BreakOut_BOX_4r2.mq4 |
//| hapalkos |
//| 2007.02.13 |
//| Code based on TIME1_modified.mq4 shown below |
//| posted to Forex Factory by glenn5t |
//| Concept of the break-out box form by Markj |
//| |
//| ++ modified so that rectangles do not overlay |
//| ++ this makes color selection more versatile |
//| +++ code consolidated to facilitate changes |
//| +++ changed period B rectangle and added offset value |
//| +++ corrected error in high-low code |
//| ++++ added ability to cross mid-night(nextDayA, nextDayB) |
//| ++++ added Unique ID to allow for multiple indicators |
//| ++++ added ability to delete specific rectangles |
//+------------------------------------------------------------------+
#property copyright "hapalkos"
#property link ""
#property indicator_chart_window
// Opening Range Break-Out per Mark Fisher in "The Logical Trader"
// more suitable to futures than spot forex
extern string UniqueID = "1420"; // --- Server Time --- GMT+2 ---
extern int NumberOfDays = 50;
extern string periodA_begin = "14:20"; // London Open
extern string periodA_end = "14:25"; // First thirty minutes after open
extern int nextDayA = 0; // Set to zero if periodA_begin and periodA_end are on the same day.
// Set to one if periodA_end is on the next day.
extern string periodB_end = "17:00"; // London close
extern int nextDayB = 0; // Set to zero if periodA_begin and periodB_end are on the same day.
// Set to one if periodB_end is on the next day.
extern color rectAB_color = C' 175,138,122';
extern bool rectAB_background = true; // true - filled solid; false - outline
extern color rectA_color = Gray;
extern bool rectA_background = false; // true - filled solid; false - outline
extern color rectB1_color = Gray;
extern bool rectB1_background = false; // true - filled solid; false - outline
extern int rectB1_band = 28; // a-value // Box Break-Out Band for the Period B rectangle
extern color rectsB2_color = Gray;
extern bool rectsB2_background = false; // true - filled solid, false - outline
extern int rectsB2_band = 56; // c-value // Box Break-Our Band for the two upper and lower rectangles
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
void init() {
DeleteObjects();
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function |
//+------------------------------------------------------------------+
void deinit() {
DeleteObjects();
return(0);
}
//+------------------------------------------------------------------+
//| Remove all indicator Rectangles |
//+------------------------------------------------------------------+
void DeleteObjects() {
datetime dtTradeDate=TimeCurrent();
for (int i=0; i<NumberOfDays; i++) {
ObjectDelete(UniqueID + " BoxHL " + TimeToStr(dtTradeDate,TIME_DATE));
ObjectDelete(UniqueID + " BoxBO_High " + TimeToStr(dtTradeDate,TIME_DATE));
ObjectDelete(UniqueID + " BoxBO_Low " + TimeToStr(dtTradeDate,TIME_DATE));
ObjectDelete(UniqueID + " BoxPeriodA " + TimeToStr(dtTradeDate,TIME_DATE));
ObjectDelete(UniqueID + " BoxPeriodB " + TimeToStr(dtTradeDate,TIME_DATE));
dtTradeDate=decrementTradeDate(dtTradeDate);
while (TimeDayOfWeek(dtTradeDate) > 5 || TimeDayOfWeek(dtTradeDate) < 1 ) dtTradeDate = decrementTradeDate(dtTradeDate); // Removed Sundays from plots
}
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
void start() {
datetime dtTradeDate=TimeCurrent();
for (int i=0; i<NumberOfDays; i++) {
DrawObjects(dtTradeDate, UniqueID + " BoxHL " + TimeToStr(dtTradeDate,TIME_DATE), periodA_begin, periodA_end, periodB_end, rectAB_color, 0, 1, rectAB_background,nextDayA,nextDayB);
//DrawObjects(dtTradeDate, UniqueID + " BoxBO_High " + TimeToStr(dtTradeDate,TIME_DATE), periodA_begin, periodA_end, periodB_end, rectsB2_color, rectsB2_band,2,rectsB2_background,nextDayA,nextDayB);
//DrawObjects(dtTradeDate, UniqueID + " BoxBO_Low " + TimeToStr(dtTradeDate,TIME_DATE), periodA_begin, periodA_end, periodB_end, rectsB2_color, rectsB2_band,3,rectsB2_background,nextDayA,nextDayB);
//DrawObjects(dtTradeDate, UniqueID + " BoxPeriodA " + TimeToStr(dtTradeDate,TIME_DATE), periodA_begin, periodA_end, periodA_end, rectA_color, 0,4, rectA_background,nextDayA,nextDayB);
//DrawObjects(dtTradeDate, UniqueID + " BoxPeriodB " + TimeToStr(dtTradeDate,TIME_DATE), periodA_begin, periodA_end, periodB_end, rectB1_color, rectB1_band,5, rectB1_background,nextDayA,nextDayB);
dtTradeDate=decrementTradeDate(dtTradeDate);
while (TimeDayOfWeek(dtTradeDate) > 5 || TimeDayOfWeek(dtTradeDate) < 1 ) dtTradeDate = decrementTradeDate(dtTradeDate); // Removed Sundays from plots
}
}
//+------------------------------------------------------------------+
//| Create Rectangles |
//+------------------------------------------------------------------+
void DrawObjects(datetime dtTradeDate, string sObjName, string sTimeBegin, string sTimeEnd, string sTimeObjEnd, color cObjColor, int iOffSet, int iForm, bool background, int nextDayA, int nextDayB) {
datetime dtTimeBegin, dtTimeEnd, dtTimeObjEnd;
double dPriceHigh, dPriceLow;
int iBarBegin, iBarEnd;
dtTimeBegin = StrToTime(TimeToStr(dtTradeDate, TIME_DATE) + " " + sTimeBegin);
dtTimeEnd = StrToTime(TimeToStr(dtTradeDate, TIME_DATE) + " " + sTimeEnd);
dtTimeObjEnd = StrToTime(TimeToStr(dtTradeDate, TIME_DATE) + " " + sTimeObjEnd);
if(nextDayA == 1) dtTimeEnd = dtTimeEnd + 86400;
if(nextDayB == 1) dtTimeObjEnd = dtTimeObjEnd + 86400;
if(nextDayA == 1 && TimeDayOfWeek(dtTradeDate) == 5) dtTimeEnd = dtTimeEnd + (2 * 86400);
if(nextDayB == 1 && TimeDayOfWeek(dtTradeDate) == 5) dtTimeObjEnd = dtTimeObjEnd + (2 * 86400);
iBarBegin = iBarShift(NULL, 0, dtTimeBegin)+1; // added 1 to bar count to correct calculation for highest price for the period
iBarEnd = iBarShift(NULL, 0, dtTimeEnd)+1; // added 1 to bar count to correct calculation for lowest price for the period
dPriceHigh = High[Highest(NULL, 0, MODE_HIGH, (iBarBegin)-iBarEnd, iBarEnd)];
dPriceLow = Low [Lowest (NULL, 0, MODE_LOW , (iBarBegin)-iBarEnd, iBarEnd)];
ObjectCreate(sObjName, OBJ_RECTANGLE, 0, 0, 0, 0, 0);
//---- High-Low Rectangle - Period A and B combined
if(iForm==1){
ObjectSet(sObjName, OBJPROP_TIME1 , dtTimeBegin);
ObjectSet(sObjName, OBJPROP_TIME2 , dtTimeObjEnd);
ObjectSet(sObjName, OBJPROP_PRICE1, dPriceHigh);
ObjectSet(sObjName, OBJPROP_PRICE2, dPriceLow);
ObjectSet(sObjName, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet(sObjName, OBJPROP_COLOR, cObjColor);
ObjectSet(sObjName, OBJPROP_BACK, background);
}
//---- Upper Rectangle - Period B
if(iForm==2){
ObjectSet(sObjName, OBJPROP_TIME1 , dtTimeEnd);
ObjectSet(sObjName, OBJPROP_TIME2 , dtTimeObjEnd);
ObjectSet(sObjName, OBJPROP_PRICE1, dPriceHigh);
ObjectSet(sObjName, OBJPROP_PRICE2, dPriceHigh + iOffSet*Point);
ObjectSet(sObjName, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet(sObjName, OBJPROP_COLOR, cObjColor);
ObjectSet(sObjName, OBJPROP_BACK, background);
}
//---- Lower Rectangle - Period B
if(iForm==3){
ObjectSet(sObjName, OBJPROP_TIME1 , dtTimeEnd);
ObjectSet(sObjName, OBJPROP_TIME2 , dtTimeObjEnd);
ObjectSet(sObjName, OBJPROP_PRICE1, dPriceLow - iOffSet*Point);
ObjectSet(sObjName, OBJPROP_PRICE2, dPriceLow);
ObjectSet(sObjName, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet(sObjName, OBJPROP_COLOR, cObjColor);
ObjectSet(sObjName, OBJPROP_BACK, background);
}
//---- Period A Rectangle
if(iForm==4){
ObjectSet(sObjName, OBJPROP_TIME1 , dtTimeBegin);
ObjectSet(sObjName, OBJPROP_TIME2 , dtTimeEnd);
ObjectSet(sObjName, OBJPROP_PRICE1, dPriceHigh);
ObjectSet(sObjName, OBJPROP_PRICE2, dPriceLow);
ObjectSet(sObjName, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet(sObjName, OBJPROP_COLOR, cObjColor);
ObjectSet(sObjName, OBJPROP_WIDTH, 2);
ObjectSet(sObjName, OBJPROP_BACK, background);
string sObjDesc = StringConcatenate("High: ",dPriceHigh," Low: ", dPriceLow);
ObjectSetText(sObjName, sObjDesc,10,"Times New Roman",Black);
}
//---- Period B Rectangle
if(iForm==5){
ObjectSet(sObjName, OBJPROP_TIME1 , dtTimeEnd);
ObjectSet(sObjName, OBJPROP_TIME2 , dtTimeObjEnd);
ObjectSet(sObjName, OBJPROP_PRICE1, dPriceHigh + iOffSet*Point);
ObjectSet(sObjName, OBJPROP_PRICE2, dPriceLow - iOffSet*Point);
ObjectSet(sObjName, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet(sObjName, OBJPROP_COLOR, cObjColor);
ObjectSet(sObjName, OBJPROP_WIDTH, 2);
ObjectSet(sObjName, OBJPROP_BACK, background);
}
}
//+------------------------------------------------------------------+
//| Decrement Date to draw objects in the past |
//+------------------------------------------------------------------+
datetime decrementTradeDate (datetime dtTimeDate) {
int iTimeYear=TimeYear(dtTimeDate);
int iTimeMonth=TimeMonth(dtTimeDate);
int iTimeDay=TimeDay(dtTimeDate);
int iTimeHour=TimeHour(dtTimeDate);
int iTimeMinute=TimeMinute(dtTimeDate);
iTimeDay--;
if (iTimeDay==0) {
iTimeMonth--;
if (iTimeMonth==0) {
iTimeYear--;
iTimeMonth=12;
}
// Thirty days hath September...
if (iTimeMonth==4 || iTimeMonth==6 || iTimeMonth==9 || iTimeMonth==11) iTimeDay=30;
// ...all the rest have thirty-one...
if (iTimeMonth==1 || iTimeMonth==3 || iTimeMonth==5 || iTimeMonth==7 || iTimeMonth==8 || iTimeMonth==10 || iTimeMonth==12) iTimeDay=31;
// ...except...
if (iTimeMonth==2) if (MathMod(iTimeYear, 4)==0) iTimeDay=29; else iTimeDay=28;
}
return(StrToTime(iTimeYear + "." + iTimeMonth + "." + iTimeDay + " " + iTimeHour + ":" + iTimeMinute));
}
//+------------------------------------------------------------------+
//
//
//
/*
//+------------------------------------------------------------------+
//| times.mq4 |
//| |
//| Made/Modified by sh _j . |
//+------------------------------------------------------------------+
#property copyright "Morning Star"
#property link "http://Grand Forex.ir"
#property indicator_chart_window
extern int NumberOfDays = 50;
extern string AsiaBegin = "01:00";
extern string AsiaEnd = "09:00";
extern color AsiaColor = Red;
extern string EurBegin = "09:00";
extern string EurEnd = "16:00";
extern color EurColor = Blue;
extern string USABegin = "16:00";
extern string USAEnd = "23:00";
extern color USAColor = Tan;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
void init() {
DeleteObjects();
for (int i=0; i<NumberOfDays; i++) {
CreateObjects("AS"+i, AsiaColor);
CreateObjects("EU"+i, EurColor);
CreateObjects("US"+i, USAColor);
}
Comment("");
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function |
//+------------------------------------------------------------------+
void deinit() {
DeleteObjects();
Comment("");
}
void CreateObjects(string no, color cl) {
ObjectCreate(no, OBJ_RECTANGLE, 0, 0,0, 0,0);
ObjectSet(no, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet(no, OBJPROP_COLOR, cl);
ObjectSet(no, OBJPROP_BACK, True);
}
//+------------------------------------------------------------------+
//| Óäàëåíèå îáúåêòîâ èíäèêàòîðà |
//+------------------------------------------------------------------+
void DeleteObjects() {
for (int i=0; i<NumberOfDays; i++) {
ObjectDelete("AS"+i);
ObjectDelete("EU"+i);
ObjectDelete("US"+i);
}
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
void start() {
datetime dt=CurTime();
for (int i=0; i<NumberOfDays; i++) {
DrawObjects(dt, "AS"+i, AsiaBegin, AsiaEnd);
DrawObjects(dt, "EU"+i, EurBegin, EurEnd);
DrawObjects(dt, "US"+i, USABegin, USAEnd);
dt=decDateTradeDay(dt);
while (TimeDayOfWeek(dt)>5) dt=decDateTradeDay(dt);
}
}
void DrawObjects(datetime dt, string no, string tb, string te) {
datetime t1, t2;
double p1, p2;
int b1, b2;
t1=StrToTime(TimeToStr(dt, TIME_DATE)+" "+tb);
t2=StrToTime(TimeToStr(dt, TIME_DATE)+" "+te);
b1=iBarShift(NULL, 0, t1);
b2=iBarShift(NULL, 0, t2);
p1=High[Highest(NULL, 0, MODE_HIGH, b1-b2, b2)];
p2=Low [Lowest (NULL, 0, MODE_LOW , b1-b2, b2)];
ObjectSet(no, OBJPROP_TIME1 , t1);
ObjectSet(no, OBJPROP_PRICE1, p1);
ObjectSet(no, OBJPROP_TIME2 , t2);
ObjectSet(no, OBJPROP_PRICE2, p2);
}
datetime decDateTradeDay (datetime dt) {
int ty=TimeYear(dt);
int tm=TimeMonth(dt);
int td=TimeDay(dt);
int th=TimeHour(dt);
int ti=TimeMinute(dt);
td--;
if (td==0) {
tm--;
if (tm==0) {
ty--;
tm=12;
}
if (tm==1 || tm==3 || tm==5 || tm==7 || tm==8 || tm==10 || tm==12) td=31;
if (tm==2) if (MathMod(ty, 4)==0) td=29; else td=28;
if (tm==4 || tm==6 || tm==9 || tm==11) td=30;
}
return(StrToTime(ty+"."+tm+"."+td+" "+th+":"+ti));
}
//+------------------------------------------------------------------+
*/
Comments