Issues correctly positioning arrows on chart

 

hey :)

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 wjere the EA is loaded thr 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 followig 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






Files:
 

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
 

@ffoor

thank you for your reply. that's a great idea using the ATR.


@Marco vd Heijden

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 @Marco vd Heijden 

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;
}
 

@nicholi shen

awesome :) thanks a lot, I will test it out...

 

alright, sorry for the late response.

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

@ffoorr

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