Files
2026-06-08 10:36:15 +02:00

254 lines
9.7 KiB
Plaintext

//+------------------------------------------------------------------+
//| DAILY RANGE BREAKOUT EA.mq5 |
//| Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
double maximum_price = -DBL_MAX;
double minimum_price = +DBL_MAX;
datetime maximum_time, minimum_time;
bool isHaveDailyRange_Prices = false;
bool isHaveDailyRange_Break = false;
#define RECTANGLE_PREFIX "RANGE RECTANGLE "
#define UPPER_LINE_PREFIX "UPPER LINE"
#define LOWER_LINE_PREFIX "LOWER LINE"
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit(){
//---
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick(){
//---
static datetime midnight = iTime(_Symbol,PERIOD_D1,0);
static datetime sixAM = midnight + 6 * 3600;
static datetime scanBarTime = sixAM + 1 * PeriodSeconds(_Period); // next bar
static datetime validBreakTime_start = scanBarTime;
static datetime validBreakTime_end = midnight + (6+5) * 3600; // 11 AM
//Print("END TIME = ",validBreakTime_end);
//Print("Midnight T = ",midnight,", 6 AM = ",sixAM,", SCAN BAT T = ",scanBarTime);
if (isNewDay()){
midnight = iTime(_Symbol,PERIOD_D1,0);
sixAM = midnight + 6 * 3600;
scanBarTime = sixAM + 1 * PeriodSeconds(_Period); // next bar
validBreakTime_start = scanBarTime;
validBreakTime_end = midnight + (6+5) * 3600; // 11 AM
maximum_price = -DBL_MAX;
minimum_price = +DBL_MAX;
isHaveDailyRange_Prices = false;
isHaveDailyRange_Break = false;
}
if (isNewBar()){
datetime currentBarTime = iTime(_Symbol,_Period,0);
if (currentBarTime == scanBarTime && !isHaveDailyRange_Prices){
Print("WE HAVE ENOUGH BARS DATA FOR DOCUMENTATION. MAKE THE DATA EXTRACTION NOW");
int total_bars = int((sixAM - midnight)/PeriodSeconds(_Period))+1;
Print("Total bars for scan = ",total_bars);
int highest_price_bar_index = -1;
int lowest_price_bar_index = -1;
for (int i=1; i<=total_bars; i++){
double open_i = open(i);
double close_i = close(i);
double highest_price_i = (open_i > close_i) ? open_i : close_i;
double lowest_price_i = (open_i < close_i) ? open_i : close_i;
if (highest_price_i > maximum_price){
maximum_price = highest_price_i;
highest_price_bar_index = i;
maximum_time = time(i);
}
if (lowest_price_i < minimum_price){
minimum_price = lowest_price_i;
lowest_price_bar_index = i;
minimum_time = time(i);
}
}
Print("Maximum Price = ",maximum_price,", Bar Index = ",highest_price_bar_index,", Time = ",maximum_time);
Print("Minimum Price = ",minimum_price,", Bar Index = ",lowest_price_bar_index,", Time = ",minimum_time);
create_Rectangle(RECTANGLE_PREFIX+TimeToString(maximum_time),maximum_time,maximum_price,minimum_time,minimum_price,clrBlue);
create_Line(UPPER_LINE_PREFIX+TimeToString(midnight),midnight,maximum_price,sixAM,maximum_price,3,clrBlack,DoubleToString(maximum_price,_Digits));
create_Line(LOWER_LINE_PREFIX+TimeToString(midnight),midnight,minimum_price,sixAM,minimum_price,3,clrRed,DoubleToString(minimum_price,_Digits));
isHaveDailyRange_Prices = true;
}
}
double barClose = close(1);
datetime barTime = time(1);
if (barClose > maximum_price && isHaveDailyRange_Prices && !isHaveDailyRange_Break
&& barTime >= validBreakTime_start && barTime <= validBreakTime_end
){
Print("CLOSE Price broke the HIGH range. ",barClose," > ",maximum_price);
isHaveDailyRange_Break = true;
drawBreakPoint(TimeToString(barTime),barTime,barClose,234,clrBlack,-1);
}
else if (barClose < minimum_price && isHaveDailyRange_Prices && !isHaveDailyRange_Break
&& barTime >= validBreakTime_start && barTime <= validBreakTime_end
){
Print("CLOSE Price broke the LOW range. ",barClose," < ",minimum_price);
isHaveDailyRange_Break = true;
drawBreakPoint(TimeToString(barTime),barTime,barClose,233,clrBlue,+1);
}
}
//+------------------------------------------------------------------+
double open(int index){return (iOpen(_Symbol,_Period,index));}
double high(int index){return (iHigh(_Symbol,_Period,index));}
double low(int index){return (iLow(_Symbol,_Period,index));}
double close(int index){return (iClose(_Symbol,_Period,index));}
datetime time(int index){return (iTime(_Symbol,_Period,index));}
bool isNewBar(){
static int prevbars = 0;
int currbars = iBars(_Symbol,_Period);
if (prevbars == currbars) return (false);
prevbars = currbars;
return (true);
}
void create_Rectangle(string objName,datetime time1,double price1,
datetime time2,double price2,color clr){
if (ObjectFind(0,objName) < 0){
ObjectCreate(0,objName,OBJ_RECTANGLE,0,time1,price1,time2,price2);
ObjectSetInteger(0,objName,OBJPROP_TIME,0,time1);
ObjectSetDouble(0,objName,OBJPROP_PRICE,0,price1);
ObjectSetInteger(0,objName,OBJPROP_TIME,1,time2);
ObjectSetDouble(0,objName,OBJPROP_PRICE,1,price2);
ObjectSetInteger(0,objName,OBJPROP_FILL,true);
ObjectSetInteger(0,objName,OBJPROP_COLOR,clr);
ObjectSetInteger(0,objName,OBJPROP_BACK,false);
ChartRedraw(0);
}
}
bool isNewDay(){
bool newDay = false;
MqlDateTime str_datetime;
TimeToStruct(TimeCurrent(), str_datetime);
static int prevday = 0;
int currday = str_datetime.day;
if (prevday == currday){// we are still in current day
newDay = false;
}
else if (prevday != currday){// we have a new day
Print("WE HAVE A NEW DAY WITH DATE ",currday);
prevday = currday;
newDay = true;
}
return (newDay);
}
void create_Line(string objName,datetime time1,double price1,
datetime time2,double price2,int width,color clr,string text){
if (ObjectFind(0,objName) < 0){
ObjectCreate(0,objName,OBJ_TREND,0,time1,price1,time2,price2);
ObjectSetInteger(0,objName,OBJPROP_TIME,0,time1);
ObjectSetDouble(0,objName,OBJPROP_PRICE,0,price1);
ObjectSetInteger(0,objName,OBJPROP_TIME,1,time2);
ObjectSetDouble(0,objName,OBJPROP_PRICE,1,price2);
ObjectSetInteger(0,objName,OBJPROP_WIDTH,width);
ObjectSetInteger(0,objName,OBJPROP_COLOR,clr);
ObjectSetInteger(0,objName,OBJPROP_BACK,false);
long scale = 0;
if (!ChartGetInteger(0,CHART_SCALE,0,scale)){
Print("UNABLE TO GET THE CHART SCALE. DEFAULT VALUE OF ",scale," IS CONSIDERED.");
}
int fontsize = 11;
// 0=minimized, 5 = maximized
if (scale==0){fontsize=5;}
else if (scale==1){fontsize=6;}
else if (scale==2){fontsize=7;}
else if (scale==3){fontsize=9;}
else if (scale==4){fontsize=11;}
else if (scale==5){fontsize=13;}
string txt = " Right Price";
string objNameDescr = objName + txt;
ObjectCreate(0,objNameDescr,OBJ_TEXT,0,time2,price2);
ObjectSetInteger(0,objNameDescr,OBJPROP_COLOR,clr);
ObjectSetInteger(0,objNameDescr,OBJPROP_FONTSIZE,fontsize);
ObjectSetInteger(0,objNameDescr,OBJPROP_ANCHOR,ANCHOR_LEFT);
ObjectSetString(0,objNameDescr,OBJPROP_TEXT, " " + text);
ObjectSetString(0,objNameDescr,OBJPROP_FONT,"Calibri");
ChartRedraw(0);
}
}
void drawBreakPoint(string objName,datetime time,double price,int arrCode,
color clr,int direction){
if (ObjectFind(0,objName) < 0){
ObjectCreate(0,objName,OBJ_ARROW,0,time,price);
ObjectSetInteger(0,objName,OBJPROP_ARROWCODE,arrCode);
ObjectSetInteger(0,objName,OBJPROP_COLOR,clr);
ObjectSetInteger(0,objName,OBJPROP_FONTSIZE,12);
if (direction > 0) ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_TOP);
if (direction < 0) ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_BOTTOM);
string txt = " Breakout";
string objNameDescr = objName + txt;
ObjectCreate(0,objNameDescr,OBJ_TEXT,0,time,price);
ObjectSetInteger(0,objNameDescr,OBJPROP_COLOR,clr);
ObjectSetInteger(0,objNameDescr,OBJPROP_FONTSIZE,12);
if (direction > 0) {
ObjectSetInteger(0,objNameDescr,OBJPROP_ANCHOR,ANCHOR_LEFT_UPPER);
ObjectSetString(0,objNameDescr,OBJPROP_TEXT, " " + txt);
}
if (direction < 0) {
ObjectSetInteger(0,objNameDescr,OBJPROP_ANCHOR,ANCHOR_LEFT_LOWER);
ObjectSetString(0,objNameDescr,OBJPROP_TEXT, " " + txt);
}
}
ChartRedraw(0);
}