Help with array and object delete

 
Hi everyone! I'm trying to create an indicator that identifies some price zones that interest me. I was able to create it perfectly and the logic works, the only problem is that I would like to eliminate the price zones that are invalidated (ie exceeded) but it is proving very difficult for me. I've tried saving the values of the object in an array, and then comparing them to the prices, but no luck. What I also don't understand is that if for example I try to screen print the value of the array, I succeed in the function, but if I try in oncalculate it always returns zero.
Thanks to whoever can help me!

double    rectangleLongPrice[100];
double    rectangleShortPrice[100];
double    oldLongZonePrice = 0;
double    oldShortZonePrice = 0;

void CheckZone()
{
    for (int j = 0; j < 100; j++)
    {
        if (ObjectFind("Bullish" + DoubleToStr(j, 0)) != -1)
        {
        double longZonePrice = ObjectGet("Bullish" + DoubleToStr(j, 0), OBJPROP_PRICE2);
        if ( longZonePrice != oldLongZonePrice ) {
        oldLongZonePrice = longZonePrice;
        ArrayFill(rectangleLongPrice,j,1,longZonePrice);
        }
        }
        else if (ObjectFind("Bearish" + DoubleToStr(j, 0)) != -1)
        {
        double shortZonePrice = ObjectGet("Bearish" + DoubleToStr(j, 0), OBJPROP_PRICE1);
        if ( shortZonePrice != oldShortZonePrice ) {
        ArrayFill(rectangleShortPrice,j,1,shortZonePrice);
        }
        }    
    }
}


