0

My objective is to create a rectangle object on a chart that measures from the highest high and lowest low between a specified time frame and for an X amount of days?

a sample ScreenView

I know how to create an object to a chart but I'm not sure how I can make it repeat for an X amount of days back. How can I achieve this? I was thinking maybe a For loop would be a good approach?I could use some guidance.

user3666197
  • 1
  • 6
  • 50
  • 92
Gerald
  • 21
  • 1
  • 3
  • Would be fair, Gerald, to post a sketch of the result you would like to have on screen. Post a link to such illustration and I can upload that into your post, as your initial [reputation]-score does not allow you to post Fig(s) directly, ok? – user3666197 May 31 '15 at 08:38
  • Here is my sketch: https://drive.google.com/file/d/0B5qYCIRe_Vz_MkU3WkNiNTl4U0k/view?usp=sharing – Gerald May 31 '15 at 18:42
  • Great move, Gerald. Fig. included ( next rather save as `PNG` ( `P`-ortable is worth it's meaning ) , StackOverflow rejects some otherwise common formats ( be it due to licensing or royalties issues - it simply rejects, who cares why? ). So, questions come: your base chart is an M15 one, while your GreenBoxOBJECTs span 8-bars, **[Q1]** do you aim at a synthetic super-TimeFrame of H2 or was that an un-intentional? **[Q2]** Is the `X` in this case `== 4` as noted above? **[Q3]** How do you state the GreenBoxOBJECT starting DateTime? It looks as if derived from the 1st retrospective day - was it? – user3666197 May 31 '15 at 21:18
  • I just happened to use the M15 chart just to show more examples of what I was looking for. As for a time frame in this example I used 05:00 to 07:00. I would like an Extern option for designated time frames. Within the time frame I want the highest high and lowest low. This should be the ranges for the rectangle box. I would like if the box could possibly be drawn in real time once the last time frame is true. Also if the box could be drawn for an X amount of days back show in the photo. – Gerald Jun 01 '15 at 00:24

2 Answers2

1

Try this code (Expert Advisor). Ok, it is not efficient (as it recalculate every tick), but I it demonstrates the concept pretty well. enter image description here

and here's the code for it:

//+------------------------------------------------------------------+
//|                                            GeraldHighLowV0R1.mq4 |
//|               Copyright 2015, joseph.lee @ fs [dot] com [dot] my |
//|                                            http://www.fs.com.my/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, joseph.lee @ fs [dot] com [dot] my"
#property link      "http://www.fs.com.my/"
#property version   "1.00"
#property strict

extern int      viTimeOfDayStartHour    =  3;
extern int      viTimeOfDayEndHour      =  9;
extern int      viDaysToDraw            = 10;


void OnTick() {
    string      vsGlobalDebug           = "";
    datetime    vdCurrentDayStart       = iTime(Symbol(), PERIOD_D1, 0);    //Get Broker Today DateTime as of Midnight

    ObjectsDeleteAll();
    //---------------------------------------------------------------
    //Process [viDaysToDraw] number of days (**Sat/Sun is included)
    //---------------------------------------------------------------
    for(int viDay=0; viDay<viDaysToDraw; viDay++) {
        datetime vdDateOfSection        = vdCurrentDayStart-(viDay*PERIOD_D1*60);                       //Get Section Midnight DateTime
        datetime    vdSectionStart      = vdDateOfSection + (viTimeOfDayStartHour*PERIOD_H1*60);        //Add Hours to Mark start of section
        datetime    vdSectionEnd        = vdDateOfSection + (viTimeOfDayEndHour  *PERIOD_H1*60);        //Add Hours to mark End of section

        //----------------------------------------------------------------------
        //Calculate the number of bars between (inclusive) Start and End time
        //----------------------------------------------------------------------
        int     viSectionEndBarIndex         = iBarShift(Symbol(), PERIOD_CURRENT, vdSectionEnd,false);
        int     viSectionStartBarIndex       = iBarShift(Symbol(), PERIOD_CURRENT, vdSectionStart,false);
        int     viBarCountBtwStartAndEndHour = viSectionStartBarIndex-viSectionEndBarIndex+1;
        //-----------------------------------------------------------------

        //-----------------------------------------------------------------
        //Find the Highest/Lowest Bar index within the Day Section
        //-----------------------------------------------------------------
        int     viSectionHighestBar     = iHighest(Symbol(), PERIOD_CURRENT, MODE_HIGH, viBarCountBtwStartAndEndHour, viSectionEndBarIndex);
        int     viSectionLowestBar      = iLowest(Symbol(), PERIOD_CURRENT, MODE_LOW, viBarCountBtwStartAndEndHour, viSectionEndBarIndex);
        //-----------------------------------------------------------------

        //-----------------------------------------------------------------
        //Find the Highest/Lowest Price within the Day Section
        //-----------------------------------------------------------------
        double  viSectionHighestPrice   = iHigh(Symbol(), PERIOD_CURRENT, viSectionHighestBar);
        double  viSectionLowestPrice    = iLow( Symbol(), PERIOD_CURRENT, viSectionLowestBar);
        //-----------------------------------------------------------------

        //-----------------------------------------------------------------
        //Add Verbose/Debug Info for display
        //-----------------------------------------------------------------
        StringAdd(
            vsGlobalDebug, "\n[Day" + IntegerToString(viDay) + "]: "
                + "Start: "     + TimeToString(vdSectionStart)
                + ", Lowest: "  + DoubleToString(viSectionLowestPrice,Digits)
                + ", End: "     + TimeToString(vdSectionEnd)
                + ", Highest: " + DoubleToString(viSectionHighestPrice,Digits));
        //-----------------------------------------------------------------

        //-----------------------------------------------------------------
        //Crete Rectangle Object for the Day section
        //-----------------------------------------------------------------
        string  vsObjName   = "HLDay" + IntegerToString(viDay);
        ObjectCreate(0, vsObjName, OBJ_RECTANGLE, 0, vdSectionStart, viSectionLowestPrice, vdSectionEnd, viSectionHighestPrice);
        ObjectSetInteger(0, vsObjName, OBJPROP_COLOR, clrDarkGreen);
        ObjectSetInteger(0, vsObjName, OBJPROP_WIDTH, 0);
        ObjectSetInteger(0, vsObjName, OBJPROP_BACK, true);
        ObjectSetInteger(0, vsObjName, OBJPROP_SELECTABLE, false);
        //-----------------------------------------------------------------
    }
    ChartRedraw();

    //-----------------------------------------------------------------
    // Show Debug/Verbose Info
    //-----------------------------------------------------------------
    Comment("\n" + vsGlobalDebug );
}
jlee88my
  • 2,935
  • 21
  • 28
  • Thank you both for the help, much appreciated. – Gerald Jun 11 '15 at 00:14
  • Please would you take a look at this question for me https://stackoverflow.com/questions/53397898/how-can-i-write-an-mt4-indicator-that-draws-a-rectangle-and-horizontal-lines-ove – hutfelt Nov 21 '18 at 05:02
  • I realised that this solves part of my question. How can I solve the remainder and convert this to an indicator? – hutfelt Nov 21 '18 at 05:09
0

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 MVC-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 (Man-Machine-Interface) 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 );
             }
        }
    }
user3666197
  • 1
  • 6
  • 50
  • 92