Set event handler callback for MetaTrader 5

Discuss, post your questions about TWSLink here.

Users who just registered, please write an email to
forum@trade-commander.de
with your username mentioned.
So we can distinguish you from bots.
Thank you
Post Reply
pietrop
Posts: 11
Joined: Tue Mar 20, 2018 1:05 pm

Set event handler callback for MetaTrader 5

Post by pietrop »

Hello all,

I need a working example for the SET_EVENT_HANDLER function in MT5:

Code: Select all

$TRADE_COMMANDER_HOME/twslink2/Documentation/html/fct_SET_EVENT_HANDLER.html
The given example:

Code: Select all

ret = SET_EVENT_HANDLER(ProcessTWSEvents,17,0)
works only for C# or the likes, i guess.

In MT5 I can't convert the address of my event handler function to the 64-bit int required by the DLL function.
I've tried this:

Code: Select all

...
typedef void (*TFunc)(int,int,int,int,double,double,double,double,string,string,string,string,double,double,int,int);
...

void ibEventHandler(		
	int integer1,	// carries always main category of event
	int integer2,	// can have specific meaning, in particular when integer1=2
	int integer3,	// carries any value
	int integer4,	// carries any value
	double double1,	// carries any value
	double double2,	// carries any value
	double double3,	// carries any value
	double double4,	// carries any value
	string string1,	// carries any value
	string string2,	// carries any value
	string string3,	// carries any value
	string string4,	// carries any value
	double double5,	// carries any value
	double double6,	// carries any value
	int integer5,	// carries any value
	int integer6	// carries any value
){
  // TODO
  return;
}

int OnInit() {
...
  TFunc func_ptr = ibEventHandler;
  res = SET_EVENT_HANDLER( func_ptr, 0, 0 );
...
}

but I get the compilation error:

Code: Select all

'func_ptr' - parameter conversion not allowed
Since the SET_EVENT_HANDLER wants "a 64 Bit-Pointer to address of callback function".

If I use this:

Code: Select all

  res = SET_EVENT_HANDLER( (int) func_ptr, 0, 0 );
I get:

Code: Select all

'(int)' - invalid cast operation
Any idea?

board_admin
Site Admin
Posts: 244
Joined: Mon Apr 24, 2017 3:24 pm

Re: Set event handler callback for MetaTrader 5

Post by board_admin »

The point is the cast operation. It seems not to be possible
to cast a pointer into int or long.

When you are certain, that your MetaTrader 5 is running in a 64 bit process (which is the case on 64 bit machines)
you need to change declaration of

Code: Select all

int SET_EVENT_HANDLER(int callback_handle,int subscription_mask,int traget_thread_id);
int SET_EVENT_HANDLER_OLE(int callback_handle,int subscription_mask,int traget_thread_id);
to

Code: Select all

int SET_EVENT_HANDLER(long callback_handle,int subscription_mask,int traget_thread_id);
int SET_EVENT_HANDLER_OLE(long  callback_handle,int subscription_mask,int traget_thread_id);
But this wont solve the compiler error in mql5. For some reasons, the mql compiler is to restrictive here.
You need a valid cast. Perhaps a question to MetaTrader forum?

board_admin
Site Admin
Posts: 244
Joined: Mon Apr 24, 2017 3:24 pm

Re: Set event handler callback for MetaTrader 5

Post by board_admin »

Workaround: The Event Handling is used in so called passive Eventhandling. The other options is the active event handling, you fetch
the events ocassionally or frequently. Watch the sample please:

Code: Select all

//+------------------------------------------------------------------+
//|                                                 twslink2demo.mq5 |
//|                              Copyright 2012, trade-commander.org |
//|                                   http://www.trade-commander.com |
//+------------------------------------------------------------------+
// function U2A is used to convert unicode strings as used in MT5 to ansi string used in TWSLink
#property copyright "Copyright 2012, trade-commander.org"
#property link      "http://www.trade-commander.com"
#property version   "1.00"

#include <twslink2.mqh>



int      uidMSFT         	= 0;        // unique id for MSFT contract
int      uidOrderMSFT       = 0;       // unique id for MSFT order

//-----------------------------------
//--type of callback function
//-----------------------------------
typedef void (*twsl_fp)(	
	int ,	
	int ,	
	int ,	
	int ,	
	double ,
	double ,
	double ,
	double ,
	string ,
	string ,
	string ,
	string ,
	double ,
	double ,
	int ,	
	int );

void ibEventHandler(		
	int integer1,	// carries always main category of event
	int integer2,	// can have specific meaning, in particular when integer1=2
	int integer3,	// carries any value
	int integer4,	// carries any value
	double double1,	// carries any value
	double double2,	// carries any value
	double double3,	// carries any value
	double double4,	// carries any value
	string string1,	// carries any value
	string string2,	// carries any value
	string string3,	// carries any value
	string string4,	// carries any value
	double double5,	// carries any value
	double double6,	// carries any value
	int integer5,	// carries any value
	int integer6	// carries any value
){
  PrintFormat("-%d -%d -%d -%d -%.8f -%.8f -%.8f -%.8f -%s -%s -%s -%s -%.8f -%.8f -%d -%d"
		,integer1,integer2,integer3,integer4
		,double1,double2,double3,double4
		,string1,string2,string3,string4
		,double5,double6
		,integer5,integer6);
  return;
}

twsl_fp cb=ibEventHandler;

void fetch_twslink_events(int timeout_milliseconds=3)
{
	int uidev=0;
	while( (uidev=WAIT_FOR_EVENT(timeout_milliseconds)) > 0)
	{

		ibEventHandler(GET_EVENT_VAL_I(uidev,1)
						,GET_EVENT_VAL_I(uidev,2)
						,GET_EVENT_VAL_I(uidev,3)
						,GET_EVENT_VAL_I(uidev,4)

						,GET_EVENT_VAL_D(uidev,5)
						,GET_EVENT_VAL_D(uidev,6)
						,GET_EVENT_VAL_D(uidev,7)
						,GET_EVENT_VAL_D(uidev,8)

						,GET_EVENT_VAL(uidev,9)
						,GET_EVENT_VAL(uidev,10)
						,GET_EVENT_VAL(uidev,11)
						,GET_EVENT_VAL(uidev,12)

						,GET_EVENT_VAL_D(uidev,13)
						,GET_EVENT_VAL_D(uidev,14)

						,GET_EVENT_VAL_I(uidev,15)
						,GET_EVENT_VAL_I(uidev,16));

	
	}
	
}

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
// connect to TWS / Gateway at standard port. make sure TWS or Gateway are setup to operate with API clients such as TWSLink2  (http://www.youtube.com/watch?v=53tmypRq5wI)
	CONNECT(U2A("127.0.0.1"),7497,1,1000);
	// register MSFT
	uidMSFT=REGISTER_CONTRACT(U2A("MSFT"),U2A("STK"), U2A("USD"), U2A("SMART"), U2A(""), U2A(""),U2A(""), 0.0, U2A(""),0,0.0);
	// place buy 100 shares at market for MSFT		
	uidOrderMSFT=PLACE_ORDER(uidMSFT,0, U2A("BUY"), U2A("MKT"),100,0.0,0.0,U2A("GTC"), 1,0);

	/*
	void* cbl=(void*) cb;
	int ret=SET_EVENT_HANDLER((long) cb,0,0);
		*/
	
	// set a timer called each 10 milliseconds
	bool bret=EventSetMillisecondTimer(10);

	return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

 	fetch_twslink_events();  
  }
//+------------------------------------------------------------------+
void OnTimer()
{
	fetch_twslink_events();
}

pietrop
Posts: 11
Joined: Tue Mar 20, 2018 1:05 pm

Re: Set event handler callback for MetaTrader 5

Post by pietrop »

Thanks, I've looked into the active event handling and I've tested the following code:

Code: Select all

void ibEventHandler(		
	int integer1,	// carries always main category of event
	int integer2,	// can have specific meaning, in particular when integer1=2
	int integer3,	// carries any value
	int integer4,	// carries any value
	double double1,	// carries any value
	double double2,	// carries any value
	double double3,	// carries any value
	double double4,	// carries any value
	string string1,	// carries any value
	string string2,	// carries any value
	string string3,	// carries any value
	string string4,	// carries any value
	double double5,	// carries any value
	double double6,	// carries any value
	int integer5,	// carries any value
	int integer6	// carries any value
){
  Print("Inside ibEventHandler: ", 
    integer1, ",", integer2, ",", integer3, ",", integer4, ",", 
    "\n  ", double1, ",", double2, ",", double3, ",", double4, ",", 
    "\n  ", string1, ",", string2, ",", string3, ",", string4, ",", 
    "\n  ", double5, ",", double6,
    "\n  ", integer5, ",", integer6, ","
  ); 
}


int OnInit() {
...
  res = SET_EVENT_HANDLER( 0, 1, 0 );
...
}

void OnTick() {
...
  testIbEvents();  
...
}