void DeleteBrokeZone()
{
    for (int j = 0; j < 100; j++)
    {
            if (Close[j + 1] > rectangleLongPrice[j] && Close[j] < rectangleLongPrice[j])
            {
                ObjectDelete("Bullish" + DoubleToStr(j, 0));
            }
            if (Close[j + 1]  < rectangleShortPrice[j] && Close[j]  > rectangleShortPrice[j])
            {
                ObjectDelete("Bearish" + DoubleToStr(j, 0));
            }
        }
    }
 
 if (Close[j + 1] > rectangleLongPrice[j] && Close[j] < rectangleLongPrice[j])            {
                ObjectDelete("Bullish" + DoubleToStr(j, 0));

Do not use series index in object names, as they are not unique. As soon as a new bar starts, you will be trying to create a new name (e.g., “name0”), same, existing, previous, name (e.g., “name0” now on bar one.)

Use time (as int) or a non-series index:

#define  SERIES(I)   (Bars - 1 - I) // As-series to non-series or back.
 
William Roeder # :

Do not use series index in object names , as they are not unique. As soon as a new bar starts, you will be trying to create a new name (e.g., “name0”), same, existing, previous, name (e.g., “name0” now on bar one.)

Use time (as int ) or a non-series index:

Thanks, I tried adding the price of the corresponding bar to the name. Now I've tried another approach, saving the name in the array, then fetching the price with Objectget. With a comment I can see that the name is saved in the array, but when it comes to getting the prices, if I try to print them with a comment they are not exact.. This is the code I use in a while loop inside oncalculate to create the zones and save the name :

       if (isCandleSequenceLong)
        {
        string LongName = "Bullish" + DoubleToString (Low[i + 2 ], 0 );
        ObjectCreate (LongName, OBJ_RECTANGLE , 0 , Time[i + 3 ], High[i + 2 ], EMPTY_VALUE , Low[i + 2 ]);
        ObjectSet(LongName, OBJPROP_COLOR , Lime);
        if (!FillZone)
        ObjectSet(LongName, OBJPROP_BACK , false );
        rectangleLongName[i] = LongName;
        isCandleSequenceLong  = false ;
        }

       if (isCandleSequenceShort)
        {
        string ShortName = "Bearish" + DoubleToString (High[i + 2 ], 0 );
        ObjectCreate (ShortName, OBJ_RECTANGLE , 0 , Time[i + 3 ], High[i + 2 ], EMPTY_VALUE , Low[i + 2 ]);
        ObjectSet(ShortName, OBJPROP_COLOR , Red);
        if (!FillZone)
        ObjectSet(ShortName, OBJPROP_BACK , false );
        rectangleShortName[i] = ShortName;
        isCandleSequenceShort = false ;
        }

And this is the function that should eliminate them  :

 void DeleteBrokeZone()
{
     for ( int j = 0 ; j < ObjectsTotal ()- 1 ; j++)
    {
     double LongPrice = ObjectGet(rectangleLongName[j],OBJPROP_PRICE2);
     double ShortPrice= ObjectGet(rectangleShortName[j],OBJPROP_PRICE1);
     Comment (LongPrice);
             if (Close[j + 1 ] > LongPrice && Close[j] < LongPrice )
            {
                 if (!ObjectDelete (rectangleLongName[j])) Print ( "Error:" + rectangleLongName[j]);
            }
             if (Close[j + 1 ]  < ShortPrice && Close[j]  > ShortPrice)
            {
                 if (!ObjectDelete (rectangleShortName[j])) Print ( "Error:" + rectangleShortName[j]);
            }
        }
    }

The weird thing is that it works in backtest, but not in live! ty

 
Can anyone help me? i am really stuck on this code
 
forextastic #:
Can anyone help me? i am really stuck on this code
I think something essential, not shown in the code you posted is the issue...

Maybe you could debug the code to find out why it is not deleting...

I could imagine you have some logic to only deletee once per candle, that would explain why it is not working on live market.
 
Dominik Christian Egert # :
I think something essential, not shown in the code you posted is the issue...

Maybe you could debug the code to find out why it is not deleting...

I could imagine you have some logic to only deletee once per candle, that would explain why it is not working on live market.

thanks, what's the problem of checking at each new bar ?

I modified the code and now I'm getting some results, that is, even in the live market it eliminates some invalid zones, but unfortunately not all. I can't figure out why some zones that meet the deletion criteria are not deleted...

 if (isCandleSequenceLong)
       {
         static int longcounter  = 1000 ;
         string LongName = "Bullish" + IntegerToString (longcounter, 0 );
         ObjectCreate (LongName, OBJ_RECTANGLE , 0 , Time[i + 3 ], High[i + 2 ], EMPTY_VALUE , Low[i + 2 ]);
        ObjectSet(LongName, OBJPROP_COLOR , Lime);
         if (!FillZone)
           ObjectSet(LongName, OBJPROP_BACK , false );
        rectangleLongName[longArrayCounter] = LongName;
        isCandleSequenceLong  = false ;
        longcounter++;
        longArrayCounter++;
       }

     if (isCandleSequenceShort)
       {
         static int shortcounter = 1000 ;
         string ShortName = "Bearish" + IntegerToString (shortcounter, 0 );
         ObjectCreate (ShortName, OBJ_RECTANGLE , 0 , Time[i + 3 ], High[i + 2 ], EMPTY_VALUE , Low[i + 2 ]);
        ObjectSet(ShortName, OBJPROP_COLOR , Red);
         if (!FillZone)
           ObjectSet(ShortName, OBJPROP_BACK , false );
        rectangleShortName[shortArrayCounter] = ShortName;
        isCandleSequenceShort = false ;
        shortcounter++;
        shortArrayCounter++;
       }

 void DeleteBrokeZone()
{
     for ( int i = 0 ; i < ArraySize (rectangleLongName); i++)
    {
         if ( StringLen (rectangleLongName[i]) > 0 )
        {
             if ( ObjectFind ( NULL , rectangleLongName[i]) != - 1 )
            {
                price1 = ObjectGetDouble ( 0 , rectangleLongName[i], OBJPROP_PRICE1);
                price2 = ObjectGetDouble ( 0 , rectangleLongName[i], OBJPROP_PRICE2);

                 if (Close[i] < price2)
                {
                     if (! ObjectDelete ( 0 , rectangleLongName[i])) {
                         Print ( "Error deleting Long object: " + rectangleLongName[i]);
                        }
                     else 
                         Print ( "Deleted Long object: " + rectangleLongName[i]);
                    rectangleLongName[i] = "" ; 
                    RefreshRates();
                }
            }
        }
    }

     for ( int x = 0 ; x < ArraySize (rectangleShortName); x++)
    {
         if ( StringLen (rectangleShortName[x]) > 0 )
        {
             if ( ObjectFind ( NULL , rectangleShortName[x]) != - 1 )
            {
                price1 = ObjectGetDouble ( 0 , rectangleShortName[x], OBJPROP_PRICE1);
                price2 = ObjectGetDouble ( 0 , rectangleShortName[x], OBJPROP_PRICE2);

                 if (Close[x] > price1)
                {
                     if (! ObjectDelete ( 0 , rectangleShortName[x])) {
                         Print ( "Error deleting Short object: " + rectangleShortName[x]);
                        }
                     else 
                         Print ( "Deleted Short object: " + rectangleShortName[x]);
                    rectangleShortName[x] = "" ; 
                    RefreshRates();
                }
            }
        }
    }
}
 
forextastic #:

thanks, what's the problem of checking at each new bar ?

I modified the code and now I'm getting some results, that is, even in the live market it eliminates some invalid zones, but unfortunately not all. I can't figure out why some zones that meet the deletion criteria are not deleted...

In your first approach, you checked the close price, which is equal to the open price on the first tick of a candle in live markets. The candle forms with time. This is not the case in history data, where the candle is presented as whole.

That's why it didn't work. Now, I looked at your code and would like to give you an advice.

Don't nest so many if() and for() loops. I suggest a max of 2 additional nestings. If possible, try to avoid nesting. It makes code very hard to read and understand.
 
Dominik Christian Egert # :
In your first approach, you checked the close price, which is equal to the open price on the first tick of a candle in live markets. The candle forms with time. This is not the case in history data, where the candle is presented as whole.

That's why it didn't work. Now, I looked at your code and would like to give you an advice.

Don't nest so many if() and for() loops. I suggest a max of 2 additional nestings. If possible, try to avoid nesting. It makes code very hard to read and understand.

Thanks Dominik, I tweaked the if and for loops nestings a bit but that didn't fix the problem sadly, I'm really stuck on this code.

 
forextastic #:

Thanks Dominik, I tweaked the if and for loops nestings a bit but that didn't fix the problem sadly, I'm really stuck on this code.

OK, I have coded it up for you, but you need to figure it out on your own, as I have not checked the code, I just typed it!!!


struct my_zones
{
    double  break_level;
    string  obj_name;
    bool    short_zone;

    my_zones() :
        break_level(0.0),
        obj_name(""),
        short_zone(false)
    { };
};
my_zones    arr_zones[];
int         zone_count      = 0;
int         delete_count    = 0;
int         obj_count       = 0;

int OnCalculate()
{

    // Create zones on chart
    ResetLastError();
    if(isCandleSequenceLong)
    {
        const string obj_name = DrawRectangle("Bullish", Time[i + 3 ], High[i + 2 ], EMPTY_VALUE , Low[i + 2 ], Lime, (!FillZone));
        if( (_LastError != 0)
         || (obj_name == "") )
        { 
            printf("Error drawing object to chart. ErrNo: %i", _LastError); 
            ResetLastError();
        }
        else
        { 
            zone_count = ArrayResize(arr_zones, zone_count + 1, 500);
            arr_zones[zone_count - 1].break_level   = Low[i + 2 ];
            arr_zones[zone_count - 1].obj_name      = obj_name;
            isCandleSequenceLong                    = false;
        }
    }
    
    if(isCandleSequenceShort)
    {
        const string obj_name = DrawRectangle("Bearish", Time[i + 3 ], High[i + 2 ], EMPTY_VALUE , Low[i + 2 ], Red, (!FillZone));
        if( (_LastError != 0)
         || (obj_name == "") )
        { 
            printf("Error drawing object to chart. ErrNo: %i", _LastError); 
            ResetLastError();
        }
        else
        { 
            zone_count = ArrayResize(arr_zones, zone_count + 1, 500);
            arr_zones[zone_count - 1].break_level   = High[i + 2 ];
            arr_zones[zone_count - 1].obj_name      = obj_name;
            arr_zones[zone_count - 1].short_zone    = true;
            isCandleSequenceShort                   = false;
        }
    }


    // Validate zones
        
        CheckZoneBreaking(Close[i]);
}




const string DrawRectangle(const string obj_name, const datetime point_a_t, const double point_a_p, const datetime point_b_t, const double point_b_p, const color obj_color, const bool filled)
{
    const string _obj_name = StringFormat("%s_%i", obj_name, obj_count++);
    bool err = false;

    err = !ObjectCreate(ChartID(), _obj_name, OBJ_RECTANGLE, 0, point_a_t, point_a_p, point_b_t, point_b_p);
    err |= (!err) && !ObjectSetInteger(ChartID(), _obj_name, OBJPROP_COLOR, obj_color);
    err |= (!err) && !ObjectSetInteger(ChartID(), _obj_name, OBJPROP_BACK, filled);

    return((err) ? "" : _obj_name);
}


void CheckZoneBreaking(const double close_price)
{
    // Check all zones
    for(int idx = zone_count - 1; (idx > -1) && !_StopFlag; idx--)
    {
        if( (arr_zones[idx].short_zone)
         && (arr_zones[idx].break_level < close_price) )
        { 
            ObjectDelete(arr_zones[idx].obj_name);
            arr_zones[idx].obj_name     = "";
            arr_zones[idx].break_level  = DBL_MAX;
            delete_count++;
        }
        else if( (!arr_zones[idx].short_zone)
              && (arr_zones[idx].break_level > close_price) )
        {
            ObjectDelete(arr_zones[idx].obj_name);
            arr_zones[idx].obj_name     = "";
            arr_zones[idx].break_level  = 0.0;
            delete_count++;
        }
    }

    // Remove deleted
    if(delete_count > 250)
    {
        int ptr = 0;
        for(int idx = 0; (idx < zone_count) && !_StopFlag; idx++)
        {
            if(arr_zones[idx].obj_name == "")
            { continue; }
            arr_zones[ptr] = arr_zones[idx];
            ptr++;
        }
        delete_count    = 0;
        zone_count      = ArrayResize(arr_zones, ptr, 500);
    }

    // Return    
    return;
}

EDIT:

I fixed a few typos.

EDIT:
And some more typos. Sorry for the inconveniences.
 
Dominik Christian Egert # :

OK, I have coded it up for you, but you need to figure it out on your own, as I have not checked the code, I just typed it!!!


EDIT:

I fixed a few typos.

EDIT:
And some more typos. Sorry for the inconveniences.

Thank you very much, it's a code that I can't understand probably due to inexperience (for example, never used structures), I will study it well and try to implement

Edit : It seems your solution of calling the function passing the Close[i] in oncalculate fixed the problems I had without changing anything else! thanks!!!
 
forextastic #:

Thank you very much, it's a code that I can't understand probably due to inexperience (for example, never used structures), I will study it well and try to implement

Edit : It seems your solution of calling the function passing the Close[i] in oncalculate fixed the problems I had without changing anything else! thanks!!!
So you could use the by me typed code without any changes??


Reason: