├── .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 |