void testIbEvents() {
  int eventUid = WAIT_FOR_EVENT(1000);
  if( eventUid > 0 ) {
    Print("Event Uid=", eventUid, ", allVals=", A2U(GET_EVENT_VAL(eventUid,0)));
    ibEventHandler(	
    	GET_EVENT_VAL_I(eventUid,1),
    	GET_EVENT_VAL_I(eventUid,2),
    	GET_EVENT_VAL_I(eventUid,3),
    	GET_EVENT_VAL_I(eventUid,4),
    	GET_EVENT_VAL_D(eventUid,5),
    	GET_EVENT_VAL_D(eventUid,6),
    	GET_EVENT_VAL_D(eventUid,7),
    	GET_EVENT_VAL_D(eventUid,8),
    	A2U(GET_EVENT_VAL(eventUid,9)),
    	A2U(GET_EVENT_VAL(eventUid,10)),
    	A2U(GET_EVENT_VAL(eventUid,11)),
    	A2U(GET_EVENT_VAL(eventUid,12)),
    	GET_EVENT_VAL_D(eventUid,13),
    	GET_EVENT_VAL_D(eventUid,14),
    	GET_EVENT_VAL_I(eventUid,15),
    	GET_EVENT_VAL_I(eventUid,16)
  	);
  }
}
But from the logs apparently I get events with no significant fields (as per the documentation, "enf"=Event Not Found):

Code: Select all

...
Event Uid=1324, allVals=enf
Inside ibEventHandler: 2147483646,2147483646,2147483646,2147483646,
  1.797693134862316e+308,1.797693134862316e+308,1.797693134862316e+308,1.797693134862316e+308,
  enf,enf,enf,enf,
  1.797693134862316e+308,1.797693134862316e+308
  2147483646,2147483646
Event Uid=1325, allVals=enf
Inside ibEventHandler: 2147483646,2147483646,2147483646,2147483646,
  1.797693134862316e+308,1.797693134862316e+308,1.797693134862316e+308,1.797693134862316e+308,
  enf,enf,enf,enf,
  1.797693134862316e+308,1.797693134862316e+308
  2147483646,2147483646
...
Am I doing something wrong?

pietrop
Posts: 11
Joined: Tue Mar 20, 2018 1:05 pm

Re: Set event handler callback for MetaTrader 5

Post by pietrop »

@board_admin
I've tested your code, but I get the compilation errors:

Code: Select all

'(void*)' - invalid cast operation
'(void*)' - invalid cast operation
at the line:

Code: Select all

  void* cbl = (void*) cb;
and:

Code: Select all

'(long)' - invalid cast operation
at the line:

Code: Select all

  res = SET_EVENT_HANDLER( (long) cbl, 1, 0 );
According to the doc, though, I should be able to access the events by simply passing 0 as callback:
IN
Param # Type Name Description Format Value Range
1 int64 pcb 64 Bit-Pointer to address of callback function >=0
2 int mask Bitmask of main-event subscription. Pass 0 to subscribe for all events eventident >=0
3 int threadid id of thread getting callback. If 0, the calling thread gets callback >=0

Comments

If #1 is 0 but #2 is not 0, all events are buffered in the event buffer. This makes it possible to to access events in those applications that can't utilize callback Functions (active eventhandling), like eSignal EFS or TradeStation (if not possible meanwhile)

If #1 is not 0 and #2 is not 0, all events get reflected only through callback defined by #1 and are not stored in the event buffer
so:

Code: Select all

SET_EVENT_HANDLER( 0, <bitmask>, 0)
should do the trick. I don't understand why I get "enf" from the events.

EDIT:

Apparently,

Code: Select all

res = SET_EVENT_HANDLER( 0, 1, 0 );
always returns 0.

Still, when i call WAIT_FOR_EVENT, I receive increasing event uids, but with invalid fields.

board_admin
Site Admin
Posts: 244
Joined: Mon Apr 24, 2017 3:24 pm

Re: Set event handler callback for MetaTrader 5

Post by board_admin »

With active Eventhandling, you don't call SET_EVENT_HANDLER.
Check this sample please. Should run fine:

Code: Select all

//+------------------------------------------------------------------+
//|                                                 twslink2demo.mq5 |
//|                              Copyright 2012, trade-commander.org |
//|                                   http://www.trade-commander.com |
//+------------------------------------------------------------------+
// function U2A is used to convert unicode strings as used in MT5 to ansi string used in TWSLink
#property copyright "Copyright 2012, trade-commander.org"
#property link      "http://www.trade-commander.com"
#property version   "1.00"

#include <twslink2.mqh>



int      uidMSFT         	= 0;        // unique id for MSFT contract
int      uidOrderMSFT       = 0;       // unique id for MSFT order



void ibEventHandler(		
	int integer1,	// carries always main category of event
	int integer2,	// can have specific meaning, in particular when integer1=2
	int integer3,	// carries any value
	int integer4,	// carries any value
	double double1,	// carries any value
	double double2,	// carries any value
	double double3,	// carries any value
	double double4,	// carries any value
	string string1,	// carries any value
	string string2,	// carries any value
	string string3,	// carries any value
	string string4,	// carries any value
	double double5,	// carries any value
	double double6,	// carries any value
	int integer5,	// carries any value
	int integer6	// carries any value
){
  PrintFormat("-%d -%d -%d -%d -%.8f -%.8f -%.8f -%.8f -%s -%s -%s -%s -%.8f -%.8f -%d -%d"
		,integer1,integer2,integer3,integer4
		,double1,double2,double3,double4
		,string1,string2,string3,string4
		,double5,double6
		,integer5,integer6);
  return;
}

void fetch_twslink_events(int timeout_milliseconds=3)
{
	int uidev=0;
	while( (uidev=WAIT_FOR_EVENT(timeout_milliseconds)) > 0)
	{

		ibEventHandler(GET_EVENT_VAL_I(uidev,1)
						,GET_EVENT_VAL_I(uidev,2)
						,GET_EVENT_VAL_I(uidev,3)
						,GET_EVENT_VAL_I(uidev,4)

						,GET_EVENT_VAL_D(uidev,5)
						,GET_EVENT_VAL_D(uidev,6)
						,GET_EVENT_VAL_D(uidev,7)
						,GET_EVENT_VAL_D(uidev,8)

						,GET_EVENT_VAL(uidev,9)
						,GET_EVENT_VAL(uidev,10)
						,GET_EVENT_VAL(uidev,11)
						,GET_EVENT_VAL(uidev,12)

						,GET_EVENT_VAL_D(uidev,13)
						,GET_EVENT_VAL_D(uidev,14)

						,GET_EVENT_VAL_I(uidev,15)
						,GET_EVENT_VAL_I(uidev,16));

	
	}
	
}

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
// connect to TWS / Gateway at standard port. make sure TWS or Gateway are setup to operate with API clients such as TWSLink2  (http://www.youtube.com/watch?v=53tmypRq5wI)
	CONNECT(U2A("127.0.0.1"),7497,1,1000);
	// register MSFT
	uidMSFT=REGISTER_CONTRACT(U2A("MSFT"),U2A("STK"), U2A("USD"), U2A("SMART"), U2A(""), U2A(""),U2A(""), 0.0, U2A(""),0,0.0);
	// place buy 100 shares at market for MSFT		
	uidOrderMSFT=PLACE_ORDER(uidMSFT,0, U2A("BUY"), U2A("MKT"),100,0.0,0.0,U2A("GTC"), 1,0);

	/*
	void* cbl=(void*) cb;
	int ret=SET_EVENT_HANDLER((long) cb,0,0);
		*/
	
	// set a timer called each 10 milliseconds
	bool bret=EventSetMillisecondTimer(10);
	
	return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

 	fetch_twslink_events();  
  }
//+------------------------------------------------------------------+
void OnTimer()
{
	fetch_twslink_events();
}

pietrop
Posts: 11
Joined: Tue Mar 20, 2018 1:05 pm

Re: Set event handler callback for MetaTrader 5

Post by pietrop »

@boad_admin
With your latest code I don't even get the event uids > 0.
If I use SET_EVENT_HANDLER( 0, 1, 0 ), I get the events uid but with the uninitialized event fields ("enf", etc.).

board_admin
Site Admin
Posts: 244
Joined: Mon Apr 24, 2017 3:24 pm

Re: Set event handler callback for MetaTrader 5

Post by board_admin »

If you just use the code (exactly) i provided, it does not work ?
SET_EVENT_HANDLER makes no sense as you have no callback.

pietrop
Posts: 11
Joined: Tue Mar 20, 2018 1:05 pm

Re: Set event handler callback for MetaTrader 5

Post by pietrop »

Unfortunately I've tested your code and it doesn't work, as I've described in my previous post.
As I've mentioned before, I had seen from this doc:

twslink2/Documentation/html/fct_SET_EVENT_HANDLER.html

that you need to set the callback to 0 to get the events in active mode:
Comments

If #1 is 0 but #2 is not 0, all events are buffered in the event buffer. This makes it possible to to access events in those applications that can't utilize callback Functions (active eventhandling), like eSignal EFS or TradeStation (if not possible meanwhile)

If #1 is not 0 and #2 is not 0, all events get reflected only through callback defined by #1 and are not stored in the event buffer
If i call SET_EVENT_HANDLER, I get 0 as a response but at least I get the event uids > 0 from WAIT_FOR_EVENT. But they have meaningless fields.

board_admin
Site Admin
Posts: 244
Joined: Mon Apr 24, 2017 3:24 pm

Re: Set event handler callback for MetaTrader 5

Post by board_admin »

Some parts of the documentation are out of date. The code is working on my side.
Please do not use SET_EVENT_HANDLER and try again.

pietrop
Posts: 11
Joined: Tue Mar 20, 2018 1:05 pm

Re: Set event handler callback for MetaTrader 5

Post by pietrop »

Before I was in WINE on Ubuntu, now I'm testing on Windows 10 in VirtualBox.
In this configuration I can get the events uid without registering the handler, but their fields are always "enf".

EDIT
But if I no longer need to set the event handler (and thus provide the event subscription category bitmask), this measn that in active mode I fetch all the events categories? What if I'm only interested in a subset?

board_admin
Site Admin
Posts: 244
Joined: Mon Apr 24, 2017 3:24 pm

Re: Set event handler callback for MetaTrader 5

Post by board_admin »

could you write a post with logfiles (loglevel=1) attached ?

pietrop
Posts: 11
Joined: Tue Mar 20, 2018 1:05 pm

Re: Set event handler callback for MetaTrader 5

Post by pietrop »

You mean TWSlink, MT or IB Gateway/TWS logfiles?

board_admin
Site Admin
Posts: 244
Joined: Mon Apr 24, 2017 3:24 pm

Re: Set event handler callback for MetaTrader 5

Post by board_admin »

TWSLink logs. Should be located in

Code: Select all

C:\trade-commander\twslink2\log

pietrop
Posts: 11
Joined: Tue Mar 20, 2018 1:05 pm

Re: Set event handler callback for MetaTrader 5

Post by pietrop »

You can find the log here attached.
Attachments
log.txt.gz
log files
(2.71 KiB) Downloaded 392 times

board_admin
Site Admin
Posts: 244
Joined: Mon Apr 24, 2017 3:24 pm

Re: Set event handler callback for MetaTrader 5

Post by board_admin »

Hello,
please download and install update:

http://trade-commander.com/?ddownload=281

There is in fact a problem. Please let me know, if you get values now.

pietrop
Posts: 11
Joined: Tue Mar 20, 2018 1:05 pm

Re: Set event handler callback for MetaTrader 5

Post by pietrop »

I'm trying to install it on Ubuntu WINE but I get the error in attachment.
Shall I delete the old file manually?
Attachments
Screenshot from 2018-04-03 13-56-42.png
Screenshot from 2018-04-03 13-56-42.png (16.72 KiB) Viewed 24937 times

board_admin
Site Admin
Posts: 244
Joined: Mon Apr 24, 2017 3:24 pm

Re: Set event handler callback for MetaTrader 5

Post by board_admin »

Just let me mention this: It is not tested on Linux/MacOS/Wine.
So i am sorry, can't provide support her.

The error below looks like TWSLink is somehow still in use

pietrop
Posts: 11
Joined: Tue Mar 20, 2018 1:05 pm

Re: Set event handler callback for MetaTrader 5

Post by pietrop »

I've managed to install after rebooting.
But unfortunately it's the same as before. I get the events but with all meaningless fields:

Code: Select all

2018.04.04 12:31:09.288	ZetaEA (GBPCHF,M1)	Event Uid=405, allVals=enf
2018.04.04 12:31:09.290	ZetaEA (GBPCHF,M1)	Inside ibEventHandler: 2147483646,2147483646,2147483646,2147483646,
2018.04.04 12:31:09.290	ZetaEA (GBPCHF,M1)	  1.797693134862316e+308,1.797693134862316e+308,1.797693134862316e+308,1.797693134862316e+308,
2018.04.04 12:31:09.290	ZetaEA (GBPCHF,M1)	  enf,enf,enf,enf,
2018.04.04 12:31:09.290	ZetaEA (GBPCHF,M1)	  1.797693134862316e+308,1.797693134862316e+308
2018.04.04 12:31:09.290	ZetaEA (GBPCHF,M1)	  2147483646,2147483646

Post Reply