ChartXYToTimePrice behaving weird in custom indicator (Mt4 Build 603)

 

Hi guys, I'm testing out on this new chart operation ChartXYToTimePrice() on a custom indicator for the new Mql4. But the price converted from CHARTEVENT_CLICK (x, y coordinates) behaves weirdly. Price converted from screen XY coordinates (obtained from mouse click event) is incorrect & appears to be upside down (chart top lower price ---> chart bottom higher price). Here's my simple test code:

//+------------------------------------------------------------------+
//|                                                    TestClick.mq4 |
//|                                     Copyright 2014, BigFisherman |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014, BigFisherman"
#property indicator_separate_window
#property indicator_minimum 1
#property indicator_maximum 10
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
   
//---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
}
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
//---
   datetime ClickTime = 0;
   double ClickPrice = 0.0;
   int Window = 0;
   int X = (int)lparam;
   int Y = (int)dparam;

   if (id==CHARTEVENT_CLICK){
      bool ConvertXY_Result = ChartXYToTimePrice(0,X,Y,Window,ClickTime,ClickPrice);
      Print("X: "+X+" Y: "+Y+" Window: "+Window+" ClickTime: "+ClickTime+" ClickPrice: "+ClickPrice);
   }   
}
//+------------------------------------------------------------------+

And here's the log generated from some random mouse click (Note "Y" coordinates & "ClickPrice". Smaller Y (Higher chart position) --> Lower ClickPrice ):

2014.02.13 18:47:47.775 TestClick AUDJPY,Daily: X: 367 Y: 21 Window: 0 ClickTime: 1384992000 ClickPrice: 80.43123393
2014.02.13 18:47:44.535 TestClick AUDJPY,Daily: X: 227 Y: 31 Window: 0 ClickTime: 1383004800 ClickPrice: 80.63714653
2014.02.13 18:47:43.335 TestClick AUDJPY,Daily: X: 224 Y: 142 Window: 0 ClickTime: 1383004800 ClickPrice: 82.92277635
2014.02.13 18:47:42.431 TestClick AUDJPY,Daily: X: 227 Y: 247 Window: 0 ClickTime: 1383004800 ClickPrice: 85.08485861
2014.02.13 18:47:41.463 TestClick AUDJPY,Daily: X: 232 Y: 311 Window: 0 ClickTime: 1383091200 ClickPrice: 86.40269923

Any idea what's wrong with my codes or it's some bug? I've read through the help files & forums but found no solutions yet.

Thanks in advance!

 
BigFisherman:

Hi guys, I'm testing out on this new chart operation ChartXYToTimePrice() on a custom indicator for the new Mql4. But the price converted from CHARTEVENT_CLICK (x, y coordinates) behaves weirdly. Price converted from screen XY coordinates (obtained from mouse click event) is incorrect & appears to be upside down (chart top lower price ---> chart bottom higher price). Here's my simple test code:

And here's the log generated from some random mouse click (Note "Y" coordinates & "ClickPrice". Smaller Y (Higher chart position) --> Lower ClickPrice ):

2014.02.13 18:47:47.775 TestClick AUDJPY,Daily: X: 367 Y: 21 Window: 0 ClickTime: 1384992000 ClickPrice: 80.43123393
2014.02.13 18:47:44.535 TestClick AUDJPY,Daily: X: 227 Y: 31 Window: 0 ClickTime: 1383004800 ClickPrice: 80.63714653
2014.02.13 18:47:43.335 TestClick AUDJPY,Daily: X: 224 Y: 142 Window: 0 ClickTime: 1383004800 ClickPrice: 82.92277635
2014.02.13 18:47:42.431 TestClick AUDJPY,Daily: X: 227 Y: 247 Window: 0 ClickTime: 1383004800 ClickPrice: 85.08485861
2014.02.13 18:47:41.463 TestClick AUDJPY,Daily: X: 232 Y: 311 Window: 0 ClickTime: 1383091200 ClickPrice: 86.40269923

Any idea what's wrong with my codes or it's some bug? I've read through the help files & forums but found no solutions yet.

Thanks in advance!

Please submit your findings to the service desk.
 

When placing an object such as a label on the chart, the default anchor corner is 0 (top left)

From your results, it appears that the default corner is 2 (bottom left) for CHARTEVENT_CLICK.

Actually this would make sense as when reading a chart normally, you would expect the x co-ordinate to increase as it moves to the right and the y co-ordinate to increase as it moves from the bottom to the top.

 
ubzen:
Please submit your findings to the service desk.


Submitted #955612
 
GumRai:

When placing an object such as a label on the chart, the default anchor corner is 0 (top left)

From your results, it appears that the default corner is 2 (bottom left) for CHARTEVENT_CLICK.

Actually this would make sense as when reading a chart normally, you would expect the x co-ordinate to increase as it moves to the right and the y co-ordinate to increase as it moves from the bottom to the top.


Yeap, it make more sense for Y=0 to be at chart bottom than current top, but I'm actually fine if it works. Lets see if they get this fix soon.

 
BigFisherman:

Submitted #955612
Fixed
 

@Slava

The bug is still exist. The x is always get 0 value and y converting strange data.

I made some EA that putting HLine and Vline, and as on image can't put lines in place that mouse is. Just when scaling chart to reach more price, the hline is visible and next is again put in top. Similary with vline.

There is similar bug with keystrokes, that not calling some functions for trade, just once time.


 
I can confirm this same bug with ChartXYToTimePrice() on MT4 and mt5. In case that on mt5 keystrokes working corect around repeating events.
 
Robert:
I can confirm this same bug with ChartXYToTimePrice() on MT4 and mt5. In case that on mt5 keystrokes working corect around repeating events.

Seems to be working fine for me. Use this indicator to test. 

#property indicator_chart_window
#include <ChartObjects\ChartObjectsLines.mqh>

CChartObjectHLine g_price;
CChartObjectVLine g_time;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true);
   g_price.Create(0, "price", 0, 0.0);
   g_time.Create(0, "time", 0, 0);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
//---
   string comm = "Press \"x\" key to toggle mouse tracking\n";
   static bool state = false;
   if(!state)
      Comment(comm);
   if(id == CHARTEVENT_KEYDOWN){
      short key = (short)TranslateKey((int)lparam);
      if(key == 'x')
         state = !state;
   }   
   if(id == CHARTEVENT_MOUSE_MOVE && state){
      int subwindow = 0;
      datetime time = 0;
      double price  = 0;
      if(!ChartXYToTimePrice(
            ChartID(),
            (int)lparam,
            (int)dparam,
            subwindow,
            time,
            price
         )
      ){
         Print(__FUNCTION__,_LastError);
      }
      Comment(StringFormat(comm+"%s\n%s",
         string(time), DoubleToString(price, _Digits)
      ));
      g_price.Price(0, price);
      g_time.Time(0, time);
   }
}
//+------------------------------------------------------------------+
 
Robert:
I can confirm this same bug with ChartXYToTimePrice() on MT4 and mt5. In case that on mt5 keystrokes working corect around repeating events.

As nicholishen I am also using this function and never noticed a bug.

If you want to confirm a bug, please post evidences to reproduce it, otherwise it's just waste of time.

 

@Alain Verleyen
@nicholi shen

Thx for your support here.


Soo.. I prepared the code and I made some test.

First.. I noticed that in some cases to rebot MT4 the Comment() not updating data when moving mouse, when puting again EA then working - strange (not observed this in mt5).

Second.. now I'm lost. The Comment() updating data and it is scorrect, but when push button to do some action the value is changed as previous described.

Third.. when trading is done by S/B keys, then only one time can be done most often, some times Mt4 execute this normaly (not observed this in mt5). Can't udnerstand and recognize what is wrong in this all.


#property copyright "MR R..e"
extern double  Lot     = 0.10;
extern double  Slippage       = 4;
extern double  TP             = 150;
extern double  SL             = 150;
extern double  RiskReward     = 1;
 
extern int     Magic          = 123;   
extern double _Lot            = 0.01;      
 
int ticket,open_trade,counter;
datetime expiration;
bool result = false;
string _  ="_";
string __ =" ";
string zp =",";
string I =" | "; 

#define K_0 48
#define K_1 49
#define K_2 50
#define K_3 51
#define K_4 52
#define K_5 53
#define K_6 54
#define K_7 55
#define K_8 56
#define K_9 57

#define K_A 65
#define K_B 66
#define K_C 67
#define K_D 68
#define K_E 69
#define K_F 70
#define K_G 71
#define K_H 72
#define K_I 73
#define K_J 74
#define K_K 75
#define K_L 76
#define K_M 77
#define K_N 78
#define K_O 79
#define K_P 80
#define K_Q 81
#define K_R 82
#define K_S 83
#define K_T 84
#define K_U 85
#define K_V 86
#define K_W 87
#define K_X 88
#define K_Y 89
#define K_Z 90


//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){
   ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,1);
 
   return(INIT_SUCCEEDED);
} 
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  //Comment("");
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
 
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam){
   //+------------------------------------------------------------------+
   //int digits   = MarketInfo(Symbol(),MODE_DIGITS);

   //--- Convert the X and Y coordinates in terms of date/time
   //if(id==CHARTEVENT_MOUSE_MOVE){
      int      x     =(int)lparam;
      int      y     =(int)dparam;
      datetime dt    =0;
      double   price =0;
      int      window=0;
      ChartXYToTimePrice(0,x,y,window,dt,price);
      Comment(x,I,y,I,dt,I,price); 
      //Print(x,I,y,I,dt,I,price);
   //double value = NormalizeDouble(price,digits);
   
   //+------------------------------------------------------------------+
      if(id==CHARTEVENT_KEYDOWN){
         //Print("Test OK");
         switch(lparam){
            case K_S:  sell_(0);                   break;
            case K_B:  buy_(0);                    break; 
            case K_A:  CloseAllOrders();           break;
            case K_C:  CloseAllOrdersOnChart();    break;
            case K_P:  modify_tp_(dt,price);       break;
            case K_L:  modify_sl_(dt,price);       break;
            case K_H:  Create_HLine(dt,price);     break;
            case K_V:  Create_VLine(dt,price);     break;
            case K_D:  DeleteObjects();            break;
 
         }
     }
     RefreshRates();
}
//+------------------------------------------------------------------+
// FUNCTIONS
//+------------------------------------------------------------------+
void sell_(double lot){ 
   string signal = "sell";
   
   if(lot>0){_Lot = lot;}
   //double minstoplevel=MarketInfo(Symbol(),MODE_STOPLEVEL);
   double price = Bid; //NormalizeDouble(Bid,Digits
   if(SL>0){SL = Ask+SL*Point;}else SL =0;
   if(TP>0){TP = Bid-TP*Point;}else TP =0;
   result=OrderSend(Symbol(),OP_SELL,_Lot,price,Slippage,SL,TP,signal,Magic,0,Red); check_result(result);
   Print(_Lot,I,price,I,SL,I,TP,I,signal);    
}
//+------------------------------------------------------------------+
void buy_(double lot){ 
   string signal = "buy";
   
   if(lot>0){_Lot = lot;}
   //double minstoplevel=MarketInfo(Symbol(),MODE_STOPLEVEL);   
   if(SL>0){SL = Bid-SL*Point;}else SL =0; 
   if(TP>0){TP =Ask+TP*Point;}else TP =0;
   double price = Ask; //NormalizeDouble(Ask,Digits) 
   result=OrderSend(Symbol(),OP_BUY,_Lot,price,Slippage,SL,TP,signal,Magic,0,Blue); check_result(result);
   Print(_Lot,I,price,I,SL,I,TP,I,signal);     
}
//+------------------------------------------------------------------+
void sell_stop_(double lot, datetime dt, double price){ 
   string signal = "sell_stop";
      
   if(lot>0){_Lot = lot;} 
   //double minstoplevel=MarketInfo(Symbol(),MODE_STOPLEVEL);
   if(SL>0){SL = Ask+SL*Point;}else SL =0;
   if(TP>0){TP = Bid-TP*Point;}else TP =0;
   if(dt>TimeCurrent()){expiration=dt;}
   result=OrderSend(Symbol(),OP_SELLSTOP,_Lot,price,Slippage,SL,TP,signal,Magic,expiration,Red); check_result(result); 
   Print(_Lot,I,price,I,SL,I,TP,I,signal);      
}
//+------------------------------------------------------------------+
void buy_stop_(double lot, datetime dt, double price){ 
   string signal = "buy_stop";
      
   if(lot>0){_Lot = lot;}
   //double minstoplevel=MarketInfo(Symbol(),MODE_STOPLEVEL);
   if(SL>0){SL = Bid-SL*Point;}else SL =0; 
   if(TP>0){TP =Ask+TP*Point;}else TP =0;
   if(dt>TimeCurrent()){expiration=dt;}
   result=OrderSend(Symbol(),OP_BUYSTOP,_Lot,price,Slippage,SL,TP,signal,Magic,expiration,Blue); check_result(result); 
   Print(_Lot,I,price,I,SL,I,TP,I,signal);      
}
//+------------------------------------------------------------------+
void sell_limit_(double lot, datetime dt, double price){ 
   string signal = "sell_limit";
     
   if(lot>0){_Lot = lot;} 
   //double minstoplevel=MarketInfo(Symbol(),MODE_STOPLEVEL);
   if(SL>0){SL = Ask+SL*Point;}else SL =0;
   if(TP>0){TP = Bid-TP*Point;}else TP =0;
   if(dt>TimeCurrent()){expiration=dt;}
   result=OrderSend(Symbol(),OP_SELLLIMIT,_Lot,price,Slippage,SL,TP,signal,Magic,expiration,Red); check_result(result); 
   Print(_Lot,I,price,I,SL,I,TP,I,signal);   
}
//+------------------------------------------------------------------+
void buy_limit_(double lot, datetime dt, double price){ 
   string signal = "buy_limit";
   
   if(lot>0){_Lot = lot;}
   //double minstoplevel=MarketInfo(Symbol(),MODE_STOPLEVEL);
   if(SL>0){SL = Bid-SL*Point;}else SL =0; 
   if(TP>0){TP =Ask+TP*Point;}else TP =0;
   if(dt>TimeCurrent()){expiration=dt;}
   result=OrderSend(Symbol(),OP_BUYLIMIT,_Lot,price,Slippage,SL,TP,signal,Magic,expiration,Blue); check_result(result); 
   Print(_Lot,I,price,I,SL,I,TP,I,signal);      
} 
//+------------------------------------------------------------------+
void CloseAllOrders(){ 
   int total = OrdersTotal();
   for (int i=total-1; i>=0; i--) {
       if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)){ 
          //if (OrderMagicNumber() == Magic){ 
              if (OrderType() == OP_BUY ){result = OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),Slippage); check_result(result); }
              if (OrderType() == OP_SELL){result = OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),Slippage); check_result(result); }
          //}   
       }
    } 
}
//+------------------------------------------------------------------+
void CloseAllOrdersOnChart(){ 
   int total = OrdersTotal();
   for (int i=total-1; i>=0; i--) {
       if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)){ 
          if (OrderSymbol() == Symbol()&& OrderMagicNumber() == Magic){ 
              if (OrderType() == OP_BUY ){result = OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),Slippage); check_result(result); }
              if (OrderType() == OP_SELL){result = OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),Slippage); check_result(result); }
          }   
       }
    } 
} 
//+------------------------------------------------------------------+
void modify_tp_(datetime t, double p){
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
         continue;
      if(OrderSymbol()!=Symbol())
         continue;
      
      RefreshRates();
      
      if(OrderType()==OP_BUY)     
      if(p>Ask)
         result = OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss(),p,OrderExpiration(),White); check_result(result);
      if(OrderType()==OP_SELL)
      if(p<Bid)
         result = OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss(),p,OrderExpiration(),White); check_result(result);    
      if((OrderType()==OP_BUYSTOP) || (OrderType()==OP_BUYLIMIT))     
      if(p>OrderOpenPrice())
         result = OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss(),p,OrderExpiration(),White); check_result(result); 
      if((OrderType()==OP_SELLSTOP) || (OrderType()==OP_SELLLIMIT))
      if(p<OrderOpenPrice())
         result = OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss(),p,OrderExpiration(),White); check_result(result);             
   }
}
//+------------------------------------------------------------------+
void modify_sl_(datetime t, double p){
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
         continue;
      if(OrderSymbol()!=Symbol())
         continue;
      
      RefreshRates();
      
      if(OrderType()==OP_BUY)     
      if(p<Bid)
         result = OrderModify(OrderTicket(),OrderOpenPrice(),p,OrderTakeProfit(),OrderExpiration(),White);check_result(result);
      if(OrderType()==OP_SELL)
      if(p>Ask)
         result = OrderModify(OrderTicket(),OrderOpenPrice(),p,OrderTakeProfit(),OrderExpiration(),White);check_result(result);      
      if((OrderType()==OP_BUYSTOP) || (OrderType()==OP_BUYLIMIT))     
      if(p<OrderOpenPrice())
         result = OrderModify(OrderTicket(),OrderOpenPrice(),p,OrderTakeProfit(),OrderExpiration(),White);check_result(result);   
      if((OrderType()==OP_SELLSTOP) || (OrderType()==OP_SELLLIMIT))
      if(p>OrderOpenPrice())
         result = OrderModify(OrderTicket(),OrderOpenPrice(),p,OrderTakeProfit(),OrderExpiration(),White);check_result(result);           
   }
}
 
