├── .gitignore ├── LICENSE ├── README.markdown ├── examples ├── README.markdown ├── mql4zmq.mq4 ├── mql4zmq_bridge.mq4 ├── mql4zmq_pub.rb ├── mql4zmq_sub.rb └── mql4zmq_tickcollector.py ├── mql4zmq.c ├── mql4zmq.def ├── mql4zmq.h ├── mql4zmq.mqh ├── mql4zmq.vcxproj ├── mql4zmq.vcxproj.filters ├── mql4zmq.vcxproj.user └── pre-compiled ├── libzmq.dll └── mql4zmq.dll /.gitignore: -------------------------------------------------------------------------------- 1 | Debug -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011, 2012, 2013 Austen Conrad 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # mql4zmq 2 | 3 | The goal of this project is to provide [MQL4](http://docs.mql4.com/ "MQL4 documentation homepage.") bindings for the [ZeroMQ](http://zeromq.org/ "ZeroMQ homepage.") networking library. 4 | 5 | Licensed under the MIT License. See [LICENSE](https://github.com/AustenConrad/mql4zmq/blob/master/LICENSE) for more information. 6 | 7 | ### Version notes: 8 | If you are using MetaTrader build 509 or earlier, use stable [release 1.0.1](https://github.com/AustenConrad/mql4zmq/releases/tag/v1.0.1) 9 | 10 | If you are using MetaTrader build 600+, use the latest beta [2.0.0-pre](https://github.com/AustenConrad/mql4zmq/tree/2.0.0-pre) 11 | 12 | ### Example Usage: 13 | 14 | See Publish/Subscribe example in [examples](https://github.com/AustenConrad/mql4zmq/tree/master/examples "MQL4ZMQ Examples folder at Master.") folder. In general the use is exactly as [documented](http://api.zeromq.org/2-1:_start "ZeroMQ API Documentation.") by ZeroMQ and described in the "C" examples in the [ZGuide](http://zguide.zeromq.org/page:all "ZeroMQ ZGuide.") 15 | 16 | ### To build: 17 | 18 | 0. Download and install [Microsoft Visual C++ Express 2010](http://go.microsoft.com/?linkid=9709949 "Microsoft's Visual C++ 2010 Express Download Link.") if you don't already have it. 19 | 20 | 1. Download the [ZeroMQ v2.1.11 source](http://download.zeromq.org/zeromq-2.1.11.zip "ZeroMQ v2.1.1 source.") 21 | 22 | 2. Download or git clone the [MQL4ZMQ source](https://github.com/AustenConrad/mql4zmq/ "mql4zmq github.") 23 | 24 | 3. Copy the downloaded 'mql4zmq' source folder to: downloaded_zeromq_source_folder\builds\msvc\ 25 | 26 | 4. Open the ZMQ build solution at: downloaded_zeromq_source_folder\builds\msvc\msvc 27 | * You may need to right click on it and select: "open with" => "Microsfot Visual C++ 2010 Express" 28 | * It may need to be converted. In which case, select 'next' => 'no' then 'next' => 'finish' 29 | 30 | 5. Now that we have the solution open we need to add the mqlzmq project to the solution. To do this: 31 | 1. Right-click on "Solution 'msvc'" then select "add" => "existing project" 32 | 2. A file browser opens up. Go into the 'msvc' folder then the 'mql4zmq' folder and select the 'mql4zmq' project file. 33 | - You should now see the mql4zmq listed as project within the solution. 34 | 3. Right-click on the 'mql4zmq' project and select 'Project Dependencies'. Make sure the drop-down 'Projects' menu is set to 'mql4zmq' and then select 'libzmq' in the 'Depends on' list. Select "OK" to complete. 35 | 4. Make sure the build is set to 'Release' and not 'Debug'. See drop-down in middle of top Visual C++ application menu. 36 | 5. You are now ready to build the solution which will produce the ZeroMQ library (libzmq.dll) and the MQL4ZMQ bindings library (mql4zmq.dll). To do this right-click on the solution and select 'Build Solution'. 37 | 6. Once all 8 projects within the solution have completed building, we need to copy the files the MetaTrader needs to the location it needs them as follows: 38 | 39 |

40 | 		[downloaded_zeromq_source_folder]\builds\msvc\Release\mql4zmq.dll
41 | 		=> c:\Program Files (x86)\[metatrader directory]\experts\libraries\mql4zmq.dll
42 | 	
43 | 		[downloaded_zeromq_source_folder]\lib\libzmq.dll
44 | 		=> c:\Windows\SysWOW64\libzmq.dll
45 | 	
46 | 		[downloaded_zeromq_source_folder]\builds\msvc\mql4zmq\mql4zmq.mqh 
47 | 		=> c:\Program Files (x86)\[metatrader directory]\experts\include\mql4zmq.mqh	
48 | 	
49 | 		[downloaded_zeromq_source_folder]\builds\msvc\mql4zmq\examples\mql4zmq.mq4 
50 | 		=> c:\Program Files (x86)\[metatrader directory]\experts\mql4zmq.mq4
51 | 
52 | 		
53 | 54 | 6. You are now ready to open up metatrader, attach the example mql4zmq expert to the chart, and be off and running. 55 | * NOTE: when attaching to the chart make sure to select "Allow DLL Imports" and de-select "Confirm DLL Function Calls". 56 | 57 | 58 | ### To use the pre-compiled libraries: 59 | 60 | 0. Download and install the [Microsoft Visual C++ 2010 Redistributable Package](http://www.microsoft.com/download/en/details.aspx?id=5555 "Microsoft Visual C++ 2010 Redistributable Package Download.") if you don't already have it. 61 | 62 | 1. Download or git clone the [MQL4ZMQ source](https://github.com/AustenConrad/mql4zmq/ "mql4zmq github.") 63 | 64 | 2. Copy the following files to the following locations for MetaTrader: 65 | 66 |

67 | 	[downloaded_mql4zmq_source_folder]\pre-compiled\mql4zmq.dll 
68 | 	=> c:\Program Files (x86)\[metatrader directory]\experts\libraries\mql4zmq.dll
69 | 
70 | 	[downloaded_mql4zmq_source_folder]\pre-compiled\libzmq.dll 
71 | 	=> c:\Windows\SysWOW64\libzmq.dll
72 | 
73 | 	[downloaded_mql4zmq_source_folder]\mql4zmq.mqh 
74 | 	=> c:\Program Files (x86)\[metatrader directory]\experts\include\mql4zmq.mqh
75 | 
76 | 	[downloaded_mql4zmq_source_folder]\examples\mql4zmq.mq4 
77 | 	=> c:\Program Files (x86)\[metatrader directory]\experts\mql4zmq.mq4
78 | 
79 | 	
80 | 81 | 3. You are now ready to open up metatrader, attach the example mql4zmq expert to the chart, and be off and running. 82 | * NOTE: when attaching to the chart make sure to select "Allow DLL Imports" and de-select "Confirm DLL Function Calls". 83 | -------------------------------------------------------------------------------- /examples/README.markdown: -------------------------------------------------------------------------------- 1 | # mql4zmq examples 2 | ## mql4zmq.mq4: 3 | 4 | This is an example EA that shows how to use mql4zmq to publish and subscribe messages each tick. 5 | 6 | ## curl dump: 7 | On a *nix box: 8 | 9 | curl -N [metatrader ip address]:[mql4zmq publish port, default is 2027] 10 | 11 | will dump out all the messages published by the mql4zmq EA. 12 | 13 | Example => curl -N 10.18.16.5:2027 14 | 15 | ## ruby examples: 16 | The mql4zmq_pub.rb and mql4zmq_sub.rb files are provided to use to test the mql4zmq EA. 17 | 18 | They also demonstrate the key point of the mql4zmq project which is that the use of ZeroMQ to communicate with 19 | MetaTrader opens up the door to writing your trading code in any of the 30+ languages for which there is a [ZeroMQ binding.](http://www.zeromq.org/bindings:_start "ZeroMQ language bindings.") 20 | 21 | With very little work you can expand the mql4zmq EA to be a full fledged bridge. 22 | 23 | ####Example Usage: 24 | 25 | ruby mql4zmq_pub.rb 10.18.16.5:2028 cmd 26 | Hello World 27 | => cmd Hello World 28 | 29 | ruby mql4zmq_sub.rb 10.18.16.5:2027 tick my_custom1 my_custom2 30 | => subscribes to the 'tick', 'my_custom1', and 'my_custom2' channels. 31 | 32 | ## python example (Contributed by Keith K.): 33 | This script digests channel "ticks" from the mql4zmq EA and timestamps each locally 34 | in microseconds (formatted to nicely work with matplotlib via the date2num function). 35 | 36 | ## mql4zmq_bridge.mq4 (STILL IN DEVELOPMENT) 37 | This is an example bridge to show how easy it is to develop one using MQL4ZMQ. I am only adding parts 38 | as my current projects need them. Eventually, this will be a complete example. Until then, it will 39 | be largely undocumented; for reference only. -------------------------------------------------------------------------------- /examples/mql4zmq.mq4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AustenConrad/mql4zmq/19493dbc26635ac4459fee6cb01688cdc407fc08/examples/mql4zmq.mq4 -------------------------------------------------------------------------------- /examples/mql4zmq_bridge.mq4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AustenConrad/mql4zmq/19493dbc26635ac4459fee6cb01688cdc407fc08/examples/mql4zmq_bridge.mq4 -------------------------------------------------------------------------------- /examples/mql4zmq_pub.rb: -------------------------------------------------------------------------------- 1 | # run via: ruby mql4zmq_pub.rb 10.18.16.5:2028 cmd 2 | # Hello World 3 | # => sends message 'cmd Hello World' to the MetaTrader EA at 10.18.16.5:2028 4 | require 'zmq' 5 | 6 | # Check for help being requested. 7 | if ARGV[0] == "-h" || ARGV[0] == "--help" 8 | puts "Usage: ruby mql4zmq_pub.rb [MetaTrader IP address]:[MQL4ZMQ EA Port Number default 2028] [channel to send messages on]" 9 | puts "example: \n ruby mql4zmq_pub.rb 10.18.16.16:2028 cmd\n Hello World\n => sends message 'cmd Hello World' to the MetaTrader EA at 10.18.16.16" 10 | else 11 | # Initialize ZeroMQ Context. 12 | context = ZMQ::Context.new 13 | 14 | # Initialze channel variable with the supplied channel name to publish to. 15 | chan = ARGV[1] 16 | 17 | # Configure the ZeroMQ socket to be of type Publish. 18 | pub = context.socket ZMQ::PUB 19 | 20 | # Connect to the Subscription node. This is backwards from the way this is usually done, but we 21 | # do it this way for the MQL4ZMQ project so that we can have multiple publishers send commands to 22 | # the MetaTrader EA. 23 | pub.connect "tcp://#{ARGV[0]}" 24 | 25 | # On newline, send the message to the MetaTrader EA. 26 | while msg = STDIN.gets 27 | msg.strip! 28 | pub.send "#{chan} #{msg}" 29 | end 30 | end -------------------------------------------------------------------------------- /examples/mql4zmq_sub.rb: -------------------------------------------------------------------------------- 1 | # run via: ruby mql4zmq_sub.rb 10.18.16.5:2027 tick [channel 2] [channel 3]... 2 | require 'zmq' 3 | 4 | # Check for help requested 5 | if ARGV[0] == "-h" || ARGV[0] == "--help" 6 | puts "Usage: ruby mql4zmq_sub.rb [MetaTrader IP Address]:[MQL4ZMQ EA Port Number default 2027] [channel 1] [channel 2] [channel 3]..." 7 | puts "Example:\nruby zma_ploutos_sub.rb 10.18.16.16:2027 tick trades\n=> subscribes to the 'tick' and 'trades' channels coming from the MetaTrader EA at 10.18.16.16." 8 | else 9 | # Initialize the ZeroMQ context. 10 | context = ZMQ::Context.new 11 | 12 | # Store the location of the server in a variable. 13 | server = ARGV[0] 14 | 15 | # Retrieve the list of channels to subscribe to. We drop the first value because that is the server address. 16 | channels = ARGV.drop(1) 17 | 18 | # Configure the socket to be of type subscribe. 19 | sub = context.socket ZMQ::SUB 20 | 21 | # Connect to the server using the subscription model. 22 | sub.connect "tcp://#{server}" 23 | 24 | # Subscribe to the requested channels. 25 | channels.each do |ch| 26 | sub.setsockopt ZMQ::SUBSCRIBE, ch 27 | end 28 | 29 | # Do something when we receive a message. 30 | while line = sub.recv 31 | channel, bid, ask, time = line.split ' ', 4 32 | puts "##{channel} [#{time}]: #{bid[0..7]} #{ask[0..7]}" 33 | end 34 | end -------------------------------------------------------------------------------- /examples/mql4zmq_tickcollector.py: -------------------------------------------------------------------------------- 1 | # collect ticks and add matplotlib local timestamp as float 2 | 3 | import zmq 4 | from datetime import datetime 5 | from matplotlib.dates import date2num 6 | 7 | context = zmq.Context() 8 | socket = context.socket(zmq.SUB) 9 | 10 | socket.connect("tcp://127.0.0.1:2027") 11 | 12 | socket.setsockopt(zmq.SUBSCRIBE,"tick") 13 | 14 | 15 | while True: 16 | string = socket.recv() 17 | print string + " " + str(date2num(datetime.now() )) 18 | -------------------------------------------------------------------------------- /mql4zmq.c: -------------------------------------------------------------------------------- 1 | /* 2 | MQL4ZMQ - MQL4 bindings for ZeroMQ 3 | 4 | (c) 2012 Austen Conrad. Any of this software, or any part thereof, is allowed as long as the use complies with GPL v3.0: http://www.gnu.org/licenses/gpl-3.0-standalone.html 5 | Additionally, no warrenty of any kind is made. Use software at own risk. 6 | 7 | =================================== 8 | 9 | The reason for all of this is that MetaTrader is a visual basic application and therefore is written using the STDCALL calling 10 | convention while ZeroMQ dll EXPORT defaults to the standard C calling convention (CDECL). If not changed, a call to 11 | libzmq.dll from MetaTrader will result in the trading terminal crashing. 12 | 13 | Therefore, this file generates mql4zmq.dll which wraps each call the zmq.h exports when compiled as libzmq.dll (i.e. each function 14 | that has ZMQ_EXPORT preceeding it) as a STDCALL instead (i.e. __stdcall via WINAPI definition). 15 | 16 | Additionally, MetaTrader4 has limitations on datatypes and data structures that we attempt to resolve by having the wrapping funtion 17 | inputs being of a type and in a manner that will jive with MQL4. 18 | 19 | NOTE: Remember to add a link to the "libzmq.lib" file that is created upon building of libzmq to the mql4zmq project via: Add => Existing Item => ../Debug/libzmq.lib 20 | This .lib file exposes all of the exported functions of the libzmq.dll for use with our program as referenced per zmq.h. 21 | Also add the "mql4zmq.def" file to the linker input via: Properties => Configuration Properties => Linker => Input => Module Definition File, 22 | and to change the linker settings from "Windows" to "Console" via: Properties => Configuration Properties => Linker => System => Subsystem. 23 | 24 | NAMING NOTE: To avoid naming collisions with the original zmq.h definitions we renamed our exported functions with 'mql4' appended to the beginning of the name. 25 | In the mql4zmq.mqh we revert the names back to the original to reduce confusion when writing experts. 26 | 27 | libzmq.dll NOTE: After building the solution, copy ../../../lib/libzmq.dll to c:\Windows\SysWOW64\libzmq.dll so that our bindings and other applications can access ZeroMQ. 28 | 29 | */ 30 | 31 | // Include the original libzmq header file. 32 | #include "../../../include/zmq.h" 33 | 34 | // Handle DSO symbol visibility. This is already defined in zmq.h, but we set it here again to protect against future changes to Microsoft Visual C++ detection methods. 35 | #define ZMQ_EXPORT __declspec(dllexport) 36 | 37 | // Setup the standard call specification keyword for the compiler. 38 | #define WINAPI __stdcall 39 | 40 | // Hello World test function. 41 | ZMQ_EXPORT const char* WINAPI ping (const char* pong) 42 | { 43 | return(pong); 44 | } 45 | 46 | /******************************************************************************/ 47 | /* 0MQ versioning support. */ 48 | /******************************************************************************/ 49 | ZMQ_EXPORT void WINAPI mql4zmq_version (int *major, int *minor, int *patch) 50 | { 51 | zmq_version(major, minor, patch); 52 | } 53 | 54 | /******************************************************************************/ 55 | /* 0MQ errors. */ 56 | /******************************************************************************/ 57 | ZMQ_EXPORT int WINAPI mql4zmq_errno (void) 58 | { 59 | return zmq_errno(); 60 | } 61 | 62 | ZMQ_EXPORT const char* WINAPI mql4zmq_strerror (int errnum) 63 | { 64 | return zmq_strerror(errnum); 65 | } 66 | 67 | /******************************************************************************/ 68 | /* 0MQ message definition. */ 69 | /******************************************************************************/ 70 | ZMQ_EXPORT int WINAPI mql4zmq_msg_init (zmq_msg_t *msg) 71 | { 72 | return zmq_msg_init(msg); 73 | } 74 | 75 | ZMQ_EXPORT int WINAPI mql4zmq_msg_init_size (zmq_msg_t *msg, size_t size) 76 | { 77 | return zmq_msg_init_size(msg, size); 78 | } 79 | 80 | // Used to satisfy zmq_msg_init_data requirement to have a function passed to it that will free the data buffer 81 | // provided when it is no longer needed. For more info on the 'free' call see: http://www.cplusplus.com/reference/clibrary/cstdlib/free/ 82 | // 83 | // NOTICE: We are no longer using this (passing NULL instead) as it was causing windows to close MetaTrader due to 84 | // thinking it was a virus since we were clearing memory that was originally allocated MetaTrader and not mql4zmq.dll 85 | void release_buffer(void *data, void *hint) 86 | { 87 | free(data); 88 | } 89 | 90 | ZMQ_EXPORT int WINAPI mql4zmq_msg_init_data (zmq_msg_t *msg, void *data, size_t size) 91 | { 92 | return zmq_msg_init_data(msg, data, size, NULL, NULL); 93 | } 94 | 95 | ZMQ_EXPORT int WINAPI mql4zmq_msg_close (zmq_msg_t *msg) 96 | { 97 | return zmq_msg_close(msg); 98 | } 99 | 100 | ZMQ_EXPORT int WINAPI mql4zmq_msg_move (zmq_msg_t *dest, zmq_msg_t *src) 101 | { 102 | return zmq_msg_move(dest, src); 103 | } 104 | 105 | ZMQ_EXPORT int WINAPI mql4zmq_msg_copy (zmq_msg_t *dest, zmq_msg_t *src) 106 | { 107 | return zmq_msg_copy(dest, src); 108 | } 109 | 110 | ZMQ_EXPORT void* WINAPI mql4zmq_msg_data (zmq_msg_t *msg) 111 | { 112 | return zmq_msg_data(msg); 113 | } 114 | 115 | ZMQ_EXPORT size_t WINAPI mql4zmq_msg_size (zmq_msg_t *msg) 116 | { 117 | return zmq_msg_size(msg); 118 | } 119 | 120 | /******************************************************************************/ 121 | /* 0MQ infrastructure (a.k.a. context) initialisation & termination. */ 122 | /******************************************************************************/ 123 | ZMQ_EXPORT void* WINAPI mql4zmq_init (int io_threads) 124 | { 125 | return zmq_init(io_threads); 126 | } 127 | 128 | ZMQ_EXPORT int WINAPI mql4zmq_term (void *context) 129 | { 130 | return zmq_term(context); 131 | } 132 | 133 | /******************************************************************************/ 134 | /* 0MQ socket definition. */ 135 | /******************************************************************************/ 136 | ZMQ_EXPORT void* WINAPI mql4zmq_socket (void *context, int type) 137 | { 138 | return zmq_socket(context, type); 139 | } 140 | 141 | ZMQ_EXPORT int WINAPI mql4zmq_close (void *s) 142 | { 143 | return zmq_close(s); 144 | } 145 | 146 | ZMQ_EXPORT int WINAPI mql4zmq_setsockopt (void *s, int option, const void *optval, size_t optvallen) 147 | { 148 | return zmq_setsockopt(s, option, optval, optvallen); 149 | } 150 | 151 | ZMQ_EXPORT int WINAPI mql4zmq_getsockopt (void *s, int option, void *optval, size_t *optvallen) 152 | { 153 | return zmq_getsockopt(s, option, optval, optvallen); 154 | } 155 | 156 | ZMQ_EXPORT int WINAPI mql4zmq_bind (void *s, const char *addr) 157 | { 158 | return zmq_bind(s, addr); 159 | } 160 | 161 | ZMQ_EXPORT int WINAPI mql4zmq_connect (void *s, const char *addr) 162 | { 163 | return zmq_connect(s, addr); 164 | } 165 | 166 | ZMQ_EXPORT int WINAPI mql4zmq_send (void *s, zmq_msg_t *msg, int flags) 167 | { 168 | return zmq_send (s, msg, flags); 169 | } 170 | 171 | ZMQ_EXPORT int WINAPI mql4zmq_recv (void *s, zmq_msg_t *msg, int flags) 172 | { 173 | return zmq_recv(s, msg, flags); 174 | } 175 | 176 | /******************************************************************************/ 177 | /* I/O multiplexing. */ 178 | /******************************************************************************/ 179 | ZMQ_EXPORT int WINAPI mql4zmq_poll (zmq_pollitem_t *items, int nitems, long timeout) 180 | { 181 | return zmq_poll(items, nitems, timeout); 182 | } 183 | 184 | /******************************************************************************/ 185 | /* Built-in devices */ 186 | /******************************************************************************/ 187 | ZMQ_EXPORT int WINAPI mql4zmq_device (int device, void * insocket, void* outsocket) 188 | { 189 | return zmq_device(device, insocket, outsocket); 190 | } 191 | 192 | /******************************************************************************/ 193 | /* A Couple Helper Functions For Building Apps More Quickly. */ 194 | /* Taken from the Z-Guide file at: https://github.com/imatix/zguide/blob/master/examples/C/zhelpers.h 195 | /******************************************************************************/ 196 | 197 | // Receive 0MQ string from socket and convert into C string 198 | // Caller must free returned string. Returns NULL if the context 199 | // is being terminated. 200 | ZMQ_EXPORT const char* WINAPI mql4s_recv (void* socket, int flags) 201 | { 202 | // Strict "C" spec has to be followed because we outputing the function as 'extern "C"' (see mql4zmq.h). 203 | // Hence specifing our variables right away instead of inline. 204 | char* string; 205 | int size; 206 | 207 | // Initialize message. 208 | zmq_msg_t message; 209 | zmq_msg_init(&message); 210 | 211 | // Receive the inbound message. 212 | if (zmq_recv (socket, &message, flags)) 213 | return (NULL); // No message received 214 | 215 | // Retrive message size. 216 | size = zmq_msg_size(&message); 217 | 218 | // Initialize variable to hold the message. 219 | string = malloc (size + 1); 220 | 221 | // Retrive pointer to message data and store message in variable 'string' 222 | memcpy (string, zmq_msg_data (&message), size); 223 | 224 | // Deallocate message buffer. 225 | zmq_msg_close (&message); 226 | 227 | // Return the message. 228 | string [size] = 0; 229 | return (string); 230 | } 231 | 232 | // Convert C string to 0MQ string and send to socket 233 | ZMQ_EXPORT int WINAPI mql4s_send (void *socket, char *text) 234 | { 235 | // Strict "C" spec has to be followed because we outputing the function as 'extern "C"' (see mql4zmq.h). 236 | // Hence specifing our variables right away instead of inline. 237 | int result; 238 | 239 | // Initialize message. 240 | zmq_msg_t message; 241 | 242 | // Set the message to have a spcified length. 243 | zmq_msg_init_size (&message, strlen (text)); 244 | 245 | // Place the specified value of variable 'string' inside of the message buffer. 246 | memcpy (zmq_msg_data (&message), text, strlen (text)); 247 | 248 | // Stream the message to the specified socket. 249 | result = zmq_send (socket, &message, 0); 250 | 251 | // Deallocate the message. 252 | zmq_msg_close (&message); 253 | 254 | // Return the response of the zmq_send call. 0 is success, -1 is error. 255 | return (result); 256 | } 257 | 258 | // Sends string as 0MQ string, as multipart non-terminal 259 | ZMQ_EXPORT int WINAPI mql4s_sendmore (void *socket, char *text) 260 | { 261 | // Strict "C" spec has to be followed because we outputing the function as 'extern "C"' (see mql4zmq.h). 262 | // Hence specifing our variables right away instead of inline. 263 | int result; 264 | 265 | // Initialize message. 266 | zmq_msg_t message; 267 | 268 | // Set the message to have a spcified length. 269 | zmq_msg_init_size (&message, strlen (text)); 270 | 271 | // Place the specified value of variable 'string' inside of the message buffer. 272 | memcpy (zmq_msg_data (&message), text, strlen (text)); 273 | 274 | // Stream the message to the specified socket. 275 | result = zmq_send (socket, &message, ZMQ_SNDMORE); 276 | 277 | // Deallocate the message. 278 | zmq_msg_close (&message); 279 | 280 | // Return the response of the zmq_send call. 0 is success, -1 is error. 281 | return (result); 282 | } 283 | -------------------------------------------------------------------------------- /mql4zmq.def: -------------------------------------------------------------------------------- 1 | LIBRARY "mql4zmq" 2 | EXPORTS 3 | ping 4 | mql4zmq_version 5 | 6 | mql4zmq_errno 7 | mql4zmq_strerror 8 | 9 | mql4zmq_msg_init 10 | mql4zmq_msg_init_size 11 | mql4zmq_msg_init_data 12 | mql4zmq_msg_close 13 | mql4zmq_msg_move 14 | mql4zmq_msg_copy 15 | mql4zmq_msg_data 16 | mql4zmq_msg_size 17 | 18 | mql4zmq_init 19 | mql4zmq_term 20 | 21 | mql4zmq_socket 22 | mql4zmq_close 23 | mql4zmq_setsockopt 24 | mql4zmq_getsockopt 25 | mql4zmq_bind 26 | mql4zmq_connect 27 | mql4zmq_send 28 | mql4zmq_recv 29 | 30 | mql4zmq_poll 31 | 32 | mql4zmq_device 33 | 34 | mql4s_recv 35 | mql4s_send 36 | mql4s_sendmore 37 | -------------------------------------------------------------------------------- /mql4zmq.h: -------------------------------------------------------------------------------- 1 | /* 2 | MQL4ZMQ - MQL4 bindings for ZeroMQ 3 | 4 | (c) 2012 Austen Conrad. Any of this software, or any part thereof, is allowed as long as the use complies with GPL v3.0: http://www.gnu.org/licenses/gpl-3.0-standalone.html 5 | Additionally, no warrenty of any kind is made. Use software at own risk. 6 | 7 | =================================== 8 | 9 | The reason for all of this is that MetaTrader is a visual basic application and therefore is written using the STDCALL calling 10 | convention while ZeroMQ dll EXPORT defaults to the standard C calling convention (CDECL). If not changed, a call to 11 | libzmq.dll from MetaTrader will result in the trading terminal crashing. 12 | 13 | Therefore, this file generates mql4zmq.dll which wraps each call the zmq.h exports when compiled as libzmq.dll (i.e. each function 14 | that has ZMQ_EXPORT preceeding it) as a STDCALL instead (i.e. __stdcall via WINAPI definition). 15 | 16 | Additionally, MetaTrader4 has limitations on datatypes and data structures that we attempt to resolve by having the wrapping funtion 17 | inputs being of a type and in a manner that will jive with MQL4. 18 | 19 | NOTE: Remember to add a link to the "libzmq.lib" file that is created upon building of libzmq to the mql4zmq project via: Add => Existing Item => ../Debug/libzmq.lib 20 | This .lib file exposes all of the exported functions of the libzmq.dll for use with our program as referenced per zmq.h. 21 | Also add the "mql4zmq.def" file to the linker input via: Properties => Configuration Properties => Linker => Input => Module Definition File, 22 | and to change the linker settings from "Windows" to "Console" via: Properties => Configuration Properties => Linker => System => Subsystem. 23 | 24 | NAMING NOTE: To avoid naming collisions with the original zmq.h definitions we renamed our exported functions with 'mql4' appended to the beginning of the name. 25 | In the mql4zmq.mqh we revert the names back to the original to reduce confusion when writing experts. 26 | 27 | libzmq.dll NOTE: After building the solution, copy ../../../lib/libzmq.dll to c:\Windows\SysWOW64\libzmq.dll so that our bindings and other applications can access ZeroMQ. 28 | 29 | */ 30 | 31 | //Setup for "C" linkage instead of "C++" linkage. 32 | extern "C" { 33 | // Hello World test function. 34 | const char* ping (const char* pong); 35 | 36 | // zhelper functions. 37 | const char* mql4s_recv (void* socket, int flags); 38 | int mql4s_send (void *socket, char *text); 39 | int mql4s_sendmore (void *socket, char *text); 40 | } -------------------------------------------------------------------------------- /mql4zmq.mqh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AustenConrad/mql4zmq/19493dbc26635ac4459fee6cb01688cdc407fc08/mql4zmq.mqh -------------------------------------------------------------------------------- /mql4zmq.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {967C2371-4463-4BEC-97F7-63C15DF52A48} 15 | Win32Proj 16 | mql4zmq 17 | 18 | 19 | 20 | DynamicLibrary 21 | true 22 | Unicode 23 | 24 | 25 | DynamicLibrary 26 | false 27 | true 28 | Unicode 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | true 42 | 43 | 44 | false 45 | 46 | 47 | 48 | 49 | 50 | Level3 51 | Disabled 52 | WIN32;_DEBUG;_WINDOWS;_USRDLL;MQL4ZMQ_EXPORTS;%(PreprocessorDefinitions) 53 | Cdecl 54 | MultiThreadedDebugDLL 55 | 56 | 57 | Console 58 | true 59 | mql4zmq.def 60 | 61 | 62 | 63 | 64 | Level3 65 | 66 | 67 | MaxSpeed 68 | true 69 | true 70 | WIN32;NDEBUG;_WINDOWS;_USRDLL;MQL4ZMQ_EXPORTS;%(PreprocessorDefinitions) 71 | MultiThreadedDLL 72 | 73 | 74 | Console 75 | true 76 | true 77 | true 78 | mql4zmq.def 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /mql4zmq.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /mql4zmq.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /pre-compiled/libzmq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AustenConrad/mql4zmq/19493dbc26635ac4459fee6cb01688cdc407fc08/pre-compiled/libzmq.dll -------------------------------------------------------------------------------- /pre-compiled/mql4zmq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AustenConrad/mql4zmq/19493dbc26635ac4459fee6cb01688cdc407fc08/pre-compiled/mql4zmq.dll --------------------------------------------------------------------------------