How to correctly position arrows on chart

hey :slight_smile:

I have an EA that creates signals for possible buy/sell entries by placing an arrow above/under the signal candle.

my issue is, that depending on the chart where the EA is loaded the arrows are placed too far away or too closely.

please review attached images for examples.

In case of a sell signal I want to position the arrow 20 pips above the High of the signal candle

and in case of a buy to place the arrow 20 pips below the Low of the signal candle.

I’m using following approach for positioning:

// arrow creation
   ObjectCreate(0, label_name, OBJ_TEXT, 0, 0, 0);
   ObjectSet(label_name, OBJPROP_TIME1, some_time);
   ObjectSet(label_name, OBJPROP_PRICE1, price_arr); // calculated price with 20 pips added or subtracted depending on sell/buy
// price calculation

   // get digits to correctly add pips
   double digs = 1 / MathPow(10, Digits-1);
   int num_pips = 20;

   // arrow price calculation
   double price_arr = (type==SYMBOL_ARROWUP) ? iLow(Symbol(), time_frame, 1)-(num_pips*digs) 
                     : iHigh(Symbol(), time_frame, 1)+(num_pips*digs);

as you can see for instance in de30-too-narrow.jpg the arrow sits too closely while in xauusd the distance is correct.

I just can’t figure it out. tried to incorporate tick_value as well but obviously wrongly.

Can anybody help, please?

thanks in advance

Use ATR

double atr = iATR(NULL,0,10,i);

signal_up = low[i] - 0.5*atr

instead of

+(num_pips*digs)

You can try to use

High+X*_Point
Low-X*_Point

@sodowd1i
thank you for your reply. that’s a great idea using the ATR.

@lpaddie1j
many thanks, this almost solved the issue as it seems.

now I’m only having issues with DE30 and US30

with these two pairs the distances remain all too narrow still(arrows almost sit on candles).

the strange thing is, in AUXUSD (2-digits) the distances are correct while

in DE30, US30 they are not, allthough they as well have 2 digits only.

I don’t see the logic behind to generically compute the distances corretly for any pair.

any ideas are highly appreciated

currently I only see this isssue for DE30 and US30 but probably exists on other pairs as well,

that I’m currently not aware of.

I need a true generic solution for that so that the user might pick any possible chart

and see correct placements

Thanks to @lpaddie1j

My best solution:

// for DE30 and US30 multiply by 1/tick_value for (hopefully) correct solution  
   double scale_factor = (_Digits==2 && MarketInfo(Symbol(), MODE_TICKVALUE) <= 0.01) 
      ? 1/MarketInfo(Symbol(), MODE_TICKVALUE) : 1.0;

   // realized that in higher TFs the distances are too narrow as well
   scale_factor *= (time_frame >= PERIOD_H4) ? 10 : 1;

  // determine signal price locations for arrow and label
   double price_label = 
         (type==SYMBOL_ARROWUP) ? iLow(Symbol(), time_frame, 1) - (scale_factor*200*_Point) 
                     : iHigh(Symbol(), time_frame, 1) + (scale_factor*200*_Point);
   double price_arr = (type==SYMBOL_ARROWUP) ? iLow(Symbol(), time_frame, 1)-(scale_factor*80*_Point) 
                     : iHigh(Symbol(), time_frame, 1)+(scale_factor*80*_Point);

as the tick value is the only thing where the pairs differ it must be somehow integrated into the calculation.

at least this produces acceptable results.

Here’s another option. You’d need to use OnChartEvent to rewrite the buffers when the chart scale changes, but this should give you a consistent gap in pixels…

double scale_factor(int pixels)
{
   int chart_height = (int)ChartGetInteger(ChartID(), CHART_HEIGHT_IN_PIXELS);
   double chart_range = (
      ChartGetDouble(ChartID(), CHART_PRICE_MAX) - ChartGetDouble(ChartID(), CHART_PRICE_MIN)
   );
   return chart_range / chart_height * pixels;
}

I tested it out and it seems, or at least for my demands, the suggestion from

works best and is most easy and scalable.

thank you all though for your contributions which solved my issue 100%.

so my final solution for positioning the arrows is:

// either up or down 
double a_type = SYMBOL_ARROWUP;
// extra space for label
double label_factor = 1.25;
// raw ATR value
double atr_points = iATR(Symbol(), time_frame, period, candle_idx);
// arrow price-position below-low above-high 
double price_arr = (a_type==SYMBOL_ARROWUP) 
                        ? NormalizeDouble(iLow(Symbol(), time_frame, candle_idx) - atr_points, Digits)  
                        : NormalizeDouble(iHigh(Symbol(), time_frame, candle_idx) + atr_points, Digits);

// lable price-position below low-arrow above high-arrow 
double label_arr = (a_type==SYMBOL_ARROWUP) 
                        ? NormalizeDouble(iLow(Symbol(), time_frame, candle_idx) - (label_factor * atr_points), Digits)  
                        : NormalizeDouble(iHigh(Symbol(), time_frame, candle_idx) + (label_factor * atr_points), Digits);

// for adding the actual arrows to the chart -> see 1st post