//+------------------------------------------------------------------+
void check_result(bool result_){
      string info;
      if(result_ == false){
         info ="Order: " + OrderTicket() + " Error: " + GetLastError() ;
         Print(info);
         PlaySound("alert.wav");
      }      
      else{
         info ="Order: " + OrderTicket() + " Error: " + GetLastError() ;
         PlaySound("ok.wav");  
     }             
}  
  
//+------------------------------------------------------------------+
void Create_VLine(datetime t, double p){
   datetime tl = TimeLocal();
   string title = "VLine " + t + __ + tl;
   string obj_VLine_ = title;
   string desc = TimeToStr(t) + __ + TimeToStr(tl);
   ObjectCreate(obj_VLine_,OBJ_VLINE,0,t, 0,0,0,0,0);
   ObjectSet(obj_VLine_,OBJPROP_COLOR,MediumSlateBlue);
   ObjectSet(obj_VLine_,OBJPROP_STYLE,4);
   ObjectSetText(obj_VLine_,desc,5); 
   Print(title,I,t,I,p);
}
//+------------------------------------------------------------------+
void Create_HLine(datetime t, double p){
   datetime tl = TimeLocal();
   string title = "HLine " + p + __ + TimeLocal();
   string obj_HLine_ = title;
   string desc = TimeToStr(t) + __ + TimeToStr(tl);
   ObjectCreate(obj_HLine_,OBJ_HLINE,0,t, p); 
   ObjectSet(obj_HLine_, OBJPROP_COLOR,MediumSlateBlue);
   ObjectSet(obj_HLine_,OBJPROP_STYLE,4); 
   ObjectSetText(obj_HLine_,desc,5); 
   Print(title,I,t,I,p);
}
//+------------------------------------------------------------------+
void DeleteObjects(){
   Print("DeleteObjects");
   for(int i=ObjectsTotal(); i>=0; i--){           
       string name=ObjectName(i);
       ObjectDelete(name); 
   }
}
//+------------------------------------------------------------------+
Reason: