Terminology confusion avoidance
TimeFRAME is an industry-wide accepted term for a "time-based-framing" of market event flow and has for decades standardized such meaning.
Due to weekend-related gaps in a flow of natural time and due to the nature of the Task Definition above, there happens to be indeed many TimeFRAME-related operations on several TimeFRAME layers in parallel in the code-snippet below ( incl. PERIOD_D1
, PERIOD_H1
and hiding a PERIOD_CURRENT
dependency ( unknown (implicit), so was avoided to be used at all ) ) so as to allow pointer counting and back-stepping index updates ( ^PTR->TimeSERIES ).
So let's rather use another term for aGreenBOX under your given Task Definition throughout the further development and call aTimeDOMAIN-bound attributes differently -- aTimeWINDOW & al ( but not TimeFRAME, ok? )
Parametrisation
The simplest form would use the below stated set of extern
-s. It is worth to note, that extern
constructors are dangerous in case your GUI-layer application goes smarter and complex and in case it directly interfaces into XTOs ( eXecute-Trade-Operation(s) ).
#property strict
extern int aGreenBoxWindow_HOUR__ENDs = 7; // aTimeWINDOW.ends <<- 05:00 - 07:00 [GMT-ABCD]
extern int aGreenBoxWindow_HOURs_WIDE = 2; // aTimeWINDOW.width
extern int aGreenBoxWindow_nDAYs_BACK = 4; // aTimeWINDOW.repeatDays
int aCallLockPTR = 0;
string anObjNamePREFIX = "aGreenBOX.id=";
Warning
For real-time augmented trading services, based on MT4, where XTO operations are automatically bound / hooked to some GUI-layer elements ( a Visual-part of the M
V
C
-triade ), the extern
constructor-bound variables have to be rather avoided, as any change in their value ( due to MT4 architecture design ) causes a reset & non-re-entrant collision in both your **Model & Controller part of the real-time augmented service(s) and such trading service would be lethally dangerous to use and XTO.
Augmented Trading Services' Parametrisation without extern
-s
For the sake of real-time operated augmented Trading service, there are way better ( and safer ) ways how to avoid extern
's devastating impact on a running service. Besides others I love most using the process-to-process / distributed-computing messaging, that principally makes your MT4-Terminal a node inside a private cloud-based trading infrastructure and your MQL4
-based EA starts to play inside a Symphonic orchestra, together with other orchestrated instruments ( be it an AI/ML-NeuralNetwork decision making computation process, be that a GPU-based covariance-matrix evaluator for portfolio optimization quant model, simply put, anything like this can "direct" / "command" an MQL4
-process "inside" MT4-Terminal in a smooth, un-interrupted & real-time, non-blocking, fully asynchronous manner, doesn't that sound attractive? Yes, it does! View this once going to about 1 [ms] and less
A trivial solution - an example of a CPU-effective low-PRIO aproach
Once you step into UI-design territory, your ( initially hidden ) issue is called UI control-loop and the overall UI-responsiveness ( how fast the UI moves in response to both your MMI
(M
an-M
achine-I
nterface) and external stream of "inputs" ( a mouse-click / a mouse-movement / mouse-drag-&-drop / aMarketEVENT / et al ).
A reasonable policing is necessary to be put in place so as to avoid un-efficient calls on repetitive tasks, that do not bring anything new to the XTO/MVC-prioritised / MVC-deferred-Visual-part redraw operations.
With all due respect to Joseph's proposal to hang the UI-process directly as an OnTick()
blocking-task to each TickArrivalEVENT
is possible in principle, however is both lethally dangerous in production grade software for XTO and also CPU/memory-access/db.POOL resources' wasting processing power ( needed typically for other tasks )
int init(){
// ------------------------------------------- // ------------------------
aGreenBoxWINDOWs_Update(); // .init
aCallLockPTR = iBars( NULL, PERIOD_H1 ); // .set a CPU-clock saving LOCK
// ------------------------------------------- // ------------------------
}
int start(){
// ------------------------------------------- // -----------------
// HIGH-PRIORITY OPERATIONS
// ...
// ..
// .
// ||||||||||||||||||||||||||||||||||||||||||| // |||||||||||||||||
if ( iBars( NULL, PERIOD_H1 ) // .TEST
!= aCallLockPTR
){
aGreenBoxWINDOWs_UpdateJusTheLiveOne(); // .UPD GUI
aCallLockPTR = iBars( NULL, PERIOD_H1 ); // .SET PTR
}
else {// ///////////////////////////////////// // .UPD GUI in .id=1
// in case LowestLow or HighestHigh inside the Live part of
// aGreenBOX "aGreenBOX.id=1"
// was moved:
// aGreenBoxWINDOW_UpdateJustTheLiveOne();
// re-lock Hi/Lo_LOCKs // .UPD LOCKs
}
}
aGreenBOX magic for re-enforced Visual MVC-part
void aGreenBoxWINDOWs_Update(){
int static aGreenBoxWindow_Duration_SECs = aGreenBoxWindow_HOURs_WIDE
* PeriodSeconds( PERIOD_H1 );
int aGreenBoxWindow_H1Offset_ENDs = TimeHour( TimeCurrent() )
- aGreenBoxWindow_HOUR__ENDs;
if ( aGreenBoxWindow_H1Offset_ENDs < 0 ){
aGreenBoxWindow_H1Offset_ENDs+= 24;
}
datetime aGreenBoxWindow_DATETIME_ENDs = iTime( NULL,
PERIOD_D1,
0
)
+ aGreenBoxWindow_HOUR__ENDs
* PeriodSeconds( PERIOD_H1 );
if ( aGreenBoxWindow_DATETIME_ENDs
- aGreenBoxWindow_Duration_SECs > iTime( NULL,
PERIOD_H1,
0
)
){
aGreenBoxWindow_DATETIME_ENDs = iTime( NULL,
PERIOD_D1,
1
)
+ aGreenBoxWindow_HOUR__END
* PeriodSeconds( PERIOD_H1 );
}
for (
//----------------------------------------------- // --------------------
int anObjIDX = 1, // loop-pre-setting(s)
string anObjNAME = anObjNamePREFIX + "1", // var(s)=value(s) ( life-span only "inside" for(){...}-constructor in MQL4.5+ ...)
int anObjENDs = aGreenBoxWindow_DATETIME_ENDs;
//----------------------------------------------- // --------------------
anObjIDX <= aGreenBoxWindow_nDAYs_BACK; // loop-pre-condition
//----------------------------------------------- // --------------------
// loop-post-update(s)
anObjIDX++, // IDX
anObjNAME = anObjNamePREFIX + anObjIDX, // NAME
anObjENDs = iTime( NULL, // ENDs
PERIOD_D1,
anObjIDX
)
+ PeriodSeconds( PERIOD_H1 )
* aGreenBoxWindow_HOUR__ENDs,
aGreenBoxWindow_H1Offset_ENDs+= 24 // ENDs ^H1
//----------------------------------------------- // --------------------
){ // loop-body:
if ( ObjectFind( anObjNAME ) < 0 ){ // !found .ADD
ObjectCreate( anObjNAME, OBJ_RECTANGLE, 0,
aGreenBoxWindow_DATETIME_ENDs,
iHigh( NULL,
PERIOD_H1,
iHighest( NULL,
PERIOD_H1,
MODE_HIGH,
aGreenBoxWindow_HOURs_WIDE,
aGreenBoxWindow_H1Offset_ENDs
)
),
aGreenBoxWindow_DATETIME_ENDs
- aGreenBoxWindow_Duration_SECs,
iLow( NULL,
PERIOD_H1,
iLowest( NULL,
PERIOD_H1,
MODE_LOW,
aGreenBoxWindow_HOURs_WIDE,
aGreenBoxWindow_H1Offset_ENDs
)
)
);
ObjectSet( anObjNAME, OBJPROP_COLOR, DarkGreen );
ObjectSet( anObjNAME, OBJPROP_BACK, True );
}
else { // found .UPD
ObjectMove( anObjNAME, 0,
aGreenBoxWindow_DATETIME_ENDs,
iHigh( NULL,
PERIOD_H1,
iHighest( NULL,
PERIOD_H1,
MODE_HIGH,
aGreenBoxWindow_HOURs_WIDE,
aGreenBoxWindow_H1Offset_ENDs
)
)
);
ObjectMove( anObjNAME, 1,
aGreenBoxWindow_DATETIME_ENDs
- aGreenBoxWindow_Duration_SECs,
iLow( NULL,
PERIOD_H1,
iLowest( NULL,
PERIOD_H1,
MODE_LOW,
aGreenBoxWindow_HOURs_WIDE,
aGreenBoxWindow_H1Offset_ENDs
)
)
);
ObjectSet( anObjNAME, OBJPROP_COLOR, DarkGreen );
ObjectSet( anObjNAME, OBJPROP_BACK, True );
}
}
}