├── .github └── ISSUE_TEMPLATE.md ├── .gitignore ├── CHANGELOG.txt ├── LICENSE.txt ├── MQL4 ├── Include │ └── OTMql4 │ │ ├── OTBarInfo.mqh │ │ ├── OTLibConstants.mqh │ │ ├── OTLibJsonFormat.mqh │ │ ├── OTLibLog.mqh │ │ ├── OTLibMt4ProcessCmd.mqh │ │ ├── OTLibProcessCmd.mqh │ │ ├── OTLibServerErrors.mqh │ │ ├── OTLibSimpleFormatCmd.mqh │ │ ├── OTLibStrings.mqh │ │ └── OTLibTrading.mqh ├── Libraries │ └── OTMql4 │ │ ├── OTLibJsonFormat.mq4 │ │ ├── OTLibLog.mq4 │ │ ├── OTLibMt4ProcessCmd.mq4 │ │ ├── OTLibProcessCmd.mq4 │ │ ├── OTLibServerErrors.mq4 │ │ ├── OTLibSimpleFormatCmd.mq4 │ │ ├── OTLibStrings.mq4 │ │ └── OTLibTrading.mq4 ├── Python │ └── __init__.py └── Scripts │ └── OTMql4 │ └── OTLibTest.mq4 ├── README.creole ├── share └── html │ ├── CodeLibraries.html │ ├── CodeScripts.html │ ├── DevelopmentStyle.html │ ├── DirectoryStructure.html │ ├── FrontPage.html │ ├── Home.html │ ├── Installation.html │ ├── OTLibJsonFormat.html │ ├── OTLibLog.html │ ├── OTLibMt4ProcessCmd.html │ ├── OTLibProcessCmd.html │ ├── OTLibServerErrors.html │ ├── OTLibSimpleFormatCmd.html │ ├── OTLibStrings.html │ ├── OTLibTest.html │ ├── OTLibTrading.html │ └── TitleIndex.html └── wiki ├── CodeLibraries.creole ├── CodeScripts.creole ├── DevelopmentStyle.creole ├── DirectoryStructure.creole ├── FrontPage.creole ├── Home.creole ├── Installation.creole ├── OTLibJsonFormat.creole ├── OTLibLog.creole ├── OTLibMt4ProcessCmd.creole ├── OTLibProcessCmd.creole ├── OTLibServerErrors.creole ├── OTLibSimpleFormatCmd.creole ├── OTLibStrings.creole ├── OTLibTest.creole ├── OTLibTrading.creole ├── TitleIndex.creole ├── _Footer.creole └── _Sidebar.creole /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Essential information for reporting Issues: 2 | * What version of Windows and 32/64 bit: 3 | * What Build number of Metatrader: 4 | * Where was the Metatrader installed from: 5 | * OTMql4Lib from git, or what version of the OTMql4Lib installer: 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | Makefile 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .cache 41 | nosetests.xml 42 | coverage.xml 43 | 44 | # Translations 45 | *.mo 46 | *.pot 47 | 48 | # Django stuff: 49 | *.log 50 | 51 | # Sphinx documentation 52 | docs/_build/ 53 | 54 | # PyBuilder 55 | target/ 56 | Manifest.in 57 | -------------------------------------------------------------------------------- /CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | commit 843f605b208d910a595cf327c3a58796da022770 2 | Date: Wed Feb 24 23:46:44 2016 +0200 3 | 4 | Tagged 1.1.0.1 5 | 6 | commit 7158d0b9059121d4a721c136dec10af6b9ea5ba6 7 | Date: Wed Feb 24 23:32:28 2016 +0200 8 | 9 | Fixed documentation in Creole format 10 | 11 | commit c6384c252926ef06ccda0a4d7e16765a1948f141 12 | Date: Tue Feb 23 16:40:57 2016 +0200 13 | 14 | Tagged 1.1.0.0 15 | 16 | commit 0fd99b1870146d596c652a3a8fccd23a2421607e 17 | Date: Tue Feb 23 16:35:15 2016 +0200 18 | 19 | Updated documentation 20 | 21 | commit 3d842d88f43cfcfd0135ede57cb12240684ad040 22 | Date: Mon Feb 22 16:02:46 2016 +0200 23 | 24 | Updated documentation 25 | 26 | commit e8c0c97cda8b82e4c7a3c191c443b3e6544e9028 27 | Date: Mon Feb 22 02:43:27 2016 +0200 28 | 29 | Updated documentation 30 | 31 | commit 1a237f87d70c1cdd62240a141092bdfac970367d 32 | Date: Sun Feb 21 05:45:59 2016 +0200 33 | 34 | Added more documentation in Creole format 35 | 36 | commit ed42a5ced1c810f8229371ca53dd229016738191 37 | Date: Sun Feb 21 00:39:16 2016 +0200 38 | 39 | Fixed documentation in Creole format 40 | 41 | commit ce5a63ada7ca5c899dd2bacf3499abf44b5d900f 42 | Date: Sun Feb 21 00:23:02 2016 +0200 43 | 44 | Fixed documentation in Creole format 45 | 46 | commit 6b38527436f6e124ce1c599edd18461f2a8b36e3 47 | Date: Sat Feb 20 08:11:31 2016 +0200 48 | 49 | Updated documentation 50 | 51 | commit d91f017369b823a44e5825a70305a9d656df3e7c 52 | Date: Fri Feb 19 21:04:39 2016 +0200 53 | 54 | More documentation of the library code 55 | 56 | commit 7ff5031e7e878ba12a108065dbb705485037d004 57 | Date: Fri Feb 19 20:54:54 2016 +0200 58 | 59 | Started to document the library code 60 | 61 | commit 03db482cdb7871ea87da85cd018f949bdaac2970 62 | Date: Fri Feb 19 19:50:35 2016 +0200 63 | 64 | Moved documentation to a creole format 65 | 66 | commit 8d1cfeb3addfb166a2160e8444771fb1507124e0 67 | Date: Fri Feb 19 19:28:01 2016 +0200 68 | 69 | Moved documentation to a wiki format 70 | 71 | commit ef308d4bc7b884f2a7a4d003a0d39ae19e8b5c33 72 | Date: Fri Aug 21 19:10:05 2015 +0300 73 | 74 | Wired up the global variable fDebugLevel 75 | 76 | commit 1b3f74cc3a7723823897949994f1a7a170201b71 77 | Date: Wed Jul 29 01:55:14 2015 +0300 78 | 79 | Minor bug fixes 80 | 81 | commit 573344db27a96d9c4e45d22c0b9661c1a44ed225 82 | Date: Mon Jul 13 20:22:02 2015 +0300 83 | 84 | Tried to fix communications for errors but it still needs a rewrite 85 | 86 | commit 0eaaf19bb188f1431c09f132fb814e881f81e52f 87 | Date: Sun Jul 12 23:48:44 2015 +0300 88 | 89 | Fixed test Scripts 90 | 91 | commit 84ef060d4717fbe6542f9232425d7f6a4e991a7b 92 | Date: Sun Jul 12 22:32:09 2015 +0300 93 | 94 | Quiet traces until verbose is working 95 | 96 | commit 2b1dfba8af5bcf6abf15c38477ffa0b588fb99ff 97 | Date: Fri Jun 19 17:19:15 2015 +0300 98 | 99 | Refactored SMARK For ZmqCmd 100 | 101 | commit 9d9020fd2f26062423bdc9328eb4e592b52a596d 102 | Date: Thu Jun 4 21:25:23 2015 +0300 103 | 104 | Fixed order close functions and added OrderCloseMarket. 105 | 106 | commit 4ef3e1ff34ca8ae25b2a22ebecfd036fed1ec725 107 | Date: Wed Jun 3 09:49:56 2015 +0300 108 | 109 | Cleaned up the OrderSend functions and extened the ProcessCmds. 110 | 111 | commit 57205bad1d4c9908b1a19d7f3be056dfebd79540 112 | Date: Wed May 20 23:15:13 2015 +0300 113 | 114 | Trading and JSON bugfixes. 115 | 116 | commit 69592b42c3480d35ad12fefcc4b4ac6f6cb56976 117 | Date: Tue May 19 20:53:06 2015 +0300 118 | 119 | Bugfixes to JSON formatting. 120 | 121 | commit fc2985c793abc78f73fa87002ab146ba358a6a8b 122 | Date: Mon May 18 15:36:46 2015 +0300 123 | 124 | Added MQL4/Libraries/OTMql4/OTLibJsonFormat.mq4 to start sending 125 | info to the client as JSON. Just cheap string formatting for now. 126 | 127 | commit dc3fce25c8d37d6cbc349a766dd3551e00495b72 128 | Date: Fri May 15 11:27:32 2015 +0300 129 | 130 | Refactoring to pull common code from OTMql4AMQP and OTMql4Zmq into OTMql4Py. 131 | 132 | commit 33538a11e74ff9b220e1587a89fe020495aa3871 133 | Date: Fri May 8 19:09:40 2015 +0300 134 | 135 | Minor refactoring. 136 | 137 | commit 9bed4c4d72ddd399a11e2453128a3a6f6724fe95 138 | Date: Thu May 7 01:08:05 2015 +0300 139 | 140 | Refactored the Simple command format. 141 | 142 | commit c0d34605110a18b9c629fdd9f2f38663f3b631f5 143 | Date: Wed May 6 16:05:29 2015 +0300 144 | 145 | Started formalizing the formatting and unformatting of commands. 146 | 147 | commit c82c716174ae6a76cbfd5a3e75c83f77354608b5 148 | Date: Tue May 5 19:34:53 2015 +0300 149 | 150 | Minor changes to support OTMqlAMQP. 151 | 152 | commit c0b1c9746d1f188ea436426adc32a01ae830db2f 153 | Date: Sat May 2 14:39:09 2015 +0300 154 | 155 | Moved in MQL4/Include/OTMql4/OTBarInfo.mqh from OTMql4Zmq. 156 | 157 | commit 3462b96932d6e36f5bde1609c924b291585c420f 158 | Date: Fri May 1 17:53:04 2015 +0300 159 | 160 | Added share/doc/30DirectoryStructure.txt 161 | 162 | commit ad482e1237f55ba0086dabbf607c10a332519f10 163 | Date: Thu Apr 23 20:56:12 2015 +0300 164 | 165 | Added some tests o OTLibTest.mq4. 166 | 167 | commit 3bdcba29b5fa3680ddabc3c9c1ef27b677122c93 168 | Date: Thu Apr 23 16:58:14 2015 +0300 169 | 170 | Refactored OTLibProcessCmd.mqh into OTLibMt4ProcessCmd.mqh 171 | and OTZmqProcessCmd.mqh to make it easier for people to reuse 172 | ProcessCmd with the OT additions, and to extend it to handle 173 | their own additions. 174 | 175 | Added the beginning of tests in Script/OTMql4/OTLibTest.mq4 176 | 177 | commit 60ab34c439c0d8787ecc516077c8bc7008340722 178 | Date: Mon Apr 13 20:33:22 2015 +0300 179 | 180 | Added documentation on naming conventions in share/doc/09Development.txt 181 | 182 | commit c38dc2cf8c3cf55f824832f98e19141b5b385637 183 | Date: Thu Apr 2 20:03:22 2015 +0300 184 | 185 | Moved libraries into Libraries/OTMql4 to keep things tidy. 186 | 187 | commit c5d834ec067e2f29eeceb17fc8a7b89932dec978 188 | Date: Thu Apr 2 17:52:28 2015 +0300 189 | 190 | Updated Readme. 191 | 192 | commit dd49c2f0129ad5ca46728e7e8aded3bcdd319161 193 | Date: Thu Apr 2 17:21:17 2015 +0300 194 | 195 | Updated the README. 196 | 197 | commit 34af5914be82c029c99a7e475ee466477e7ab887 198 | Date: Mon Mar 30 05:40:11 2015 +0300 199 | 200 | First checkin of our library for Mql4 - untested WIP. 201 | 202 | commit 1dde6188c6ddaecec29e4fd196e6d93dc54e2c40 203 | Date: Sun Mar 29 18:18:59 2015 +0300 204 | 205 | Started with some documentation. 206 | 207 | commit d83ed7428e4d1a4256691e0af7151a36133c2c56 208 | Date: Sun Mar 29 01:20:47 2015 +0200 209 | 210 | Initial commit 211 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | 167 | -------------------------------------------------------------------------------- /MQL4/Include/OTMql4/OTBarInfo.mqh: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | /* 4 | This is a stub for the info we want put on the 0MQ wire. 5 | We will probably change the formating to be json or FITS. 6 | */ 7 | 8 | #property copyright "Copyright 2014 Open Trading" 9 | #property link "https://github.com/OpenTrading/" 10 | 11 | extern int iFastEMA=12; 12 | extern int iSlowEMA=26; 13 | extern int iSignalSMA=9; 14 | extern int iStochKperiod=5; 15 | extern int iStochDperiod=3; 16 | extern int iStochSlowing=3; 17 | 18 | string uBarInfo() { 19 | string sInfo; 20 | 21 | sInfo="iMACD="+iMACD(NULL, 0, iFastEMA, iSlowEMA, iSignalSMA, 22 | PRICE_CLOSE, MODE_MAIN,0); 23 | sInfo=sInfo+",iMA="+iMA(NULL, 0 , iFastEMA, 0, MODE_LWMA, PRICE_MEDIAN, 0); 24 | sInfo=sInfo+",iStochasticMain="+iStochastic(NULL, 0, iStochKperiod, iStochDperiod, iStochSlowing, 25 | MODE_SMA,0,MODE_MAIN,0); 26 | sInfo=sInfo+",iStochasticSignal="+iStochastic(NULL, 0, iStochKperiod, iStochDperiod, iStochSlowing, 27 | MODE_SMA,0,MODE_SIGNAL,0); 28 | return (sInfo); 29 | } 30 | -------------------------------------------------------------------------------- /MQL4/Include/OTMql4/OTLibConstants.mqh: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | #property copyright "Copyright 2013 OpenTrading" 4 | #property link "https://github.com/OpenTrading/" 5 | 6 | #define OT_MAX_TICK_RETRIES 10 7 | #define OT_TICK_SLEEP_MSEC 100 8 | 9 | #define OT_TRADE_MAX_ORDERS 10 10 | #define OT_TRADE_MAX_ORDER_RETRIES 20 11 | #define OT_TRADE_ORDER_SLEEP_MSEC 1000 12 | -------------------------------------------------------------------------------- /MQL4/Include/OTMql4/OTLibJsonFormat.mqh: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | #property copyright "Copyright 2013 OpenTrading" 4 | #property link "https://github.com/OpenTrading/" 5 | 6 | #import "OTMql4/OTLibJsonFormat.ex4" 7 | 8 | string jOTAccountInformation(); 9 | string jOTOrdersTickets(); 10 | string jOTOrdersTrades(); 11 | string jOTOrdersHistory(); 12 | string jOTOrders(int iMode); 13 | string jOTOrderInformationByTicket(int iTicket); 14 | string jOTMarketInformation(string uSymbol); 15 | string jOTTickInformation(string uSymbol, int iTimeFrame); 16 | string jOTBarInformation(string uSymbol, int iTimeFrame, int iBar); 17 | string jOTTimerInformation(); 18 | -------------------------------------------------------------------------------- /MQL4/Include/OTMql4/OTLibLog.mqh: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | /* 4 | This is just a stub for a full logging system later. 5 | */ 6 | #property copyright "Copyright 2014 Open Trading" 7 | #property link "https://github.com/OpenTrading/" 8 | 9 | #import "OTMql4/OTLibLog.ex4" 10 | 11 | void vLogInit(); 12 | void vSetLogLevel(int i); 13 | int iGetLogLevel(); 14 | 15 | void vLog(int iLevel, string sMsg); 16 | void vError(string sMess); 17 | void vWarn(string sMess); 18 | void vInfo(string sMess); 19 | void vDebug(string sMess); 20 | void vTrace(string sMess); 21 | -------------------------------------------------------------------------------- /MQL4/Include/OTMql4/OTLibMt4ProcessCmd.mqh: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | #property copyright "Copyright 2015 Open Trading" 4 | #property link "https://github.com/OpenTrading/" 5 | 6 | #import "OTMql4/OTLibMt4ProcessCmd.ex4" 7 | 8 | string zOTLibMt4ProcessCmd(string uMess); 9 | -------------------------------------------------------------------------------- /MQL4/Include/OTMql4/OTLibProcessCmd.mqh: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | #property copyright "Copyright 2015 Open Trading" 4 | #property link "https://github.com/OpenTrading/" 5 | 6 | #import "OTMql4/OTLibProcessCmd.ex4" 7 | 8 | string zOTLibProcessCmd(string uMess); 9 | string uProcessCmdi(string uCmd, string uChartId, string uIgnore, string uMark, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5, string uArg6, string uArg7); 10 | string uProcessCmdOT(string uCmd, string uChartId, string uIgnore, string uMark, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5, string uArg6, string uArg7); 11 | string uProcessCmdgOT(string uCmd, string uChartId, string uIgnore, string uMark, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5, string uArg6, string uArg7); 12 | 13 | 14 | -------------------------------------------------------------------------------- /MQL4/Include/OTMql4/OTLibServerErrors.mqh: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | #property copyright "Copyright 2013 OpenTrading" 4 | #property link "https://github.com/OpenTrading/" 5 | 6 | #import "OTMql4/OTLibServerErrors.ex4" 7 | 8 | bool bOTLibServerErrorIsContinuable(int iErr); 9 | bool bOTLibServerErrorType(int iErr); 10 | 11 | -------------------------------------------------------------------------------- /MQL4/Include/OTMql4/OTLibSimpleFormatCmd.mqh: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | #property copyright "Copyright 2015 Open Trading" 4 | #property link "https://github.com/OpenTrading/" 5 | 6 | // our string delimiter 7 | #define uBAR "|" 8 | 9 | #import "OTMql4/OTLibSimpleFormatCmd.ex4" 10 | 11 | string eOTLibSimpleUnformatCmd(string& aArrayAsList[]); 12 | 13 | string zOTLibSimpleFormatCmd(string uType, string uChartId, int iIgnore, string uMark, string uCmd); 14 | string zOTLibSimpleFormatBar(string uType, string uChartId, int iIgnore, string uMark, string uInfo); 15 | string zOTLibSimpleFormatTimer(string uType, string uChartId, int iIgnore, string uMark, string uInfo); 16 | string zOTLibSimpleFormatTick(string uType, string uChartId, int iIgnore, string uMark, string uInfo); 17 | string zOTLibSimpleFormatRetval(string uType, string uChartId, int iIgnore, string uMark, string uInfo); 18 | -------------------------------------------------------------------------------- /MQL4/Include/OTMql4/OTLibStrings.mqh: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | /* 4 | Miscellaneous functions that help handling strings. 5 | 6 | This includes Ansi to Unicode "issues". 7 | 8 | */ 9 | 10 | #property copyright "Copyright 2015, OpenTrading" 11 | #property link "https://github.com/OpenTrading/" 12 | 13 | #import "OTMql4/OTLibStrings.ex4" 14 | 15 | string uAnsi2Unicode(int ptrStringMemory); 16 | void vStringToArray(string uInput, string& uOutput[], string uDelim); 17 | string uStringReplace(string uHaystack, string uNeedle, string uReplace); 18 | -------------------------------------------------------------------------------- /MQL4/Include/OTMql4/OTLibTrading.mqh: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | #property copyright "Copyright 2013 OpenTrading" 4 | #property link "https://github.com/OpenTrading/" 5 | 6 | #import "OTMql4/OTLibTrading.ex4" 7 | 8 | int iOTOrderSelect(int iIndex, int iSelect, int iPool); 9 | int iOTOrderSendMarket(string sSymbol, int cmd, double fVolume, 10 | int iStops=3, int iProfits=10, int slippage=3); 11 | int iOTOrderSend(string sSymbol, int cmd, 12 | double volume, double price, int slippage, 13 | double stoploss, double takeprofit, 14 | string comment="", int magic=0, datetime expiration=0, 15 | color arrow_color=CLR_NONE); 16 | int iOTOrderCloseMarket(int iTicket, int iSlippage=3, color cColor=CLR_NONE); 17 | int iOTOrderCloseFull(int iTicket, double fPrice, int iSlippage=3, color cColor=CLR_NONE); 18 | int iOTOrderClose(int iTicket, double fLots, double fPrice, int iSlippage, color cColor=CLR_NONE); 19 | 20 | int iOTSetTradeIsBusy(int iMaxWaitingSeconds); 21 | int iOTSetTradeIsNotBusy(); 22 | 23 | double fOTExposedEcuInMarket(int iOrderEAMagic); 24 | bool bOTIsTradeAllowed(); 25 | int iOTRefreshRates(); 26 | int iOTMarketInfo(string s, int iMode); 27 | double fOTMarketInfo(string s, int iMode); 28 | bool bOTModifyTrailingStopLoss(string sSymbol, int iTrailingStopLossPoints, 29 | datetime tExpiration); 30 | bool bOTModifyOrder(string sMsg, 31 | int iTicket, 32 | double fPrice, 33 | double fStopLoss, 34 | double fTakeProfit, 35 | datetime tExpiration); 36 | bool bOTContinueOnOrderError(int iTicket); 37 | -------------------------------------------------------------------------------- /MQL4/Libraries/OTMql4/OTLibJsonFormat.mq4: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | #property copyright "Copyright 2015 OpenTrading" 4 | #property link "https://github.com/OpenTrading/" 5 | #property library 6 | 7 | // JSON formatting for sending information to clients. 8 | // This is simple string formatting: a JSON structure or class is never used. 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | string jOTAccountInformation() { 18 | // Retrieve the Account information as a JSON structure. 19 | // This brings back all of the ususal Account* calls, 20 | // with the values formatted as strings, intergers or floats. 21 | // 22 | string uRetval; 23 | 24 | // FixMe: coalesce 25 | uRetval = "{"; 26 | uRetval += StringFormat("\"status\": \"%s\", ", "ok"); 27 | uRetval += StringFormat("\"balance\": %f, ", AccountBalance()); // Decimal 28 | uRetval += StringFormat("\"credit\": %f, ", AccountCredit()); // Decimal 29 | uRetval += StringFormat("\"company\": \"%s\", ", AccountCompany()); 30 | uRetval += StringFormat("\"currency\": \"%s\", ", AccountCurrency()); 31 | uRetval += StringFormat("\"equity\": %f, ", AccountEquity()); // Decimal 32 | uRetval += StringFormat("\"free_margin\": %f, ", AccountFreeMargin()); // Decimal 33 | uRetval += StringFormat("\"free_margin_mode\": %f, ", AccountFreeMarginMode()); 34 | uRetval += StringFormat("\"leverage\": %i, ", AccountLeverage()); 35 | uRetval += StringFormat("\"margin\": %f, ", AccountMargin()); // Decimal 36 | uRetval += StringFormat("\"name\": \"%s\", ", AccountName()); 37 | uRetval += StringFormat("\"number\": %i, ", AccountNumber()); 38 | uRetval += StringFormat("\"profit\": %f, ", AccountProfit()); // Decimal 39 | uRetval += StringFormat("\"server\": \"%s\", ", AccountServer()); 40 | uRetval += StringFormat("\"stopout_level\": %i, ", AccountStopoutLevel()); //? 41 | uRetval += StringFormat("\"stopout_mode\": %i", AccountStopoutMode()); //? 42 | uRetval += "}"; 43 | return(uRetval); 44 | } 45 | 46 | string jOTOrdersTickets() { 47 | string uRetval; 48 | int iRetval; 49 | int i; 50 | 51 | uRetval = "["; 52 | for(i=OrdersTotal()-1; i>=0; i--) { 53 | iRetval = iOTOrderSelect(i, SELECT_BY_POS, MODE_TRADES); 54 | if (iRetval < 0) {continue;} 55 | if (uRetval != "[") uRetval += ", "; 56 | uRetval += StringFormat("%i", OrderTicket()); 57 | } 58 | uRetval += "]"; 59 | return(uRetval); 60 | } 61 | 62 | string jOTOrdersTrades() { 63 | return(jOTOrders(MODE_TRADES)); 64 | } 65 | 66 | string jOTOrdersHistory() { 67 | return(jOTOrders(MODE_HISTORY)); 68 | } 69 | 70 | string jOTOrders(int iMode) { 71 | string uRetval, uReason; 72 | int i, iRetval, iTicket; 73 | 74 | uRetval = "["; 75 | for(i=OrdersTotal()-1; i>=0; i--) { 76 | iRetval = iOTOrderSelect(i, SELECT_BY_POS, iMode); 77 | if (iRetval <= 0) { 78 | uReason = ErrorDescription(GetLastError()); 79 | vWarn("Select order failed " + 80 | " for pos " + i + ": " + uReason); 81 | } else { 82 | if (uRetval != "[") uRetval += ", "; 83 | iTicket = OrderTicket(); 84 | uRetval += jOTOrderInformationByTicket(iTicket); 85 | } 86 | } 87 | uRetval += "]"; 88 | return(uRetval); 89 | } 90 | 91 | string jOTOrderInformationByTicket(int iTicket) { 92 | string uRetval, uReason; 93 | int iRetval; 94 | 95 | // FixMe: coalesce 96 | uRetval = "{"; 97 | iRetval = iOTOrderSelect(iTicket, SELECT_BY_TICKET, MODE_TRADES); 98 | if (iRetval <= 0) { 99 | uReason = ErrorDescription(GetLastError()); 100 | vWarn("Select order failed " + 101 | " for order " + iTicket + ": " + uReason); 102 | uRetval += StringFormat("\"status\": \"%s\", ", "failed"); 103 | uRetval += StringFormat("\"reason\": \"%s\"", uReason); 104 | } else { 105 | uRetval += StringFormat("\"ticket\": %i, ", OrderTicket()); 106 | uRetval += StringFormat("\"symbol\": \"%s\", ", OrderSymbol()); 107 | uRetval += StringFormat("\"status\": \"%s\", ", "ok"); 108 | uRetval += StringFormat("\"opentime\": %i, ", OrderOpenTime()); 109 | uRetval += StringFormat("\"type\": %i, ", OrderType()); 110 | uRetval += StringFormat("\"lots\": %f, ", OrderLots()); 111 | uRetval += StringFormat("\"openprice\": %f, ", OrderOpenPrice()); 112 | uRetval += StringFormat("\"stoploss\": %f, ", OrderStopLoss()); 113 | uRetval += StringFormat("\"takeprofit\": %f, ", OrderTakeProfit()); 114 | uRetval += StringFormat("\"closetime\": %i, ", OrderCloseTime()); 115 | uRetval += StringFormat("\"closeprice\": %f, ", OrderClosePrice()); 116 | uRetval += StringFormat("\"commission\": %f, ", OrderCommission()); 117 | uRetval += StringFormat("\"swap\": %f, ", OrderSwap()); 118 | uRetval += StringFormat("\"profit\": %f, ", OrderProfit()); 119 | uRetval += StringFormat("\"comment\": \"%s\", ", OrderComment()); 120 | uRetval += StringFormat("\"magicnumber\": %i", OrderMagicNumber()); 121 | } 122 | uRetval += "}"; 123 | return(uRetval); 124 | } 125 | 126 | string jOTMarketInformation(string uSymbol) { 127 | string uRetval; 128 | 129 | // FixMe: coalesce 130 | uRetval = "{"; 131 | uRetval += StringFormat("\"symbol\": \"%s\", ", uSymbol); 132 | uRetval += StringFormat("\"low\": %f, ", MarketInfo(uSymbol, MODE_LOW)); 133 | uRetval += StringFormat("\"high\": %f, ", MarketInfo(uSymbol, MODE_HIGH)); 134 | uRetval += StringFormat("\"time\": %d, ", MarketInfo(uSymbol, MODE_TIME));//fix 135 | uRetval += StringFormat("\"bid\": %f, ", MarketInfo(uSymbol, MODE_BID)); 136 | uRetval += StringFormat("\"ask\": %f, ", MarketInfo(uSymbol, MODE_ASK)); 137 | uRetval += StringFormat("\"point\": %f, ", MarketInfo(uSymbol, MODE_POINT));//fix? 138 | uRetval += StringFormat("\"digits\": %f, ", MarketInfo(uSymbol, MODE_DIGITS));//fix? 139 | uRetval += StringFormat("\"spread\": %f, ", MarketInfo(uSymbol, MODE_SPREAD)); 140 | uRetval += StringFormat("\"stoplevel\": %f, ", MarketInfo(uSymbol, MODE_STOPLEVEL)); 141 | uRetval += StringFormat("\"lotsize\": %f, ", MarketInfo(uSymbol, MODE_LOTSIZE)); 142 | uRetval += StringFormat("\"tickvalue\": %f, ", MarketInfo(uSymbol, MODE_TICKVALUE)); 143 | uRetval += StringFormat("\"ticksize\": %f, ", MarketInfo(uSymbol, MODE_TICKSIZE)); 144 | uRetval += StringFormat("\"swaplong\": %f, ", MarketInfo(uSymbol, MODE_SWAPLONG)); 145 | uRetval += StringFormat("\"swapshort\": %f, ", MarketInfo(uSymbol, MODE_SWAPSHORT)); 146 | uRetval += StringFormat("\"starting\": \"%s\", ", (string)MarketInfo(uSymbol, MODE_STARTING));//? 147 | uRetval += StringFormat("\"expiration\": \"%s\", ", (string)MarketInfo(uSymbol, MODE_EXPIRATION));//? 148 | uRetval += StringFormat("\"tradeallowed\": \"%s\", ", (string)MarketInfo(uSymbol, MODE_TRADEALLOWED));//? 149 | uRetval += StringFormat("\"minlot\": \"%s\", ", (string)MarketInfo(uSymbol, MODE_MINLOT));//? 150 | uRetval += StringFormat("\"lotstep\": \"%s\", ", (string)MarketInfo(uSymbol, MODE_LOTSTEP));//? 151 | uRetval += StringFormat("\"maxlot\": \"%s\", ", (string)MarketInfo(uSymbol, MODE_MAXLOT));//? 152 | uRetval += StringFormat("\"swaptype\": \"%s\", ", (string)MarketInfo(uSymbol, MODE_SWAPTYPE));//? 153 | uRetval += StringFormat("\"profitcalcmode\": \"%s\", ", (string)MarketInfo(uSymbol, MODE_PROFITCALCMODE));//? 154 | uRetval += StringFormat("\"margincalcmode\": \"%s\", ", (string)MarketInfo(uSymbol, MODE_MARGINCALCMODE));//? 155 | uRetval += StringFormat("\"margininit\": \"%s\", ", (string)MarketInfo(uSymbol, MODE_MARGININIT)); 156 | uRetval += StringFormat("\"marginmaintenance\": \"%s\", ", (string)MarketInfo(uSymbol, MODE_MARGINMAINTENANCE)); 157 | uRetval += StringFormat("\"marginhedged\": \"%s\", ", (string)MarketInfo(uSymbol, MODE_MARGINHEDGED)); 158 | uRetval += StringFormat("\"marginrequired\": \"%s\", ", (string)MarketInfo(uSymbol, MODE_MARGINREQUIRED)); 159 | uRetval += StringFormat("\"freezelevel\": \"%s\"", (string)MarketInfo(uSymbol, MODE_FREEZELEVEL)); 160 | uRetval += "}"; 161 | return(uRetval); 162 | } 163 | 164 | string jOTTickInformation(string uSymbol, int iTimeFrame) { 165 | string uRetval; 166 | int iDigits; 167 | double fBid, fAsk, fPoint; 168 | 169 | iDigits = (int) MarketInfo(uSymbol, MODE_DIGITS); 170 | fBid = NormalizeDouble(MarketInfo(uSymbol, MODE_BID), iDigits); 171 | fAsk = NormalizeDouble(MarketInfo(uSymbol, MODE_ASK), iDigits); 172 | fPoint = NormalizeDouble(MarketInfo(uSymbol, MODE_POINT), iDigits); 173 | // FixMe: coalesce 174 | uRetval = "{"; 175 | uRetval += StringFormat("\"currenttime\": \"%s\", ", IntegerToString(TimeCurrent())); 176 | uRetval += StringFormat("\"bid\": %f, ", fBid); 177 | uRetval += StringFormat("\"ask\": %f", fAsk); 178 | 179 | uRetval += "}"; 180 | return(uRetval); 181 | } 182 | 183 | string jOTBarInformation(string uSymbol, int iTimeFrame, int iBar) { 184 | string uRetval; 185 | int iDigits, iSpread; 186 | 187 | // FixMe: coalesce 188 | uRetval = "{"; 189 | iDigits = (int) MarketInfo(uSymbol, MODE_DIGITS); 190 | iSpread = (int) MarketInfo(uSymbol, MODE_SPREAD); 191 | 192 | uRetval += StringFormat("\"bartime\": \"%s\", ", TimeToStr(iTime(uSymbol, iTimeFrame, iBar))); 193 | uRetval += StringFormat("\"open\": %f, ", iOpen(uSymbol, iTimeFrame, iBar)); 194 | uRetval += StringFormat("\"high\": %f, ", iHigh(uSymbol, iTimeFrame, iBar)); 195 | uRetval += StringFormat("\"low\": %f, ", iLow(uSymbol, iTimeFrame, iBar)); 196 | uRetval += StringFormat("\"close\": %f, ", iClose(uSymbol, iTimeFrame, iBar)); 197 | uRetval += StringFormat("\"volume\": %i", iVolume(uSymbol, iTimeFrame, iBar)); 198 | 199 | uRetval += "}"; 200 | return(uRetval); 201 | } 202 | 203 | string jOTTimerInformation() { 204 | string uRetval; 205 | uRetval = "{"; 206 | uRetval += StringFormat("\"IsConnected\": %i, ", IsConnected()); 207 | // uRetval += StringFormat("\"IsTradeAllowed\": %i, ", IsTradeAllowed()); 208 | uRetval += StringFormat("\"OrdersTotal\": %i, ", OrdersTotal()); 209 | uRetval += StringFormat("\"IsTradeContextBusy\": %i", IsTradeContextBusy()); 210 | uRetval += "}"; 211 | return(uRetval); 212 | } 213 | -------------------------------------------------------------------------------- /MQL4/Libraries/OTMql4/OTLibLog.mq4: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | // This will provide our logging functions, but is just a 4 | // skeleton for now. See OTLibPyLog for logging with Python. 5 | 6 | #property copyright "Copyright 2014 Open Trading" 7 | #property link "https://github.com/OpenTrading/" 8 | #property library 9 | 10 | // constants 11 | #define OT_LOG_PANIC 0 // unused 12 | #define OT_LOG_ERROR 1 13 | #define OT_LOG_WARN 2 14 | #define OT_LOG_INFO 3 15 | #define OT_LOG_DEBUG 4 16 | #define OT_LOG_TRACE 5 17 | 18 | int iDefaultLoglevel = OT_LOG_DEBUG; 19 | 20 | /* floating point rounding error */ 21 | double fEPSILON=0.01; 22 | 23 | void vLogInit() { 24 | // Initializes the logging environment. This should be called 25 | // from your OnInit() function. It is safe to call it a second time; 26 | // subsequent calls will just be ignored. 27 | 28 | /* not Tmp */ 29 | if (GlobalVariableCheck("fDebugLevel") == false) { 30 | /* 1= Error, 2 = Warn, 3 = Info, 4 = Debug, 5 = Trace */ 31 | GlobalVariableSet("fDebugLevel", iDefaultLoglevel); 32 | } 33 | } 34 | 35 | void vSetLogLevel(int i) { 36 | GlobalVariableSet("fDebugLevel", i); 37 | } 38 | 39 | int iGetLogLevel() { 40 | int iDebugLevel; 41 | double fDebugLevel; 42 | 43 | fDebugLevel = GlobalVariableGet("fDebugLevel"); 44 | if (fDebugLevel < fEPSILON) { 45 | iDebugLevel = iDefaultLoglevel; 46 | GlobalVariableSet("fDebugLevel", iDebugLevel); 47 | } else { 48 | iDebugLevel = MathRound(fDebugLevel); 49 | } 50 | return(iDebugLevel); 51 | } 52 | 53 | void vLog(int iLevel, string sMess) { 54 | if (iLevel <= iGetLogLevel() ) { 55 | Print(sMess); 56 | } 57 | } 58 | 59 | void vError(string sMess) { 60 | vLog(OT_LOG_ERROR, "ERROR: "+sMess); 61 | } 62 | 63 | void vWarn(string sMess) { 64 | vLog(OT_LOG_WARN, "WARN: "+sMess); 65 | } 66 | 67 | void vInfo(string sMess) { 68 | vLog(OT_LOG_INFO, "INFO: "+sMess); 69 | } 70 | 71 | void vDebug(string sMess) { 72 | vLog(OT_LOG_DEBUG, "DEBUG: "+sMess); 73 | } 74 | 75 | void vTrace(string sMess) { 76 | vLog(OT_LOG_TRACE, "TRACE: "+sMess); 77 | } 78 | -------------------------------------------------------------------------------- /MQL4/Libraries/OTMql4/OTLibMt4ProcessCmd.mq4: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | // This is the replacement for what should be Eval in Mt4: 4 | // take a string expression and evaluate it. 5 | // 6 | // We know this is verbose and could be done more compactly, 7 | // but it's clean and robust so we'll leave it like this for now. 8 | // 9 | // If you want to extend this for your own functions you have declared in Mql4, 10 | // look at how zOTLibProcessCmd calls zMt4LibProcessCmd in OTLibProcessCmd.mq4. 11 | 12 | #property copyright "Copyright 2015 Open Trading" 13 | #property link "https://github.com/OpenTrading/" 14 | #property library 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | string zOTLibMt4ProcessCmd(string uMess) { 23 | // This is the replacement for what should be Eval in Mt4: 24 | // take a string expression and evaluate it. 25 | // zMt4LibProcessCmd only handles base Mt4 expressions. 26 | 27 | // Returns the result of processing the command as a string 28 | // in the form "type|value" where type is one of: 29 | // string, int, double, bool, datetime, void, json 30 | 31 | // Returns "error|explanation" if there is an error. 32 | 33 | // Returns "" if the the command was not recognized; 34 | // you can use this fact to process the standard Mt4 commands 35 | // with zOTLibMt4ProcessCmd, and if it returns "", 36 | // write your own zMyProcessCmd to process your additions. 37 | 38 | string uType, uChartId, uIgnore, uMark, uCmd, uMsg; 39 | string uArg1=""; 40 | string uArg2=""; 41 | string uArg3=""; 42 | string uArg4=""; 43 | string uArg5=""; 44 | string uArg6=""; 45 | string uArg7=""; 46 | string aArrayAsList[]; 47 | int iLen; 48 | string uRetval, uKey; 49 | 50 | iLen = StringLen(uMess); 51 | if (iLen <= 0) { 52 | vError("eOTLibProcessCmd: empty input"); 53 | return(""); 54 | } 55 | 56 | vStringToArray(uMess, aArrayAsList, "|"); 57 | 58 | iLen = ArraySize(aArrayAsList); 59 | //vTrace("zMt4LibProcessCmd: " +uMess +" ArrayLen " +iLen); 60 | 61 | uRetval = eOTLibSimpleUnformatCmd(aArrayAsList); 62 | if (uRetval != "") { 63 | vError("eOTLibProcessCmd: preprocess failed with error: " +uRetval); 64 | return(""); 65 | } 66 | 67 | uType = aArrayAsList[0]; 68 | uChartId = aArrayAsList[1]; 69 | uIgnore = aArrayAsList[2]; 70 | uMark = aArrayAsList[3]; 71 | uCmd = aArrayAsList[4]; 72 | uArg1 = aArrayAsList[5]; 73 | uArg2 = aArrayAsList[6]; 74 | uArg3 = aArrayAsList[7]; 75 | uArg4 = aArrayAsList[8]; 76 | uArg5 = aArrayAsList[9]; 77 | uArg6 = aArrayAsList[10]; 78 | uArg7 = aArrayAsList[11]; 79 | 80 | uKey = StringSubstr(uCmd, 0, 3); 81 | 82 | if (StringFind(uCmd, "|", 0) >= 0) { 83 | uMsg="Found separator in command"; 84 | vWarn(uMsg); 85 | uRetval=uMark+"|error|"+uMsg; 86 | return(uRetval); 87 | } 88 | 89 | if (uCmd == "OrdersTotal") { //0 90 | uRetval = "int|" +IntegerToString(OrdersTotal()); 91 | } else if (uCmd == "Period") { //0 92 | uRetval = "int|" +IntegerToString(Period()); 93 | } else if (uCmd == "RefreshRates") { //0 94 | uRetval = "bool|" +RefreshRates(); 95 | } else if (uCmd == "Symbol") { //0 96 | uRetval = "string|" +Symbol(); 97 | } else if (uCmd == "Comment") { 98 | // FixMe: what's the return value? 99 | Comment(uArg1); 100 | uRetval = "void|"; 101 | } else if (uCmd == "Print") { 102 | // FixMe: what's the return value? 103 | // FixMe: we should handle multi-args 104 | Print(uArg1); 105 | uRetval = "void|"; 106 | } else if (uKey == "Fil") { 107 | // FixMe: File* 108 | uRetval = ""; 109 | } else if (uKey == "Ter") { 110 | uRetval = zProcessCmdTer(uCmd, uChartId, uIgnore, uArg1, uArg2, uArg3, uArg4, uArg5); 111 | } else if (uKey == "Win") { 112 | uRetval = zProcessCmdWin(uCmd, uChartId, uIgnore, uArg1, uArg2, uArg3, uArg4, uArg5); 113 | } else if (uKey == "Acc") { 114 | uRetval = zProcessCmdAcc(uCmd, uChartId, uIgnore, uArg1, uArg2, uArg3, uArg4, uArg5); 115 | } else if (uKey == "Glo") { 116 | uRetval = zProcessCmdGlo(uCmd, uChartId, uIgnore, uArg1, uArg2, uArg3, uArg4, uArg5); 117 | } 118 | 119 | if (StringCompare(uRetval, "") == 0) { 120 | //vTrace("zMt4LibProcessCmd: UNHANDELED" +uKey +" uCmd: " +uCmd); 121 | return(""); 122 | } 123 | // vTrace("zMt4LibProcessCmd uMess: " +uMess +" -> " +uRetval); 124 | 125 | // WE INCLUDE THE SMARK 126 | uRetval = uMark + "|" + uRetval; 127 | 128 | return(uRetval); 129 | } 130 | 131 | string zProcessCmdTer(string uCmd, string uChartId, string uIgnore, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5) { 132 | string uMsg; 133 | string uRetval=""; 134 | 135 | if (uCmd == "TerminalCompany") { //0 136 | uRetval = "string|" +TerminalCompany(); 137 | } else if (uCmd == "TerminalName") { //0 138 | uRetval = "string|" +TerminalName(); 139 | } else if (uCmd == "TerminalInfoString") { //1 140 | // groan - does everything coerce? 141 | uRetval = "string|" +(string)TerminalInfoString(uArg1); 142 | } else if (uCmd == "TerminalPath") { //0 143 | uRetval = "string|" +TerminalPath(); 144 | } else { 145 | uMsg = "Unrecognized action: "; 146 | vWarn("zProcessCmdTer: " +uMsg +uCmd); 147 | uRetval = ""; 148 | } 149 | 150 | return (uRetval); 151 | } 152 | 153 | string zProcessCmdWin(string uCmd, string uChartId, string uIgnore, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5) { 154 | string uMsg; 155 | string uRetval=""; 156 | int iIndex, iPeriod; 157 | 158 | if (uCmd == "WindowBarsPerChart") { //0 159 | uRetval = "int|" +IntegerToString(WindowBarsPerChart()); 160 | } else if (uCmd == "WindowFind") { //0 161 | uRetval = "string|" +WindowFind(uArg1); 162 | } else if (uCmd == "WindowFirstVisibleBar") { //0 163 | uRetval = "int|" +IntegerToString(WindowFirstVisibleBar()); 164 | } else if (uCmd == "WindowHandle") { 165 | iPeriod=StrToInteger(uArg2); 166 | uRetval = "int|" +IntegerToString(WindowHandle(uArg1, iPeriod)); 167 | } else if (uCmd == "WindowIsVisible") { 168 | iIndex=StrToInteger(uArg1); 169 | uRetval = "bool|" +WindowIsVisible(iIndex); 170 | } else if (uCmd == "WindowOnDropped") { 171 | uRetval = "int|" +IntegerToString(WindowOnDropped()); 172 | } else if (uCmd == "WindowPriceMax") { 173 | iIndex=StrToInteger(uArg1); 174 | uRetval = "double|" +DoubleToStr(DoubleToStr(WindowPriceMax(iIndex), 2), 6); 175 | } else if (uCmd == "WindowPriceMin") { 176 | iIndex=StrToInteger(uArg1); 177 | uRetval = "double|" +DoubleToStr(DoubleToStr(WindowPriceMin(iIndex), 2), 6); 178 | } else if (uCmd == "WindowPriceOnDropped") { 179 | uRetval = "double|" +DoubleToStr(WindowPriceOnDropped(), 6); 180 | } else if (uCmd == "WindowRedraw") { //0 181 | WindowRedraw(); 182 | uRetval = "void|"; 183 | // WindowScreenShot 184 | } else if (uCmd == "WindowTimeOnDropped") { 185 | uRetval = "datetime|" +WindowTimeOnDropped(); 186 | } else if (uCmd == "WindowXOnDropped") { 187 | uRetval = "int|" +IntegerToString(WindowXOnDropped()); 188 | } else if (uCmd == "WindowYOnDropped") { 189 | uRetval = "int|" +IntegerToString(WindowYOnDropped()); 190 | } else if (uCmd == "WindowsTotal") { //0 191 | uRetval = "int|" +IntegerToString(WindowsTotal()); 192 | } else { 193 | uMsg="Unrecognized action: "; 194 | vWarn("zProcessCmdWin: " +uMsg +uCmd); 195 | uRetval = ""; 196 | } 197 | 198 | return(uRetval); 199 | } 200 | 201 | 202 | string zProcessCmdAcc(string uCmd, string uChartId, string uIgnore, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5) { 203 | string uMsg; 204 | string uRetval=""; 205 | string uSymbol; 206 | int iCmd; 207 | double fVolume; 208 | 209 | if (uCmd == "AccountBalance") { //0 210 | uRetval = "double|" +DoubleToStr(AccountBalance(), 2); 211 | } else if (uCmd == "AccountCompany") { //0 212 | uRetval = "string|" +AccountCompany(); 213 | } else if (uCmd == "AccountCredit") { //0 214 | uRetval = "double|" +DoubleToStr(AccountCredit(), 2); 215 | } else if (uCmd == "AccountCurrency") { //0 216 | uRetval = "string|" +AccountCurrency(); 217 | } else if (uCmd == "AccountEquity") { //0 218 | uRetval = "double|" +DoubleToStr(AccountEquity(), 2); 219 | } else if (uCmd == "AccountFreeMargin") { //0 220 | uRetval = "double|" +DoubleToStr(AccountFreeMargin(), 2); 221 | } else if (uCmd == "AccountFreeMarginCheck") { 222 | // assert 223 | uSymbol=uArg1; 224 | iCmd=StrToInteger(uArg2); 225 | fVolume=StrToDouble(uArg3); 226 | uRetval = "double|" +DoubleToStr(AccountFreeMarginCheck(uSymbol, iCmd, fVolume), 2); 227 | } else if (uCmd == "AccountFreeMarginMode") { //0 228 | uRetval = "double|" +DoubleToStr(AccountFreeMarginMode(), 2); 229 | } else if (uCmd == "AccountLeverage") { //0 230 | uRetval = "int|" +IntegerToString(AccountLeverage()); 231 | } else if (uCmd == "AccountMargin") { //0 232 | uRetval = "double|" +DoubleToStr(AccountMargin(), 2); 233 | } else if (uCmd == "AccountName") { //0 234 | uRetval = "string|" +AccountName(); 235 | } else if (uCmd == "AccountNumber") { //0 236 | uRetval = "int|" +IntegerToString(AccountNumber()); 237 | } else if (uCmd == "AccountProfit") { //0 238 | uRetval = "double|" +DoubleToStr(AccountProfit(), 2); 239 | } else if (uCmd == "AccountServer") { //0 240 | uRetval = "string|" +AccountServer(); 241 | } else if (uCmd == "AccountStopoutLevel") { //0 242 | uRetval = "int|" +IntegerToString(AccountStopoutLevel()); 243 | } else if (uCmd == "AccountStopoutMode") { //0 244 | uRetval = "int|" +IntegerToString(AccountStopoutMode()); 245 | } else { 246 | uMsg="Unrecognized action: "; 247 | vWarn("zProcessCmdAcc: " +uMsg +uCmd); 248 | uRetval=""; 249 | } 250 | 251 | return(uRetval); 252 | } 253 | 254 | string zProcessCmdGlo(string uCmd, string uChartId, string uIgnore, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5) { 255 | string uMsg; 256 | string uRetval=""; 257 | string sName; 258 | double fValue; 259 | int iValue; 260 | 261 | if (uCmd == "GlobalVariableCheck") { 262 | // assert 263 | sName = uArg1; 264 | uRetval = "bool|" +GlobalVariableCheck(sName); 265 | } else if (uCmd == "GlobalVariableDel") { 266 | // assert 267 | sName = uArg1; 268 | uRetval = "bool|" +GlobalVariableDel(sName); 269 | } else if (uCmd == "GlobalVariableDeleteAll") { 270 | // assert 271 | sName = uArg1; 272 | iValue = StringToInteger(uArg2); //FixMe: datetime 273 | //FixMe uRetval = "bool|" +GlobalVariableDeleteAll(sName, iValue); 274 | uRetval = "bool|false"; 275 | } else if (uCmd == "GlobalVariableGet") { 276 | // assert 277 | sName = uArg1; 278 | uRetval = "double|" +DoubleToStr(GlobalVariableGet(sName), 6); 279 | // overloaded 280 | } else if (uCmd == "GlobalVariableName") { 281 | // assert 282 | iValue = StringToInteger(uArg1); 283 | uRetval = "string|" +GlobalVariableName(iValue); 284 | // overloaded but we cant pass pointers 285 | } else if (uCmd == "GlobalVariableSet") { 286 | // assert 287 | sName = uArg1; 288 | fValue = StrToDouble(uArg2); 289 | uRetval = "double|" +DoubleToStr(GlobalVariableSet(sName, fValue), 6); 290 | } else { 291 | // GlobalVariableSetOnCondition 292 | uMsg = "Unrecognized action: "; 293 | vWarn("zProcessCmdGlo: " +uMsg +uCmd); 294 | uRetval = ""; 295 | } 296 | 297 | return(uRetval); 298 | } 299 | -------------------------------------------------------------------------------- /MQL4/Libraries/OTMql4/OTLibProcessCmd.mq4: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | // This is the replacement for what should be Eval in Mt4: 4 | // take a string expression and evaluate it. 5 | // 6 | // We know this is verbose and could be done more compactly, 7 | // but it's clean and robust so we'll leave it like this for now. 8 | // 9 | // If you want to extend this for your own functions you have declared in Mql4, 10 | // look at how zOTLibProcessCmd calls zMt4LibProcessCmd and then 11 | // goes on and handles it if zMt4LibProcessCmd didn't. 12 | // 13 | 14 | #property copyright "Copyright 2013 OpenTrading" 15 | #property link "https://github.com/OpenTrading/" 16 | #property library 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | // extentions from OpenTrading - see uProcessCmdgOT and uProcessCmdOT 25 | #include 26 | #include 27 | 28 | string zOTLibProcessCmd(string uMess) { 29 | // This is the replacement for what should be Eval in Mt4: 30 | // take a string expression and evaluate it. 31 | // zMt4LibProcessCmd handles base Mt4 expressions, and 32 | // zOTLibProcessCmd also handles base OpenTrading expressions. 33 | 34 | // Returns the result of processing the command. 35 | // Returns "" if there is an error. 36 | 37 | string uType, uChartId, uIgnore, uMark, uCmd; 38 | string uArg1=""; 39 | string uArg2=""; 40 | string uArg3=""; 41 | string uArg4=""; 42 | string uArg5=""; 43 | string uArg6=""; 44 | string uArg7=""; 45 | string aArrayAsList[]; 46 | int iLen; 47 | string uRetval, uKey; 48 | 49 | iLen = StringLen(uMess); 50 | if (iLen <= 0) {return("");} 51 | 52 | uRetval = zOTLibMt4ProcessCmd(uMess); 53 | if (uRetval != "") { 54 | //vTrace("zOTLibProcessCmd: returning " +uRetval); 55 | return(uRetval); 56 | } 57 | 58 | vStringToArray(uMess, aArrayAsList, "|"); 59 | 60 | iLen = ArraySize(aArrayAsList); 61 | // vTrace("zOTLibProcessCmd: " +uMess +" ArrayLen " +iLen); 62 | 63 | uRetval = eOTLibSimpleUnformatCmd(aArrayAsList); 64 | if (uRetval != "") { 65 | vError("eOTLibProcessCmd: preprocess failed with error: " +uRetval); 66 | return(""); 67 | } 68 | 69 | uType = aArrayAsList[0]; 70 | uChartId = aArrayAsList[1]; 71 | uIgnore = aArrayAsList[2]; 72 | uMark = aArrayAsList[3]; 73 | uCmd = aArrayAsList[4]; 74 | uArg1 = aArrayAsList[5]; 75 | uArg2 = aArrayAsList[6]; 76 | uArg3 = aArrayAsList[7]; 77 | uArg4 = aArrayAsList[8]; 78 | uArg5 = aArrayAsList[9]; 79 | uArg6 = aArrayAsList[10]; 80 | uArg7 = aArrayAsList[11]; 81 | 82 | uKey = StringSubstr(uCmd, 0, 3); 83 | if (uKey == "gOT") { 84 | // extentions from OpenTrading 85 | uRetval = uProcessCmdgOT(uCmd, uChartId, uIgnore, uMark, uArg1, uArg2, uArg3, uArg4, uArg5, uArg6, uArg7); 86 | 87 | if (StringCompare(uRetval, "") == 0 ) vDebug("zOTLibProcessCmd: UNHANDELED gOT uCmd: " +uCmd); 88 | } else if (StringSubstr(uCmd, 1, 2) == "OT") { 89 | uRetval = uProcessCmdOT(uCmd, uChartId, uIgnore, uMark, uArg1, uArg2, uArg3, uArg4, uArg5, uArg6, uArg7); 90 | if (StringCompare(uRetval, "") == 0 ) vDebug("zOTLibProcessCmd: UNHANDELED OT uCmd: " +uCmd); 91 | 92 | } else if (StringSubstr(uCmd, 0, 1) == "i") { 93 | //? are these Mt4 or OT? 94 | uRetval = uProcessCmdi(uCmd, uChartId, uIgnore, uMark, uArg1, uArg2, uArg3, uArg4, uArg5, uArg6, uArg7); 95 | if (StringCompare(uRetval, "") == 0 ) vDebug("zOTLibProcessCmd: UNHANDELED i uCmd: " +uCmd); 96 | 97 | } 98 | if (StringCompare(uRetval, "") == 0) { 99 | //vTrace("zOTLibProcessCmd: UNHANDELED uCmd: " +uCmd); 100 | return(""); 101 | } 102 | // vTrace("zOTLibProcessCmd uMess: " +uMess +" -> " +uRetval); 103 | 104 | // WE INCLUDE THE SMARK 105 | uRetval = uMark + "|" + uRetval; 106 | return(uRetval); 107 | 108 | } 109 | 110 | string uProcessCmdi (string uCmd, string uChartId, string uIgnore, string uMark, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5, string uArg6, string uArg7) { 111 | string uMsg; 112 | string uRetval="none|"; 113 | string uSymbol; 114 | int iPeriod, iShift; 115 | int iType, iCount, iStart; 116 | 117 | if (StringFind(uCmd, "|", 0) >= 0) { 118 | uMsg="found separator in command"; 119 | vWarn(uMsg +": " +uCmd); 120 | uRetval=uMark +"|error|"+uMsg; 121 | return(uRetval); 122 | } 123 | 124 | uSymbol = uArg1; 125 | iPeriod = StrToInteger(uArg2); 126 | 127 | // iBarShift 128 | if (uCmd == "iBars") { 129 | uRetval = "int|" +IntegerToString( iBars(uSymbol, iPeriod)); 130 | } else if (uCmd == "iClose") { 131 | iShift = StrToInteger(uArg3); 132 | uRetval = "double|" +DoubleToStr( iClose(uSymbol, iPeriod, iShift), 4); 133 | } else if (uCmd == "iHigh") { 134 | iShift = StrToInteger(uArg3); 135 | uRetval = "double|" +DoubleToStr( iHigh(uSymbol, iPeriod, iShift), 4); 136 | } else if (uCmd == "iHighest") { 137 | iType = StrToInteger(uArg3); 138 | iCount = StrToInteger(uArg4); 139 | iStart = StrToInteger(uArg5); 140 | uRetval = "int|" +IntegerToString( iHighest(uSymbol, iPeriod, iType, iCount, iStart)); 141 | } else if (uCmd == "iLow") { 142 | iShift=StrToInteger(uArg3); 143 | uRetval = "double|" +DoubleToStr( iLow(uSymbol, iPeriod, iShift), 4); 144 | } else if (uCmd == "iLowest") { 145 | iType = StrToInteger(uArg3); 146 | iCount = StrToInteger(uArg4); 147 | iStart = StrToInteger(uArg5); 148 | uRetval = "int|" +IntegerToString( iLowest(uSymbol, iPeriod, iType, iCount, iStart)); 149 | } else if (uCmd == "iOpen") { 150 | iShift = StrToInteger(uArg3); 151 | uRetval = "double|" +DoubleToStr( iOpen(uSymbol, iPeriod, iShift), 4); 152 | } else if (uCmd == "iTime") { 153 | iShift = StrToInteger(uArg3); 154 | uRetval = "datetime|" + iTime(uSymbol, iPeriod, iShift); 155 | } else if (uCmd == "iVolume") { 156 | iShift = StrToInteger(uArg3); 157 | uRetval = "double|" +DoubleToStr( iVolume(uSymbol, iPeriod, iShift), 2); 158 | } else { 159 | uMsg="Unrecognized action: "; 160 | vWarn(uMsg + uCmd); 161 | uRetval=uMark +"|error|"+uMsg; 162 | } 163 | 164 | return(uRetval); 165 | } 166 | 167 | // OpenTrading additions 168 | // names start with a lower case letter then OT 169 | string uProcessCmdOT(string uCmd, string uChartId, string uIgnore, string uMark, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5, string uArg6, string uArg7) { 170 | string uMsg, sSymbol; 171 | string uRetval="none|"; 172 | int iTicket, iTimeframe, iCmd, iBar; 173 | double fLots; 174 | double fPrice; 175 | double fStopLoss; 176 | double fTakeProfit; 177 | datetime tExpiration; 178 | int iMaxWaitingSeconds; 179 | int iOrderEAMagic; 180 | int iTrailingStopLossPoints; 181 | int iSlippage; 182 | color cColor; 183 | 184 | if (StringFind(uCmd, "|", 0) >= 0) { 185 | uMsg="Found separator in command"; 186 | vWarn(uMsg + uCmd); 187 | uRetval=uMark +"|error|"+uMsg; 188 | return(uRetval); 189 | } 190 | 191 | if (uCmd == "iOTOrderSelect") { 192 | uRetval = "int|" +IntegerToString( iOTOrderSelect(StrToInteger(uArg1), StrToInteger(uArg2), StrToInteger(uArg3))); 193 | 194 | } else if (uCmd == "iOTOrderSend") { 195 | sSymbol = uArg1; 196 | // assert string length > 3 197 | iCmd = StrToInteger(uArg2); 198 | fLots = StrToDouble(uArg3); 199 | fPrice = StrToDouble(uArg4); 200 | iSlippage = StrToInteger(uArg5); 201 | fStopLoss = StrToDouble(uArg6); 202 | fTakeProfit = StrToDouble(uArg7); 203 | // FixMe: 204 | cColor=CLR_NONE; 205 | uRetval = "int|" +IntegerToString(iOTOrderSend(sSymbol, iCmd, 206 | fLots, fPrice, iSlippage, 207 | fStopLoss, fTakeProfit 208 | )); 209 | 210 | } else if (uCmd == "iOTOrderSendMarket") { 211 | sSymbol = uArg1; 212 | iCmd = StrToInteger(uArg2); 213 | fLots = StrToDouble(uArg3); 214 | // fPrice = StrToDouble(uArg4); 215 | // iSlippage = StrToInteger(uArg5); 216 | // FixMe: 217 | cColor=CLR_NONE; 218 | uRetval = "int|" +IntegerToString( iOTOrderSendMarket(sSymbol, iCmd, fLots)); 219 | 220 | } else if (uCmd == "iOTOrderCloseMarket") { 221 | iTicket = StrToInteger(uArg1); 222 | uRetval = "int|" +IntegerToString( iOTOrderCloseMarket(iTicket)); 223 | 224 | } else if (uCmd == "iOTOrderCloseFull") { 225 | iTicket = StrToInteger(uArg1); 226 | fLots = StrToDouble(uArg2); 227 | fPrice = StrToDouble(uArg3); 228 | // FixMe: 229 | iSlippage = StrToInteger(uArg4); 230 | // FixMe: 231 | cColor=CLR_NONE; 232 | uRetval = "int|" +IntegerToString( iOTOrderCloseFull(iTicket, fPrice, iSlippage, cColor)); 233 | 234 | } else if (uCmd == "iOTOrderClose") { 235 | iTicket = StrToInteger(uArg1); 236 | fLots = StrToDouble(uArg2); 237 | fPrice = StrToDouble(uArg3); 238 | iSlippage = StrToInteger(uArg4); 239 | // FixMe: 240 | cColor=CLR_NONE; 241 | uRetval = "int|" +IntegerToString( iOTOrderClose(iTicket, fLots, fPrice, iSlippage, cColor)); 242 | 243 | } else if (uCmd == "iOTSetTradeIsBusy") { 244 | if (StringLen(uArg1) < 1) { 245 | uRetval = "int|" +IntegerToString( iOTSetTradeIsBusy(60)); 246 | } else { 247 | iMaxWaitingSeconds = StrToInteger(uArg1); 248 | uRetval = "int|" +IntegerToString( iOTSetTradeIsBusy(iMaxWaitingSeconds)); 249 | } 250 | 251 | } else if (uCmd == "iOTSetTradeIsNotBusy") { 252 | uRetval = "int|" +IntegerToString( iOTSetTradeIsNotBusy()); 253 | 254 | } else if (uCmd == "fOTExposedEcuInMarket") { 255 | if (StringLen(uArg1) < 1) { 256 | iOrderEAMagic = 0; 257 | } else { 258 | iOrderEAMagic = StrToInteger(uArg1); 259 | } 260 | uRetval = "double|" +DoubleToStr( fOTExposedEcuInMarket(iOrderEAMagic), 2); 261 | 262 | } else if (uCmd == "bOTIsTradeAllowed") { 263 | uRetval = "bool|" + bOTIsTradeAllowed(); 264 | 265 | } else if (uCmd == "iOTRefreshRates") { 266 | uRetval = "bool|" + iOTRefreshRates(); 267 | 268 | } else if (uCmd == "iOTMarketInfo") { 269 | sSymbol = uArg1; 270 | iCmd = StrToInteger(uArg2); 271 | uRetval = "int|" + iOTMarketInfo(sSymbol, iCmd); 272 | 273 | } else if (uCmd == "fOTMarketInfo") { 274 | sSymbol = uArg1; 275 | iCmd = StrToInteger(uArg2); 276 | uRetval = "double|" + fOTMarketInfo(sSymbol, iCmd); 277 | 278 | } else if (uCmd == "bOTModifyTrailingStopLoss") { 279 | sSymbol = uArg1; 280 | iTrailingStopLossPoints = StrToInteger(uArg2); 281 | if (StringLen(uArg3) < 1) { 282 | tExpiration = 0; 283 | } else { 284 | // FixMe: StrToDateTime? 285 | tExpiration = StrToInteger(uArg3); 286 | } 287 | uRetval = "bool|" + bOTModifyTrailingStopLoss(sSymbol, 288 | iTrailingStopLossPoints, 289 | tExpiration); 290 | 291 | } else if (uCmd == "bOTModifyOrder") { 292 | // this implies a selected order 293 | iTicket = StrToInteger(uArg2); 294 | fPrice = StrToDouble(uArg3); 295 | fStopLoss = StrToDouble(uArg4); 296 | fTakeProfit = StrToDouble(uArg5); 297 | // ignores datetime tExpiration 298 | tExpiration = 0; 299 | // Notes: Open price and expiration time can be changed only for pending orders. 300 | uRetval = "bool|" + bOTModifyOrder(uArg1, iTicket, fPrice, 301 | fStopLoss, fTakeProfit, tExpiration); 302 | 303 | } else if (uCmd == "bOTContinueOnOrderError") { 304 | iTicket = StrToInteger(uArg1); 305 | uRetval = "bool|" + bOTContinueOnOrderError(iTicket); 306 | 307 | } else if (uCmd == "jOTAccountInformation") { 308 | uRetval = "json|" + jOTAccountInformation(); 309 | } else if (uCmd == "jOTOrdersTickets") { 310 | uRetval = "json|" + jOTOrdersTickets(); 311 | } else if (uCmd == "jOTOrdersHistory") { 312 | uRetval = "json|" + jOTOrdersHistory(); 313 | } else if (uCmd == "jOTOrdersTrades") { 314 | uRetval = "json|" + jOTOrdersTrades(); 315 | } else if (uCmd == "jOTOrders") { 316 | uRetval = "json|" + jOTOrders(StrToInteger(uArg1)); 317 | } else if (uCmd == "jOTOrderInformationByTicket") { 318 | iTicket = StrToInteger(uArg1); 319 | uRetval = "json|" + jOTOrderInformationByTicket(iTicket); 320 | } else if (uCmd == "jOTMarketInformation") { 321 | uRetval = "json|" + jOTMarketInformation(uArg1); 322 | } else if (uCmd == "jOTBarInformation") { 323 | iTimeframe = StrToInteger(uArg2); 324 | iBar = StrToInteger(uArg3); 325 | uRetval = "json|" + jOTBarInformation(uArg1, iTimeframe, iBar); 326 | } else { 327 | uMsg = "Unrecognized action: "; 328 | vWarn("uProcessCmdOT: " +uMsg +uCmd); 329 | uRetval = ""; 330 | } 331 | 332 | return(uRetval); 333 | } 334 | 335 | 336 | // Wrap all of the functions that depend on an order being selected 337 | // into a generic gOTWithOrderSelectByTicket and gOTWithOrderSelectByPosition 338 | string uProcessCmdgOT(string uCmd, string uChartId, string uIgnore, string uMark, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5, string uArg6, string uArg7) { 339 | string uRetval="none|"; 340 | string uMsg; 341 | int iError; 342 | 343 | if (StringFind(uCmd, "|", 0) >= 0) { 344 | uMsg="Found separator in command"; 345 | vWarn(uMsg + uCmd); 346 | uRetval=uMark +"|error|"+uMsg; 347 | return(uRetval); 348 | } 349 | 350 | if (uCmd == "gOTWithOrderSelectByTicket") { 351 | int iTicket=StrToInteger(uArg1); 352 | 353 | if (OrderSelect(iTicket, SELECT_BY_TICKET) == false) { 354 | iError=GetLastError(); 355 | uMsg = "OrderSelect returned an error: " + ErrorDescription(iError)+"("+iError+")"; 356 | vError(uMsg); 357 | uRetval=uMark +"|error|"+uMsg; 358 | return(uRetval); 359 | } 360 | // drop through 361 | } else if (uCmd == "gOTWithOrderSelectByPosition") { 362 | int iPos=StrToInteger(uArg1); 363 | 364 | if (OrderSelect(iPos, SELECT_BY_POS) == false) { 365 | iError=GetLastError(); 366 | uMsg = "OrderSelect returned an error: " + ErrorDescription(iError)+"("+iError+")"; 367 | vError(uMsg); 368 | uRetval=uMark +"|error|"+uMsg; 369 | return(uRetval); 370 | } 371 | // drop through 372 | } else { 373 | uMsg="Unrecognized action"; 374 | vWarn(uMsg + uCmd); 375 | uRetval=uMark +"|error|"+uMsg; 376 | return(uRetval); 377 | } 378 | 379 | string sCommand=uArg2; 380 | // have a selected order ... 381 | if (sCommand == "OrderClosePrice" ) { 382 | uRetval = "double|" +DoubleToStr( OrderClosePrice(), 4); 383 | } else if (sCommand == "OrderCloseTime" ) { 384 | uRetval = "datetime|" + OrderCloseTime(); 385 | } else if (sCommand == "OrderComment" ) { 386 | uRetval = "string|" + OrderComment(); 387 | } else if (sCommand == "OrderCommission" ) { 388 | uRetval = "double|" +DoubleToStr( OrderCommission(), 2); 389 | } else if (sCommand == "OrderExpiration" ) { 390 | uRetval = "datetime|" + OrderExpiration(); 391 | } else if (sCommand == "OrderLots" ) { 392 | uRetval = "double|" +DoubleToStr( OrderLots(), 6); 393 | } else if (sCommand == "OrderMagicNumber" ) { 394 | uRetval = "int|" +IntegerToString( OrderMagicNumber()); 395 | } else if (sCommand == "OrderOpenPrice" ) { 396 | uRetval = "double|" +DoubleToStr( OrderOpenPrice(), 4); 397 | } else if (sCommand == "OrderOpenTime" ) { 398 | uRetval = "datetime|" + OrderOpenTime(); 399 | } else if (sCommand == "OrderProfit" ) { 400 | uRetval = "double|" +DoubleToStr( OrderProfit(), 2); 401 | } else if (sCommand == "OrderStopLoss" ) { 402 | uRetval = "double|" +DoubleToStr( OrderStopLoss(), 4); 403 | } else if (sCommand == "OrderSwap" ) { 404 | uRetval = "double|" +DoubleToStr( OrderSwap(), 4); 405 | } else if (sCommand == "OrderSymbol" ) { 406 | uRetval = "string|" + OrderSymbol(); 407 | } else if (sCommand == "OrderTakeProfit" ) { 408 | uRetval = "double|" +DoubleToStr( OrderTakeProfit(), 4); 409 | } else if (sCommand == "OrderTicket" ) { 410 | uRetval = "int|" +IntegerToString( OrderTicket()); 411 | } else if (sCommand == "OrderType" ) { 412 | uRetval = "int|" +IntegerToString( OrderType()); 413 | } else { 414 | uMsg="Unrecognized " + uCmd + " command: " + sCommand; 415 | vWarn("uProcessCmdgOT: " +uMsg); 416 | uRetval=""; 417 | } 418 | 419 | return(uRetval); 420 | } 421 | 422 | -------------------------------------------------------------------------------- /MQL4/Libraries/OTMql4/OTLibServerErrors.mq4: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8; encoding: utf-8-dos -*- 2 | 3 | #property copyright "Copyright 2009, OpenTrading" 4 | #property link "https://github.com/OpenTrading/" 5 | #property library 6 | 7 | // One of the many fundamental defects of the Mql4 language 8 | // is that there is no Object Oriented error handling. 9 | // 10 | // This leads to Mq4 returning hundreds of different errors 11 | // that are not grouped so that we can take actions based 12 | // on classes of errors. 13 | // 14 | // We try to group the large number of errors into 9 groups 15 | // so that we can for example retry a trade when there is 16 | // some kind of network error. 17 | // 18 | 19 | #define OFLIB_OTHER_ERROR 0 20 | #define OFLIB_BUSY_ERROR 1 // continuable - should retry 21 | #define OFLIB_ORDER_ERROR 2 22 | #define OFLIB_ACCOUNT_ERROR 3 23 | #define OFLIB_NETWORK_ERROR 4 24 | #define OFLIB_FATAL_ERROR 5 25 | #define OFLIB_WINDOW_ERROR 6 26 | #define OFLIB_FILE_ERROR 7 27 | #define OFLIB_RUNTIME_ERROR 8 28 | 29 | #include 30 | 31 | bool bOTLibServerErrorIsContinuable(int iErr) { 32 | int i; 33 | 34 | i = bOTLibServerErrorType(iErr); 35 | // Im not really sure what "commonerror" is (OFLIB_OTHER_ERROR) 36 | return(i == OFLIB_BUSY_ERROR || i == OFLIB_NETWORK_ERROR); 37 | } 38 | 39 | bool bOTLibServerErrorType(int iErr) { 40 | // Group the errors returned from trade server 41 | // so that we can take action based on classes of errors. 42 | switch(iErr) { 43 | case ERR_NO_ERROR: // 0 44 | return(OFLIB_OTHER_ERROR); 45 | case ERR_NO_RESULT: // 1 46 | return(OFLIB_OTHER_ERROR); 47 | case ERR_COMMON_ERROR: // 2 48 | return(OFLIB_OTHER_ERROR); 49 | 50 | case ERR_INVALID_TRADE_PARAMETERS: // 3 51 | return(OFLIB_ORDER_ERROR); 52 | 53 | case ERR_SERVER_BUSY: // 4 54 | return(OFLIB_BUSY_ERROR); 55 | 56 | case ERR_OLD_VERSION: // 5 57 | return(OFLIB_FATAL_ERROR); 58 | 59 | case ERR_NO_CONNECTION: // 6 60 | return(OFLIB_NETWORK_ERROR); 61 | 62 | case ERR_NOT_ENOUGH_RIGHTS: // 7 63 | case ERR_TOO_FREQUENT_REQUESTS: // 8 64 | case ERR_MALFUNCTIONAL_TRADE: // 9 65 | return(OFLIB_ORDER_ERROR); //? or retry? 66 | 67 | case ERR_ACCOUNT_DISABLED: // 64 68 | case ERR_INVALID_ACCOUNT: // 65 69 | return(OFLIB_ACCOUNT_ERROR); 70 | 71 | case ERR_TRADE_TIMEOUT: // 128 72 | return(OFLIB_NETWORK_ERROR); 73 | 74 | case ERR_INVALID_PRICE: // 129 75 | case ERR_INVALID_STOPS: // 130 76 | return(OFLIB_BUSY_ERROR); 77 | 78 | case ERR_INVALID_TRADE_VOLUME: // 131 79 | case ERR_MARKET_CLOSED: // 132 80 | case ERR_TRADE_DISABLED: // 133 81 | case ERR_NOT_ENOUGH_MONEY: // 134 82 | return(OFLIB_ORDER_ERROR); 83 | 84 | case ERR_PRICE_CHANGED: // 135 85 | return(OFLIB_BUSY_ERROR); 86 | 87 | case ERR_OFF_QUOTES: // 136 88 | case ERR_BROKER_BUSY: // 137 89 | case ERR_REQUOTE: // 138 90 | return(OFLIB_BUSY_ERROR); 91 | 92 | case ERR_ORDER_LOCKED: // 139 93 | return(OFLIB_BUSY_ERROR); 94 | 95 | case ERR_LONG_POSITIONS_ONLY_ALLOWED: // 140 96 | case ERR_TOO_MANY_REQUESTS: // 141 97 | case ERR_TRADE_MODIFY_DENIED: // 145 98 | return(OFLIB_ORDER_ERROR); 99 | 100 | case ERR_TRADE_CONTEXT_BUSY: // 146 101 | return(OFLIB_BUSY_ERROR); 102 | 103 | case ERR_TRADE_EXPIRATION_DENIED: // 147 104 | case ERR_TRADE_TOO_MANY_ORDERS: // 148 105 | return(OFLIB_ORDER_ERROR); 106 | 107 | //---- mql4 run time errors 108 | case ERR_NO_MQLERROR: // 4000 109 | case ERR_WRONG_FUNCTION_POINTER: // 4001 110 | case ERR_ARRAY_INDEX_OUT_OF_RANGE: // 4002 111 | case ERR_NO_MEMORY_FOR_CALL_STACK: // 4003 112 | case ERR_RECURSIVE_STACK_OVERFLOW: // 4004 113 | case ERR_NOT_ENOUGH_STACK_FOR_PARAM: // 4005 114 | case ERR_NO_MEMORY_FOR_PARAM_STRING: // 4006 115 | case ERR_NO_MEMORY_FOR_TEMP_STRING: // 4007 116 | case ERR_NOT_INITIALIZED_STRING: // 4008 117 | case ERR_NOT_INITIALIZED_ARRAYSTRING: // 4009 118 | case ERR_NO_MEMORY_FOR_ARRAYSTRING: // 4010 119 | case ERR_TOO_LONG_STRING: // 4011 120 | case ERR_REMAINDER_FROM_ZERO_DIVIDE: // 4012 121 | case ERR_ZERO_DIVIDE: // 4013 122 | case ERR_UNKNOWN_COMMAND: // 4014 123 | case ERR_WRONG_JUMP: // 4015 124 | case ERR_NOT_INITIALIZED_ARRAY: // 4016 125 | case ERR_DLL_CALLS_NOT_ALLOWED: // 4017 126 | case ERR_CANNOT_LOAD_LIBRARY: // 4018 127 | case ERR_CANNOT_CALL_FUNCTION: // 4019 128 | case ERR_EXTERNAL_CALLS_NOT_ALLOWED: // 4020 129 | case ERR_NO_MEMORY_FOR_RETURNED_STR: // 4021 130 | case ERR_SYSTEM_BUSY: // 4022 131 | case ERR_INVALID_FUNCTION_PARAMSCNT: // 4050 132 | case ERR_INVALID_FUNCTION_PARAMVALUE: // 4051 133 | case ERR_STRING_FUNCTION_INTERNAL: // 4052 134 | case ERR_SOME_ARRAY_ERROR: // 4053 135 | case ERR_INCORRECT_SERIESARRAY_USING: // 4054 136 | case ERR_CUSTOM_INDICATOR_ERROR: // 4055 137 | case ERR_INCOMPATIBLE_ARRAYS: // 4056 138 | case ERR_GLOBAL_VARIABLES_PROCESSING: // 4057 139 | case ERR_GLOBAL_VARIABLE_NOT_FOUND: // 4058 140 | case ERR_FUNC_NOT_ALLOWED_IN_TESTING: // 4059 141 | case ERR_FUNCTION_NOT_CONFIRMED: // 4060 142 | case ERR_SEND_MAIL_ERROR: // 4061 143 | case ERR_STRING_PARAMETER_EXPECTED: // 4062 144 | case ERR_INTEGER_PARAMETER_EXPECTED: // 4063 145 | case ERR_DOUBLE_PARAMETER_EXPECTED: // 4064 146 | case ERR_ARRAY_AS_PARAMETER_EXPECTED: // 4065 147 | case ERR_HISTORY_WILL_UPDATED: // 4066 148 | return(OFLIB_RUNTIME_ERROR); 149 | 150 | case ERR_TRADE_ERROR: // 4067 151 | return(OFLIB_BUSY_ERROR); 152 | 153 | case ERR_END_OF_FILE: // 4099 154 | case ERR_SOME_FILE_ERROR: // 4100 155 | case ERR_WRONG_FILE_NAME: // 4101 156 | case ERR_TOO_MANY_OPENED_FILES: // 4102 157 | case ERR_CANNOT_OPEN_FILE: // 4103 158 | case ERR_INCOMPATIBLE_FILEACCESS: // 4104 159 | return(OFLIB_FILE_ERROR); 160 | 161 | case ERR_NO_ORDER_SELECTED: // 4105 162 | case ERR_UNKNOWN_SYMBOL: // 4106 163 | case ERR_INVALID_PRICE_PARAM: // 4107 164 | case ERR_INVALID_TICKET: // 4108 165 | case ERR_TRADE_NOT_ALLOWED: // 4109 166 | case ERR_LONGS_NOT_ALLOWED: // 4110 167 | case ERR_SHORTS_NOT_ALLOWED: // 4111 168 | return(OFLIB_ORDER_ERROR); 169 | 170 | case ERR_OBJECT_ALREADY_EXISTS: // 4200 171 | case ERR_UNKNOWN_OBJECT_PROPERTY: // 4201 172 | case ERR_OBJECT_DOES_NOT_EXIST: // 4202 173 | case ERR_UNKNOWN_OBJECT_TYPE: // 4203 174 | case ERR_NO_OBJECT_NAME: // 4204 175 | case ERR_OBJECT_COORDINATES_ERROR: // 4205 176 | case ERR_NO_SPECIFIED_SUBWINDOW: // 4206 177 | case ERR_SOME_OBJECT_ERROR: // 4207 178 | return(OFLIB_WINDOW_ERROR); 179 | } 180 | return(OFLIB_OTHER_ERROR); 181 | } 182 | -------------------------------------------------------------------------------- /MQL4/Libraries/OTMql4/OTLibSimpleFormatCmd.mq4: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | #property copyright "Copyright 2013 OpenTrading" 4 | #property link "https://github.com/OpenTrading/" 5 | #property library 6 | 7 | // This is the replacement for what should be Eval in Mt4: 8 | // it takes a string expression and evaluates it. 9 | // 10 | // I know this is verbose and could be done more compactly, 11 | // but it's clean and robust so I'll leave it like this for now. 12 | // 13 | // If you want to extend this for your own functions you have declared in Mql4, 14 | // look at how OTLibProcessCmd.mq4 calls zMt4LibProcessCmd and then 15 | // goes on and handles it if zMt4LibProcessCmd didn't. 16 | // 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | string zOTLibSimpleFormatCmd(string uType, string uChartId, int iIgnore, string uMark, string uCmd) { 25 | // uType is cmd or exec 26 | // Both will be handled by ProcessCmd, but 27 | // cmd commands will be put back on the wire as a retval. 28 | // If uType is not cmd or exec then "" is returned to signal failure. 29 | // 30 | string uRetval; 31 | if (uType != "cmd" && uType != "exec") { 32 | return(""); 33 | } 34 | // FixMe: uBAR 35 | uRetval = StringFormat("%s|%s|%d|%s|%s", uType, uChartId, iIgnore, uMark, uCmd); 36 | return(uRetval); 37 | } 38 | 39 | string zOTLibSimpleFormatBar(string uType, string uChartId, int iIgnore, string uMark, string uInfo) { 40 | // uType should be one of: bar 41 | // Both will be put on the wire as a their type topics. 42 | // If uType is not tick timer or bar, then "" is returned to signal failure. 43 | 44 | string uRetval; 45 | if (uType != "bar") { 46 | return(""); 47 | } 48 | // FixMe: uBAR 49 | uRetval = StringFormat("%s|%s|%d|%s|%s", uType, uChartId, iIgnore, uMark, uInfo); 50 | return(uRetval); 51 | } 52 | 53 | string zOTLibSimpleFormatTimer(string uType, string uChartId, int iIgnore, string uMark, string uInfo) { 54 | // uType should be one of: tick or timer 55 | // Both will be put on the wire as a their type topics. 56 | // If uType is not tick timer or bar, then "" is returned to signal failure. 57 | // 58 | string uRetval; 59 | if (uType != "timer") { 60 | return(""); 61 | } 62 | // FixMe: uBAR 63 | uRetval = StringFormat("%s|%s|%d|%s|%s", uType, uChartId, iIgnore, uMark, uInfo); 64 | return(uRetval); 65 | } 66 | 67 | string zOTLibSimpleFormatTick(string uType, string uChartId, int iIgnore, string uMark, string uInfo) { 68 | // uType should be one of: tick or timer 69 | // Both will be put on the wire as a their type topics. 70 | // If uType is not tick timer or bar, then "" is returned to signal failure. 71 | // 72 | string uRetval; 73 | if (uType != "tick") { 74 | return(""); 75 | } 76 | // FixMe: uBAR 77 | uRetval = StringFormat("%s|%s|%d|%s|%s", uType, uChartId, iIgnore, uMark, uInfo); 78 | return(uRetval); 79 | } 80 | 81 | string zOTLibSimpleFormatRetval(string uType, string uChartId, int iIgnore, string uMark, string uInfo) { 82 | // uType should be one of: retval 83 | // Will be put on the wire as a its type topic. 84 | // If uType is not retval, then "" is returned to signal failure. 85 | // 86 | string uRetval; 87 | if (uType != "retval") { 88 | return(""); 89 | } 90 | if (uMark == "") { 91 | // Its already included in uInfo 92 | uRetval = StringFormat("%s|%s|%d|%s", uType, uChartId, iIgnore, uInfo); 93 | } else { 94 | // FixMe: uBAR 95 | uRetval = StringFormat("%s|%s|%d|%s|%s", uType, uChartId, iIgnore, uMark, uInfo); 96 | } 97 | return(uRetval); 98 | } 99 | 100 | string eOTLibSimpleUnformatCmd(string& aArrayAsList[]) { 101 | /* 102 | */ 103 | string uType, uChartId, uIgnore, uMark, uCmd; 104 | string uArg1=""; 105 | string uArg2=""; 106 | string uArg3=""; 107 | string uArg4=""; 108 | string uArg5=""; 109 | string uArg6=""; 110 | string uArg7=""; 111 | int iLen; 112 | string eRetval; 113 | 114 | iLen = ArraySize(aArrayAsList); 115 | if (iLen < 1) { 116 | eRetval = "eOTLibSimpleUnformatCmd iLen=0: split failed with " +uBAR; 117 | return(eRetval); 118 | } 119 | uType = StringTrimRight(aArrayAsList[0]); 120 | 121 | if (iLen < 2) { 122 | eRetval = "eOTLibSimpleUnformatCmd: split failed on field 2 "; 123 | return(eRetval); 124 | } 125 | uChartId = StringTrimRight(aArrayAsList[1]); 126 | 127 | if (iLen < 3) { 128 | eRetval = "eOTLibSimpleUnformatCmd: split failed on field 3 "; 129 | return(eRetval); 130 | } 131 | uIgnore = StringTrimRight(aArrayAsList[2]); 132 | 133 | if (iLen < 4) { 134 | eRetval = "eOTLibSimpleUnformatCmd: split failed on field 4 "; 135 | return(eRetval); 136 | } 137 | uMark = StringTrimRight(aArrayAsList[3]); 138 | if (StringLen(uMark) < 6) { 139 | eRetval = "eOTLibSimpleUnformatCmd uMark: too short " +uMark; 140 | return(eRetval); 141 | } 142 | if (iLen <= 4) { 143 | eRetval = "eOTLibSimpleUnformatCmd: split failed on field 5 "; 144 | return(eRetval); 145 | } 146 | uCmd = StringTrimRight(aArrayAsList[4]); 147 | 148 | if (iLen > 5) { 149 | uArg1 = StringTrimRight(aArrayAsList[5]); 150 | if (iLen > 6) { 151 | uArg2 = StringTrimRight(aArrayAsList[6]); 152 | if (iLen > 7) { 153 | uArg3 = StringTrimRight(aArrayAsList[7]); 154 | if (iLen > 8) { 155 | uArg4 = StringTrimRight(aArrayAsList[8]); 156 | if (iLen > 9) { 157 | uArg5 = StringTrimRight(aArrayAsList[9]); 158 | if (iLen > 10) { 159 | uArg6 = StringTrimRight(aArrayAsList[10]); 160 | if (iLen > 11) { 161 | uArg7 = StringTrimRight(aArrayAsList[11]); 162 | } 163 | } 164 | } 165 | } 166 | } 167 | } 168 | } 169 | ArrayResize(aArrayAsList, 12); 170 | aArrayAsList[0] = uType; 171 | aArrayAsList[1] = uChartId; 172 | aArrayAsList[2] = uIgnore; 173 | aArrayAsList[3] = uMark; 174 | aArrayAsList[4] = uCmd; 175 | aArrayAsList[5] = uArg1; 176 | aArrayAsList[6] = uArg2; 177 | aArrayAsList[7] = uArg3; 178 | aArrayAsList[8] = uArg4; 179 | aArrayAsList[9] = uArg5; 180 | aArrayAsList[10] = uArg6; 181 | aArrayAsList[11] = uArg7; 182 | return(""); 183 | } 184 | 185 | -------------------------------------------------------------------------------- /MQL4/Libraries/OTMql4/OTLibStrings.mq4: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | // Miscellaneous functions that help handling strings. 4 | // 5 | // This includes Ansi to Unicode "issues". 6 | // 7 | 8 | #property copyright "Copyright 2015, OpenTrading" 9 | #property link "https://github.com/OpenTrading/" 10 | #property library 11 | 12 | #import "kernel32.dll" 13 | int lstrlenA(int); 14 | void RtlMoveMemory(uchar & arr[], int, int); 15 | int LocalFree(int); // May need to be changed depending on how the DLL allocates memory 16 | #import 17 | 18 | //+----------------------------------------------------------------------------+ 19 | //| Lovely function that helps us to get ANSI strings from DLLs to our UNICODE | 20 | //| format | 21 | //| http://forum.mql4.com/60708 | 22 | //+----------------------------------------------------------------------------+ 23 | string uAnsi2Unicode(int iStringMemory) { 24 | int szString = lstrlenA(iStringMemory); 25 | uchar ucValue[]; 26 | ArrayResize(ucValue, szString + 1); 27 | RtlMoveMemory(ucValue, iStringMemory, szString + 1); 28 | string uMessage = CharArrayToString(ucValue); 29 | // Free the string memory returned by the DLL. 30 | // This step can be removed but, without it, there will be a memory leak. 31 | // The correct method for freeing the string 32 | // *depends on how the DLL allocated the memory* 33 | // The following assumes that the DLL has used LocalAlloc 34 | // (or an indirect equivalent). If not, 35 | // then the following line may not fix the leak, and may even cause a crash. 36 | LocalFree(iStringMemory); 37 | return(uMessage); 38 | } 39 | 40 | void vStringToArray(string uInput, string& uOutput[], string uDelim) { 41 | int iStart=0; 42 | int iDelpos; 43 | string uNextelem; 44 | 45 | if (uInput == "") return; 46 | ArrayResize(uOutput, 0); 47 | 48 | while(iStart < StringLen(uInput)) { 49 | iDelpos = StringFind(uInput, uDelim, iStart); 50 | if(iDelpos < 0) { 51 | uNextelem = StringSubstr(uInput,iStart); 52 | iStart = StringLen(uInput); 53 | } else { 54 | uNextelem = StringSubstr(uInput, iStart, iDelpos-iStart); 55 | iStart = iDelpos+1; 56 | } 57 | ArrayResize(uOutput, ArraySize(uOutput)+1); 58 | uOutput[ArraySize(uOutput)-1] = uNextelem; 59 | } 60 | } 61 | 62 | 63 | string uStringReplace(string uHaystack, string uNeedle, string uReplace) { 64 | string left, right; 65 | int iStart=0; 66 | int rlen=StringLen(uReplace); 67 | int nlen=StringLen(uNeedle); 68 | 69 | while (iStart > -1) { 70 | iStart = StringFind(uHaystack, uNeedle, iStart); 71 | if (iStart > -1) { 72 | if(iStart > 0) { 73 | left = StringSubstr(uHaystack, 0, iStart); 74 | } else { 75 | left = ""; 76 | } 77 | right = StringSubstr(uHaystack, iStart + nlen); 78 | uHaystack = left + uReplace + right; 79 | iStart = iStart + rlen; 80 | } 81 | } 82 | return (uHaystack); 83 | } 84 | 85 | -------------------------------------------------------------------------------- /MQL4/Libraries/OTMql4/OTLibTrading.mq4: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | #property copyright "Copyright 2013 OpenTrading" 4 | #property link "https://github.com/OpenTrading/" 5 | #property library 6 | 7 | // A More robust library of functions for Orders. 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | double fEPS=0.000001; 16 | 17 | int iOTOrderSelect(int iIndex, int iSelect, int iPool=MODE_TRADES) { 18 | // returns 1 on success, 0 or -iError on failure 19 | bool bRetval; 20 | 21 | bRetval=OrderSelect(iIndex, iSelect, iPool); 22 | if (bRetval != true) { 23 | int iError=GetLastError(); 24 | vWarn("Error selecting order # "+iIndex+ 25 | ": "+ErrorDescription(iError) +"("+iError+")"); 26 | return(-iError); 27 | } 28 | return(1); 29 | } 30 | 31 | int iOTOrderSendMarket(string uSymbol, int iCmd, double fVolume, 32 | int iStops=5, int iProfits=10, int slippage=3) { 33 | // int slippage, double stoploss, double fTakeprofit, 34 | double fPrice, fBid, fAsk; 35 | double fStoploss; 36 | double fTakeprofit; 37 | double fMinstoplevel; 38 | int iRetval, iDigits; 39 | 40 | if (bOTIsTradeAllowed() == false) { 41 | // does iOTRefreshRates() 42 | return(-1); 43 | } 44 | fBid = MarketInfo(uSymbol, MODE_BID); 45 | //? assert >0 46 | fAsk = MarketInfo(uSymbol, MODE_ASK); 47 | //? assert >0 48 | fMinstoplevel = MarketInfo(uSymbol, MODE_STOPLEVEL); 49 | iDigits = (int) MarketInfo(uSymbol, MODE_DIGITS); 50 | 51 | if (iCmd == OP_BUY) { 52 | //--- calculated SL and TP fPrices must be normalized 53 | fStoploss = NormalizeDouble(fBid-iStops*fMinstoplevel*Point, iDigits); 54 | fTakeprofit = NormalizeDouble(fAsk+iProfits*fMinstoplevel*Point, iDigits); 55 | fPrice = NormalizeDouble(fAsk, iDigits); 56 | } else { 57 | //--- calculated SL and TP fPrices must be normalized 58 | fStoploss = NormalizeDouble(fBid-iStops*fMinstoplevel*Point, iDigits); 59 | fTakeprofit = NormalizeDouble(fAsk+iProfits*fMinstoplevel*Point, iDigits); 60 | fPrice = NormalizeDouble(fBid, iDigits); 61 | } 62 | 63 | iRetval = iOTOrderSend(uSymbol, iCmd, 64 | fVolume, fPrice, slippage, 65 | fStoploss, fTakeprofit); 66 | // 130 is invalid stops 67 | return(iRetval); 68 | } 69 | 70 | int iOTOrderSend(string uSymbol, int cmd, 71 | double fVolume, double fPrice, int slippage, 72 | double fStoploss, double fTakeprofit, 73 | string comment="", int magic=0, datetime expiration=0, 74 | color arrow_color=CLR_NONE) { 75 | // Returns number of the ticket assigned to the order by the trade server or -1 if it fails. 76 | int iRetval; 77 | bool bContinuable = true; 78 | int iError; 79 | int iTick = 0; 80 | 81 | iTick=0; 82 | iError=0; 83 | while (bContinuable == true && iTick < OT_MAX_TICK_RETRIES) { 84 | iTick += 1; 85 | 86 | if (iOTSetTradeIsBusy() != 1) { 87 | vWarn(" Unable to acquire the trade context. Retrying (try #" + iTick + ")"); 88 | continue; 89 | } 90 | 91 | iRetval = OrderSend(uSymbol, cmd, fVolume, fPrice, slippage, fStoploss, 92 | fTakeprofit, comment, magic, expiration, arrow_color); 93 | iOTSetTradeIsNotBusy(); 94 | 95 | if (iRetval > 0) {return(iRetval);} 96 | 97 | iError=GetLastError(); 98 | vWarn("Error sending order: " +ErrorDescription(iError) +"("+iError+")"); 99 | // what about "no error" 100 | bContinuable = bOTLibServerErrorIsContinuable(iError); 101 | iRetval = -iError; 102 | } 103 | return(iRetval); 104 | } 105 | 106 | int iOTOrderCloseMarket(int iTicket, int iSlippage=3, color cColor=CLR_NONE) { 107 | // returns 1 on success, 0 or -iError on failure 108 | double fPrice=0.0; 109 | 110 | if (bOTIsTradeAllowed() == false) { 111 | // does iOTRefreshRates() 112 | return(-1); 113 | } 114 | //? use to default slippage? 115 | //fMinstoplevel = MarketInfo(uSymbol, MODE_STOPLEVEL); 116 | 117 | return(iOTOrderCloseFull(iTicket, fPrice, iSlippage, cColor)); 118 | } 119 | 120 | int iOTOrderCloseFull(int iTicket, double fPrice, int iSlippage=3, color cColor=CLR_NONE) { 121 | // returns 1 on success, 0 or -iError on failure 122 | double fLots=0.0; 123 | return(iOTOrderClose(iTicket, fLots, fPrice, iSlippage, cColor)); 124 | } 125 | 126 | int iOTOrderClose(int iTicket, double fLots, double fPrice, int iSlippage, color cColor=CLR_NONE) { 127 | 128 | // returns 1 on success, 0 or -iError on failure 129 | bool bRetval; 130 | bool bContinuable = true; 131 | int iError, iCmd, iDigits; 132 | int iTick=0; 133 | string uSymbol; 134 | double fBid, fAsk; 135 | 136 | iTick=0; 137 | iError=0; 138 | while (bContinuable == true && iTick < OT_MAX_TICK_RETRIES) { 139 | iTick += 1; 140 | if (iOTSetTradeIsBusy() != 1) { 141 | vWarn(" Unable to acquire the trade context. Retrying (try #" + 142 | iTick + ")"); 143 | continue; 144 | } 145 | if (fLots < fEPS || fPrice < fEPS) { 146 | iError = iOTOrderSelect(iTicket, SELECT_BY_TICKET, MODE_TRADES); 147 | if (iError <= 0) { 148 | vWarn("Select order failed " + 149 | " for order " + iTicket + 150 | ": " + ErrorDescription(GetLastError())); 151 | // FixMe?: check the error for fatal ones 152 | continue; 153 | } 154 | if (fLots < fEPS) { 155 | fLots = OrderLots(); 156 | } 157 | if (fPrice < fEPS) { 158 | uSymbol = OrderSymbol(); 159 | iCmd = OrderType(); 160 | iDigits = (int) MarketInfo(uSymbol, MODE_DIGITS); 161 | if (iCmd == OP_BUY) { 162 | fBid = MarketInfo(uSymbol, MODE_BID); 163 | //? assert >0 164 | fPrice = NormalizeDouble(fBid, iDigits); 165 | } else { 166 | fAsk = MarketInfo(uSymbol, MODE_ASK); 167 | //? assert >0 168 | fPrice = NormalizeDouble(fAsk, iDigits); 169 | } 170 | } 171 | } 172 | bRetval = OrderClose(iTicket, fLots, fPrice, iSlippage, cColor); 173 | iOTSetTradeIsNotBusy(); 174 | if (bRetval == true) { 175 | return(1); 176 | } 177 | iError=GetLastError(); 178 | vWarn("Error closing order # "+iTicket+ 179 | ": "+ErrorDescription(iError) +"("+iError+")"); 180 | 181 | // what about "no error" 182 | bContinuable = bOTLibServerErrorIsContinuable(iError); 183 | } 184 | 185 | return(-iError); 186 | } 187 | 188 | int iOTSetTradeIsBusy( int iMaxWaitingSeconds = 60 ) { 189 | /* 190 | from http://articles.mql4.com/141 191 | 192 | The function sets the global variable fTradeIsBusy value 0 with 1. 193 | If TradeIsBusy = 1 at the moment of launch, the function waits 194 | until TradeIsBusy is 0, and then replaces it with 1.0. 195 | If there is no global variable TradeIsBusy, the function creates it. 196 | 197 | Return codes: 198 | 1 - successfully completed. The global variable TradeIsBusy was assigned 1 199 | -1 - TradeIsBusy = 1 at the moment of launch, the waiting was interrupted by the user 200 | (the expert was removed from the chart, the terminal was closed, 201 | the chart period and/or symbol was changed, etc.) 202 | -2 - TradeIsBusy = 1 at the moment of launch of the function, the 203 | waiting limit was exceeded (60 sec) 204 | -3 - No connection to server 205 | */ 206 | int iError = 0; 207 | int StartWaitingTime; 208 | 209 | if(IsTesting()) return(1); 210 | if(!bOTIsTradeAllowed()) return(-3); 211 | //FixMe: something is broken below here and it may be overkill 212 | return(1); 213 | 214 | StartWaitingTime = GetTickCount(); 215 | 216 | // Check whether a global variable exists and, if not, create it 217 | while(true) { 218 | // if the expert was terminated by the user, stop operation 219 | if(IsStopped()) {return(-1);} 220 | 221 | // if the waiting time exceeds that specified in the variable 222 | // iMaxWaitingSeconds, stop operation, as well 223 | if ((GetTickCount() - StartWaitingTime) > iMaxWaitingSeconds * 1000) { 224 | vWarn("Waiting time (" + iMaxWaitingSeconds + " sec.) exceeded!"); 225 | return(-2); 226 | } 227 | // check whether the global variable exists 228 | // if it does, leave the loop and go to the block of changing 229 | // TradeIsBusy value 230 | if (GlobalVariableCheck( "fTradeIsBusy" )) break; 231 | 232 | // if the GlobalVariableCheck returns FALSE, it means that it does 233 | // not exist or an error has occurred during checking. 234 | iError = GetLastError(); 235 | if (iError != 0) { 236 | vWarn("Error in TradeIsBusy GlobalVariableCheck(\"TradeIsBusy\"): " + 237 | ErrorDescription(iError) ); 238 | Sleep(OT_TRADE_ORDER_SLEEP_MSEC); 239 | continue; 240 | } 241 | 242 | // if there is no error, it means that there is just no global variable, 243 | // try to create it as a temporary global variable. 244 | // if the GlobalVariableSet > 0, it means that the global variable 245 | // has been successfully created. Leave the function. 246 | GlobalVariableTemp("fTradeIsBusy"); 247 | if (GlobalVariableSet( "fTradeIsBusy", 1.0 ) > 0 ) { 248 | return(1); 249 | } 250 | // if the GlobalVariableSet has returned a value <= 0, 251 | // it means that an error occurred at creation of the variable 252 | iError = GetLastError(); 253 | if(iError != 0) { 254 | vWarn("Error in TradeIsBusy GlobalVariableSet(\"TradeIsBusy\",0.0 ): " + 255 | ErrorDescription(iError) ); 256 | Sleep(OT_TRADE_ORDER_SLEEP_MSEC); 257 | continue; 258 | } 259 | } 260 | 261 | // If the function execution has reached this point, it means that 262 | // the global variable variable exists. Wait until the TradeIsBusy 263 | // becomes = 0 and change the value of TradeIsBusy to 1 264 | 265 | while(true) { 266 | // if the expert was terminated by the user, stop operation 267 | if(IsStopped()) return(-1); 268 | 269 | // if the waiting time exceeds that specified in the variable 270 | // iMaxWaitingSeconds, stop operation, as well 271 | if(GetTickCount() - StartWaitingTime > iMaxWaitingSeconds * 1000) { 272 | vWarn("Waiting time (" + iMaxWaitingSeconds + " sec.) exceeded!"); 273 | return(-2); 274 | } 275 | // try to change the value of the TradeIsBusy from 0 to 1 276 | // if succeed, leave the function returning 1 ("successfully completed") 277 | if (GlobalVariableSetOnCondition( "fTradeIsBusy", 1.0, 0.0 )) { 278 | return(1); 279 | } 280 | // if not, 2 reasons for it are possible: TradeIsBusy = 1 (then one has to wait), or 281 | 282 | // an error occurred (this is what we will check) 283 | 284 | iError = GetLastError(); 285 | // if it is still an error, display information and try again 286 | if(iError != 0) { 287 | vWarn("Error in TradeIsBusy GlobalVariableSetOnCondition(\"TradeIsBusy\",1.0,0.0 ):" + 288 | ErrorDescription(iError) ); 289 | continue; 290 | } 291 | 292 | // if there is no error, it means that TradeIsBusy = 1 293 | // (another expert is trading), 294 | // then display information and wait... 295 | vInfo("Waiting for the trade context to become free..."); 296 | //? use refreshrates instead of sleep? - it can be slow 297 | // and may be called later on in the sequence that calls this 298 | Sleep(OT_TRADE_ORDER_SLEEP_MSEC); 299 | } 300 | /* should be unreached */ 301 | return(0); 302 | 303 | } 304 | 305 | 306 | int iOTSetTradeIsNotBusy() { 307 | // The function sets the value of the global variable fTradeIsBusy = 0. 308 | // If the fTradeIsBusy does not exist, the function creates it. 309 | int iError; 310 | 311 | // if testing, just terminate 312 | if(IsTesting()) return(0); 313 | 314 | //FixMe: something is broken below here and it may be overkill 315 | return(0); 316 | 317 | while(true) { 318 | // if the expert was terminated by the user, 319 | if(IsStopped()) return(-1); 320 | 321 | // try to set the global variable value = 0 322 | // (or create the global variable) 323 | // if the GlobalVariableSet returns a value > 0, it means that everything 324 | // has succeeded. Leave the function 325 | if (GlobalVariableSet( "fTradeIsBusy", 0.0 ) > 0) 326 | return(1); 327 | 328 | // if the GlobalVariableSet returns a value <= 0, 329 | // this means that an error has occurred. 330 | // Display information, wait, and try again 331 | iError = GetLastError(); 332 | if (iError != 0 ) { 333 | vWarn("Error in TradeIsNotBusy GlobalVariableSet(\"TradeIsBusy\",0.0): " + 334 | ErrorDescription(iError) ); 335 | } 336 | //? use refreshrates instead of sleep? - it can be slow 337 | // and may be called later on in the sequence that calls this 338 | Sleep(OT_TRADE_ORDER_SLEEP_MSEC); 339 | } 340 | /* should be unreached */ 341 | return(0); 342 | } 343 | 344 | 345 | /* 346 | fOTExposedEcuInMarket shows how much worse thing could get, unlike 347 | AccountMargin which shows how bad things are now. It's the worst case sum 348 | of Open against the order's fStoploss * return value < 0 means we have 349 | exposure * iOrderEAMagic=0 gives us exposed margin for ALL orders, ours or not. 350 | */ 351 | 352 | double fOTExposedEcuInMarket(int iOrderEAMagic = 0) { 353 | string uSymbol; 354 | int i; 355 | int iRetval; 356 | double fStopLoss; 357 | double fExposedEcu=0.0; 358 | 359 | for(i=OrdersTotal()-1; i>=0; i--) { 360 | 361 | iRetval = iOTOrderSelect(i, SELECT_BY_POS, MODE_TRADES); 362 | if (iRetval <= 0) { 363 | vWarn("Select order failed " + 364 | " for order " + i + 365 | ": " + ErrorDescription(GetLastError())); 366 | continue; 367 | } 368 | 369 | if (iOrderEAMagic > 0 && OrderMagicNumber() != iOrderEAMagic) continue; 370 | 371 | fStopLoss = OrderStopLoss(); 372 | if (fStopLoss < fEPS) { 373 | vWarn("The exposure is probably infinite " + 374 | " for order " + OrderTicket() +" (no stoploss)"); 375 | fExposedEcu = AccountFreeMargin(); 376 | return(fExposedEcu); 377 | } 378 | 379 | int iType = OrderType(); // Order type 380 | double fOrderLots = OrderLots(); 381 | uSymbol = OrderSymbol(); 382 | // FixMe: check retval 383 | double fLotSize = MarketInfo(uSymbol, MODE_LOTSIZE); 384 | double fOpenPrice = OrderOpenPrice(); 385 | double fMarginRequired = MarketInfo(uSymbol, MODE_MARGINREQUIRED); 386 | 387 | double fWorstCase; 388 | if (iType == OP_BUY) { 389 | if (fStopLoss < Bid) { 390 | fWorstCase = (Bid-fStopLoss)/Bid*fMarginRequired; 391 | fExposedEcu += fWorstCase * fOrderLots * fLotSize; 392 | vDebug("Exposure on order # "+i+ 393 | " fExposure="+ (fWorstCase * fOrderLots * fLotSize )+ 394 | " Bid="+Bid+ 395 | " fStopLoss="+fStopLoss+ 396 | " lots fMarginRequired="+fMarginRequired*fOrderLots * fLotSize); 397 | } 398 | } else if (iType == OP_SELL) { 399 | if (fStopLoss > Ask) { 400 | fWorstCase = (fStopLoss-Ask)/Ask*fMarginRequired; 401 | fExposedEcu += fWorstCase * fOrderLots * fLotSize; 402 | vDebug("Exposure on order # "+i+ 403 | " fExposure="+ (fWorstCase * fOrderLots * fLotSize)+ 404 | " Ask="+Ask+ 405 | " fStopLoss="+fStopLoss+ 406 | " lots fMarginRequired="+fMarginRequired*fOrderLots * fLotSize); 407 | } 408 | } 409 | } 410 | 411 | return(fExposedEcu); 412 | } 413 | 414 | bool bOTIsTradeAllowed() { 415 | /* 416 | Wait for the trade context to become free. 417 | Returns true if the trade context is free. 418 | 419 | You probably want to use this in place of RefreshRates: 420 | it checks IsTradeAllowed and runs RefreshRates. 421 | 422 | Warning: RefreshRates can take a long time. 423 | */ 424 | int iTicks = 0; 425 | 426 | if (IsTesting() || IsOptimization()) return (true); 427 | if (IsConnected() == false) { 428 | vWarn("Unable to trade : not connected"); 429 | return(false); 430 | } 431 | 432 | while( IsTradeAllowed() == false && iTicks < OT_MAX_TICK_RETRIES) { 433 | iTicks += 1; 434 | // use refresh rates to Cycle delay 435 | if (iOTRefreshRates() < 0) { 436 | return(false); 437 | } 438 | } 439 | if (iTicks >= OT_MAX_TICK_RETRIES) { 440 | vWarn("Unable to get TradeAllowed context for : "+ 441 | " in " + OT_MAX_TICK_RETRIES + " tries."); 442 | return(false); 443 | } 444 | return (true); 445 | } 446 | 447 | int iOTRefreshRates() { 448 | /* 449 | Returns 0 on success or -iError on failure 450 | 451 | Warning: RefreshRates can take a long time. 452 | */ 453 | int iTicks=0; 454 | 455 | if (IsTesting() || IsOptimization()) return (0); 456 | if (IsConnected() == false) { 457 | vWarn("Unable to refresh rates : not connected"); 458 | return(-1); 459 | } 460 | 461 | while(RefreshRates() == false && iTicks < OT_MAX_TICK_RETRIES) { 462 | iTicks += 1; 463 | Sleep(OT_TICK_SLEEP_MSEC); // Cycle delay 464 | } 465 | 466 | if (iTicks >= OT_MAX_TICK_RETRIES) { 467 | vWarn("Unable to refresh rates"+ 468 | " in " +OT_TICK_SLEEP_MSEC +"tries."); 469 | return(-2); 470 | } 471 | return(0); 472 | } 473 | /* This is wrong: MarketInfo returns many types */ 474 | int iOTMarketInfo(string s, int iMode) { 475 | /* 476 | Before using the MarketInfo() you should use the function RefreshRates() 477 | to be sure that we getting the up-to-date market data. 478 | 479 | */ 480 | int iRetval; 481 | int iError; 482 | if (s == "") { 483 | vWarn("iOTMarketInfo - Empty symbol for getting "+iMode); 484 | return(-1); 485 | } 486 | if (iMode <= 0) { 487 | vWarn("iOTMarketInfo - Negative mode for getting "+iMode+" for "+s); 488 | return(-1); 489 | } 490 | iRetval = MarketInfo(s, iMode); 491 | iError = GetLastError(); 492 | if (iError > 0) { 493 | vWarn("Error getting " +iMode +" for " +s 494 | +": "+ErrorDescription(iError)); 495 | return(-iError); 496 | } 497 | return(iRetval); 498 | } 499 | 500 | double fOTMarketInfo(string s, int iMode) { 501 | /* 502 | Before using the MarketInfo() you should use the function RefreshRates() 503 | to be sure that we getting the up-to-date market data. 504 | 505 | */ 506 | int iError; 507 | double fRetval; 508 | 509 | if (s == "") { 510 | vWarn("iOTMarketInfo - Empty symbol for getting "+iMode); 511 | return(-1.0); 512 | } 513 | if (iMode <= 0) { 514 | vWarn("iOTMarketInfo - Negative mode for getting "+iMode+" for "+s); 515 | return(-2.0); 516 | } 517 | fRetval = MarketInfo(s, iMode); 518 | iError = GetLastError(); 519 | if (iError > 0) { 520 | vWarn("Error getting " +iMode +" for " +s 521 | +": "+ErrorDescription(iError)); 522 | return(-iError*1.0); 523 | } 524 | return(fRetval); 525 | } 526 | 527 | // FixMe: should be per iTicket with uSymbol derived 528 | bool bOTModifyTrailingStopLoss(string uSymbol, int iTrailingStopLossPoints, 529 | datetime tExpiration=0) { 530 | // return value of false signals an error 531 | 532 | string sMsg; 533 | bool bRetval=true; 534 | int iRetval, i, iDigits; 535 | int iType, iMinDistance; 536 | double fTakeProfit; 537 | double fPrice; 538 | int iTicket; 539 | double fStopLoss; 540 | double fTrailingStopLoss; 541 | bool bModify; 542 | 543 | 544 | for(i=OrdersTotal()-1; i>=0; i--) { 545 | iRetval = OrderSelect(i, SELECT_BY_POS, MODE_TRADES); 546 | if (iRetval < 0) {bRetval=false; continue;} 547 | 548 | // Analysis of orders: 549 | iType = OrderType(); // Order type 550 | if (OrderSymbol() != uSymbol || iType > 1) continue; 551 | iMinDistance = MarketInfo(uSymbol, MODE_STOPLEVEL); 552 | if (iMinDistance < 0) {bRetval=false; continue;} 553 | 554 | fTakeProfit = OrderTakeProfit(); // TakeProfit of the selected order 555 | fPrice = OrderOpenPrice(); // Price of the selected order 556 | iTicket = OrderTicket(); // Ticket of the selected order 557 | fStopLoss = OrderStopLoss(); // SL of the selected order 558 | iDigits = (int) MarketInfo(uSymbol, MODE_DIGITS); 559 | 560 | fTrailingStopLoss = iTrailingStopLossPoints; // Initial value 561 | if (fTrailingStopLoss < iMinDistance) { 562 | // If less than allowed 563 | fTrailingStopLoss = iMinDistance; 564 | } 565 | 566 | bModify = false; // Not to be modified 567 | switch(iType) { 568 | case OP_BUY: // Order Buy 0 569 | if (NormalizeDouble(fStopLoss, iDigits) < // If it is lower than we want 570 | NormalizeDouble(Bid-fTrailingStopLoss*Point, iDigits) && 571 | Bid-fTrailingStopLoss*Point > fTrailingStopLoss*Point/10.0 //? why 572 | ) { 573 | fStopLoss = Bid-fTrailingStopLoss*Point; // then modify it 574 | sMsg = "Buy "; 575 | bModify = true; // To be modified 576 | } 577 | break; // Exit 'switch' 578 | case OP_SELL: // Order Sell 1 579 | if (NormalizeDouble(fStopLoss, iDigits) > // If it is higher than we want 580 | NormalizeDouble(Ask+fTrailingStopLoss*Point, iDigits) && 581 | Ask+fTrailingStopLoss*Point > fTrailingStopLoss*Point/10.0 //? why 582 | ) { 583 | // || NormalizeDouble(fStopLoss, Digits)==0 //or equal to zero 584 | fStopLoss=Ask+fTrailingStopLoss*Point; // then modify it 585 | sMsg = "Sell "; 586 | bModify = true; 587 | } 588 | } 589 | 590 | if (bModify==false) continue; 591 | 592 | bRetval = bRetval && bOTModifyOrder("Modifiying stoploss "+sMsg, 593 | iTicket, fPrice, 594 | fStopLoss, fTakeProfit, 595 | tExpiration); 596 | } 597 | 598 | return(bRetval); 599 | } 600 | 601 | bool bOTModifyOrder(string sMsg, 602 | int iTicket, 603 | double fPrice, 604 | double fStopLoss, 605 | double fTakeProfit, 606 | datetime tExpiration) { 607 | // FixMe: how do we check and order has been selected? 608 | int iRetry=0; 609 | int iTicks, iDigits; 610 | bool bAns; 611 | bool bRetval=false; 612 | string uSymbol; 613 | 614 | uSymbol = OrderSymbol(); 615 | iDigits = (int) MarketInfo(uSymbol, MODE_DIGITS); 616 | while(iRetry < OT_MAX_TICK_RETRIES) { 617 | // Modification cycle 618 | iRetry += 1; 619 | vInfo(sMsg +iTicket +" at " +Bid 620 | +" from sl " +OrderStopLoss()+" to " +fStopLoss 621 | +" from tp " +OrderTakeProfit()+" to " +fTakeProfit 622 | +". Awaiting response."); 623 | bAns = OrderModify(iTicket, NormalizeDouble(fPrice, iDigits), 624 | NormalizeDouble(fStopLoss, iDigits), 625 | NormalizeDouble(fTakeProfit, iDigits), 626 | tExpiration); 627 | 628 | if (IsTesting() || IsOptimization() || bAns==true) { 629 | vInfo("Order " +sMsg+iTicket +" is modified: "); 630 | return(true); 631 | } 632 | 633 | if (bOTContinueOnOrderError(iTicket)) { 634 | iTicks = 0; 635 | while ( RefreshRates()==false && iTicks < OT_MAX_TICK_RETRIES) { 636 | // To the new tick 637 | iTicks += 1; 638 | Sleep(OT_TICK_SLEEP_MSEC); // Cycle delay 639 | } 640 | if (iTicks >= OT_MAX_TICK_RETRIES) {break;} 641 | } 642 | } 643 | 644 | vWarn("Error modifying Order # " +iTicket +": " 645 | // +" " +ErrorDescription(iError) 646 | ); 647 | return(bRetval); 648 | } 649 | 650 | bool bOTContinueOnOrderError(int iTicket) { 651 | bool bContinue=false; 652 | int iError=GetLastError(); 653 | 654 | switch(iError) { 655 | // Overcomable errors 656 | case 130: 657 | Print("Wrong stops. Retrying."); 658 | bContinue=true; break; // At the next iteration 659 | case 136: 660 | Print("No prices. Waiting for a new tick.."); 661 | bContinue=true; break; // At the next iteration 662 | case 146: 663 | Print("Trading subsystem is busy. Retrying "); 664 | bContinue=true; break; // At the next iteration 665 | // Critical errors 666 | case 1 : 667 | Print("No error."); // WTF? 668 | break; // Exit 'switch' 669 | default: 670 | bContinue=bOTLibServerErrorIsContinuable(iError); 671 | break; 672 | } 673 | return(bContinue); 674 | } 675 | 676 | -------------------------------------------------------------------------------- /MQL4/Python/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenTrading/OTMql4Lib/3c07f4c373e549e627686af2056f160a9ed50469/MQL4/Python/__init__.py -------------------------------------------------------------------------------- /MQL4/Scripts/OTMql4/OTLibTest.mq4: -------------------------------------------------------------------------------- 1 | // -*-mode: c; c-style: stroustrup; c-basic-offset: 4; coding: utf-8-dos -*- 2 | 3 | #property copyright "Copyright 2014 Open Trading" 4 | #property link "https://github.com/OpenTrading/" 5 | 6 | // A simple test Script that doesn't do much, but it's a start. 7 | // Attach it to a chart, select the tests you want to run, 8 | // and a MessageBox will pop up to tell you if it passed or failed. 9 | 10 | #property show_inputs 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | // We will put each test as a boolean external input so the user 19 | // can select which tests to run. 20 | 21 | extern bool bTestStrings=true; 22 | extern bool bTestOTLibProcessCmd=true; 23 | 24 | double fEps=0.000001; 25 | 26 | void vAlert(string uText) { 27 | MessageBox(uText, "OTLibTest.mq4", MB_OK|MB_ICONEXCLAMATION); 28 | } 29 | 30 | string eTestStrings() { 31 | // Test our parsing of strings with vStringToArray 32 | // 33 | int iErr = 0; 34 | string uRetval = ""; 35 | string uArg; 36 | string aOutput[]; 37 | 38 | uArg = "one"; 39 | vStringToArray(uArg, aOutput, "|"); 40 | if (ArraySize(aOutput) == 1) { 41 | Print("INFO: ArraySize(aOutput) == 1 -> " +uArg); 42 | } else { 43 | return("ERROR: ArraySize(aOutput) != 1 -> " +uArg); 44 | } 45 | 46 | uArg = "one|two|three"; 47 | vStringToArray(uArg, aOutput, "|"); 48 | if (ArraySize(aOutput) == 3) { 49 | Print("INFO: ArraySize(aOutput) == 3 -> " +uArg); 50 | } else { 51 | return("ERROR: ArraySize(aOutput) != 3 -> " +uArg); 52 | } 53 | return(""); 54 | } 55 | 56 | string eTestOTLibProcessCmd() { 57 | int iErr = 0; 58 | string uRetval = ""; 59 | string uArg; 60 | string aOutput[]; 61 | string uExpect; 62 | 63 | uArg = "one"; 64 | uRetval = zOTLibProcessCmd(uArg); 65 | if (StringCompare(uRetval, "") == 0) { 66 | Print("INFO: GOOD there be an error message in the Experts Log -> " +uArg); 67 | } else { 68 | return("ERROR: should NOT have returned a value -> " +uRetval); 69 | } 70 | 71 | uArg = "exec|USDUSD|0|123456|TerminalPath"; 72 | uRetval = zOTLibProcessCmd(uArg); 73 | uExpect = "123456|string|" +TerminalPath(); 74 | if (uRetval == uExpect) { 75 | Print("INFO: GOOD right answer -> " +uArg); 76 | } else { 77 | return("ERROR: wrong return value -> " +uRetval); 78 | } 79 | return(""); 80 | } 81 | 82 | void OnStart() { 83 | string uRetval = ""; 84 | int i = 0; 85 | if ( bTestStrings == true ) { 86 | uRetval = eTestStrings(); 87 | if (uRetval != "") { 88 | vAlert(uRetval); 89 | } else { 90 | i = i + 1; 91 | } 92 | } 93 | if ( bTestOTLibProcessCmd == true ) { 94 | uRetval = eTestOTLibProcessCmd(); 95 | if (uRetval != "") { 96 | vAlert(uRetval); 97 | } else { 98 | i = i + 1; 99 | } 100 | } 101 | if ( i > 0 ) { 102 | uRetval = "INFO: tests completed"; 103 | vAlert(uRetval); 104 | } 105 | } 106 | 107 | void OnDeinit(const int iReason) { 108 | } 109 | -------------------------------------------------------------------------------- /README.creole: -------------------------------------------------------------------------------- 1 | OpenTrading Mt4 Library Code 2 | https://github.com/OpenTrading/OTMql4Lib 3 | 4 | The OTMql4Lib aims to provide a high-quality library of code to Metatrader 4, 5 | with testing and documentation, that can serve as a basis to other projects. 6 | It is the common library of Mt4 code to all of the OpenTrading projects: 7 | https://github.com/OpenTrading/ and is required as a prerequisite by OpenTrader 8 | https://github.com/OpenTrading/OpenTrader 9 | 10 | One of the key funtionalities that it provides is the {{{ProcessCmd}}} functions 11 | which is a simple replacement for what should be an {{{Eval}}} command in Mt4, 12 | to allow an Expert to evaluate arbirtary Mt4 commands. This can be used by 13 | any Remote Procedure Call libraries to send commands to Mt4 for evaluation. 14 | 15 | **This is a work in progress - a developers' version.** 16 | 17 | === Installation === 18 | 19 | There is now an installer in the Releases section on github: 20 | see https://github.com/OpenTrading/OTMql4Lib/wiki/Installation 21 | 22 | === Project === 23 | 24 | Please file any bugs in the issues tracker: 25 | https://github.com/OpenTrading/OTMql4Lib/issues 26 | 27 | Use the Wiki to start topics for discussion: 28 | https://github.com/OpenTrading/OTMql4Lib/wiki/Home 29 | It's better to use the wiki for knowledge capture, and then we can pull the 30 | important pages back into the documentation in the {{{share/doc}}} directory. 31 | You will need to be signed into github.com to edit in the wiki. 32 | 33 | * Home (https://github.com/OpenTrading/OTMql4Lib/wiki/Home) 34 | 35 | * TitleIndex (https://github.com/OpenTrading/OTMql4Lib/wiki/TitleIndex) 36 | -------------------------------------------------------------------------------- /share/html/CodeLibraries.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Code Libraries 6 | 7 | 8 | 9 | 10 |

Libraries

11 | 12 |

See https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4

13 | 14 | 24 |

This file is automatically generated from the source code: do not edit.

25 |
26 | 27 |

Parent: Home

28 | 29 | -------------------------------------------------------------------------------- /share/html/CodeScripts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Code Scripts 6 | 7 | 8 | 9 | 10 |

Scripts

11 | 12 |

See https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Scripts/OTMql4

13 | 14 | 17 |

This file is automatically generated from the source code: do not edit.

18 |
19 | 20 |

Parent: Home

21 | 22 | -------------------------------------------------------------------------------- /share/html/DevelopmentStyle.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Development Style 6 | 7 | 8 | 9 | 10 |

Coding Style

11 | 12 |

Metatrader has been a great international success, putting into the
13 | hands of end-users the ability to do programmed trading, something
14 | that was only previously available to large trading houses. It has
15 | been widely adopted, provides a credible platform for Forex trading,
16 | and there are a huge number of "experts" and programs that have been
17 | developed for it.

18 | 19 |

However, Metatrader as a language is not without some significant
20 | drawbacks. The language is very rudimentary from the computer science
21 | point of view, and is a closed sole-source product. Very importantly
22 | for writing robust, well-tested and easily maintained code, it lacks
23 | proper error handling flow-of-control constructs, such as are found in
24 | Java, Python or Lisp. This leads to poor quality code, as can be seen
25 | by much of the MQL code in existence, including the code from the
26 | manufacturer, MetaQuotes. The poor nature of the language combines
27 | with the very poor coding practices of the community (e.g. not
28 | checking error codes and no documentation or testing) to create a very
29 | poor programming environment.

30 | 31 |

Type Prefixing

32 | 33 |

We prefix all variable, function and method names with a lowercase letter
34 | that indicates the type; it helps you anticipate what type a quantity
35 | is, and to make explicit type conversions. This is not a rigid requirement,
36 | but it helps cut down on a very common type of mistake, pun intended.

37 | 38 |

If the type changes, give it a new name with the initial letter changed.
39 | In Mql, this scheme has the added advantage of avoiding any naming
40 | conflict with Mql built-ins, or most Python standard library modules.

41 | 42 |

Choose the initial letter from the following list:

43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 |
Prefix LetterVariable Type
aarray
bboolean
ccomplex (unused)
dalist or dictionary
eerror string return value, empty for success
fdouble
ggeneric - unknown or mutable
hhypertext - HTML/XML entity encoded string
iinteger
jjson string
llist or tuple (unused)
oinstance or pointer to a class
rseries
sASCII string
tdate/time value
uUnicode string
vvoid - return value not to be used
znon-empty string return - empty is a failure
122 | 125 |
126 | 127 |

Parent: Home

128 | 129 | -------------------------------------------------------------------------------- /share/html/DirectoryStructure.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Directory Structure 6 | 7 | 8 | 9 | 10 |

Directory Structure

11 | 12 |

We adopt a standard directory structure for all projects, so that it
13 | will be obvious what directory things should go in as the projects
14 | progress, and it will make it easier to share code and transfer
15 | knowledge between projects. The directory structure must be complete
16 | so that it will support the final wrapping of the deliverable,
17 | including all documentation.

18 | 19 |

The standardized Unix layout works for both MultiPlatformCoding under
20 | both Unix and Windows, and many configuration tools assume its layout. The
21 | layout is the defacto-standard created by the GNU
22 | toolchain.

23 | 24 |

In your top project directory you should find:

25 | 26 |
    27 |
  • bin: binary directory. This will contain executables, for either the main program, or support tools. For multi-platform work assume that there may be platform and OS dependent subdirectories such as
  • 28 |
  • bin/windows-x86: windows subdirectory
  • 29 |
  • bin/linux-x86: linux subdirectory
  • 30 |
31 |
    32 |
  • etc: configuration files - may be empty.
  • 33 |
34 |
    35 |
  • lib: library directory. This will contain object libraries, for either the main program, or support tools. For multi-platform work, assume that there will be platform and OS dependent files under lib.
  • 36 |
37 |
    38 |
  • net: Repository for files downloaded from the net, for all bundled prerquisites of code or tools required by the program. It may also contain the orginal version of code that this project extends, so that it's easy to compare the preoject with its origins. Make protocol subdirectories such as net/Http net/Ftp and in these subdirectories, put the name of the site the package was downloaded from.
  • 39 |
40 |
    41 |
  • share: platform independent library directories. For example, the on-line documentation might go in share/doc or in share/html and icons might go in share/icons etc.
  • 42 |
43 |
    44 |
  • src: The source code for the application and any of the tools it requires.
  • 45 |
46 |
    47 |
  • var: variable run-time data, initially empty. May have subdirectories like var/log for log files, var/cache for runtime files, var/tmp for temporary files etc.
  • 48 |
49 |
50 | 51 |

Parent: DevelopmentStyle

52 | 53 | -------------------------------------------------------------------------------- /share/html/FrontPage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Front Page 6 | 7 | 8 | 9 | 10 |

OpenTrading Mt4 Library Code
11 | https://github.com/OpenTrading/OTMql4Lib

12 | 13 |

The OTMql4Lib aims to provide a high-quality library of code to Metatrader 4,
14 | with testing and documentation, that can serve as a basis to other projects.
15 | It is the common library of Mt4 code to all of the OpenTrading projects:
16 | https://github.com/OpenTrading/ and is required as a prerequisite by OpenTrader
17 | https://github.com/OpenTrading/OpenTrader

18 | 19 |

One of the key funtionalities that it provides is the ProcessCmd functions
20 | which is a simple replacement for what should be an Eval command in Mt4,
21 | to allow an Expert to evaluate arbirtary Mt4 commands. This can be used by
22 | any Remote Procedure Call libraries to send commands to Mt4 for evaluation.

23 | 24 |

This is a work in progress - a developers' version.

25 | 26 |

Installation

27 | 28 |

There is now an installer in the Releases section on github:
29 | see https://github.com/OpenTrading/OTMql4Lib/wiki/Installation

30 | 31 |

Project

32 | 33 |

Please file any bugs in the issues tracker:
34 | https://github.com/OpenTrading/OTMql4Lib/issues

35 | 36 |

Use the Wiki to start topics for discussion:
37 | https://github.com/OpenTrading/OTMql4Lib/wiki/Home
38 | It's better to use the wiki for knowledge capture, and then we can pull the
39 | important pages back into the documentation in the share/doc directory.
40 | You will need to be signed into github.com to edit in the wiki.

41 | 42 | 45 | 48 | 49 | -------------------------------------------------------------------------------- /share/html/Home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Home 6 | 7 | 8 | 9 | 10 |

Welcome to the OTMql4Lib project!

11 | 12 |

The OTMql4Lib aims to provide a high-quality library of code to Metatrader 4,
13 | with testing and documentation, that can serve as a basis to other projects.
14 | It is the common library of Mt4 code to all of the OpenTrading projects:
15 | https://github.com/OpenTrading/ and is required as a prerequisite by OpenTrader
16 | https://github.com/OpenTrading/OpenTrader

17 | 18 |

One of the key funtionalities that it provides is the ProcessCmd functions
19 | which is a simple replacement for what should be an Eval command in Mt4,
20 | to allow an Expert to evaluate arbirtary Mt4 commands. This can be used by
21 | any Remote Procedure Call libraries to send commands to Mt4 for evaluation.

22 | 23 |

Documentation

24 | 25 |

There is now an installer in the Releases section on github: see

26 | 29 | 33 | 36 | 39 |

Project

40 | 41 |

Please file any bugs in the issues tracker:
42 | https://github.com/OpenTrading/OTMql4Lib/issues

43 | 44 |

Use the Wiki to start topics for discussion:
45 | https://github.com/OpenTrading/OTMql4Lib/wiki
46 | It's better to use the wiki for knowledge capture, and then we can pull
47 | the important pages back into the documentation in the share/doc directory.
48 | You will need to be signed into github.com to see or edit in the wiki.

49 | 50 | -------------------------------------------------------------------------------- /share/html/Installation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Installation 6 | 7 | 8 | 9 | 10 |

Binary Installer

11 | 12 |

There is now an installer in the Releases section on github:
13 | https://github.com/OpenTrading/OTMql4Lib/releases
14 | It's a simple installer that asks where you want the software installed,
15 | and the location of your personal AppData Metatrader directory,
16 | and copies the files to the right places; it installs a copy of the
17 | documentation too. Usually you could just overwrite old releases with
18 | new ones, but for now, we recommend uninstalling old releases before
19 | installing new ones in case the filenames or locations have changed.

20 | 21 |

If you have a recent (2016) release of Mt4, the location of your personal
22 | Metatrader directory to install into is no longer the Program Files
23 | directory (something like c:\Program Files\MetaTrader 4 Terminal)
24 | but rather your personal AppData directory (something like
25 | c:\Users\Administrator\AppData\Roaming\MetaQuotes\Terminal\LONGHEXNAME).

26 | 27 |

When you start Metatrader, look for the Data Directory: message
28 | in the Journal log. Usually there are 2 possibilities: if you have a
29 | subdirectory of your Users\AppData\Roaming\MetaQuotes\Terminal and
30 | then a long hexadecimal name, use it. Otherwise look in c:\Program Files
31 | for the Metatrader directory. Use the Browse button to select it,
32 | then click Next.

33 | 34 |

Install from Source

35 | 36 |

Alernatively, you can just "git clone" or download the zip from github.com
37 | and unzip into an empty directory. Then recursively copy the folder
38 | MQL4 over the MQL4 folder of your personal AppData... directory
39 | (something like
40 | c:\Users\Administrator\AppData\Roaming\MetaQuotes\Terminal\LONGHEXNAME).
41 | It will not overwrite any system files, and keeps its files in subdirectories
42 | called OTMql4.

43 | 44 |

New Mt4 Layout

45 | 46 |

From the https://docs.mql4.com/files :

47 | 48 |

There are two directories (with subdirectories) in which working files can be located:

49 | 50 |
    51 |
  • terminal_data_folder\MQL4\Files (in the terminal menu select to view "File" - "Open the data directory");
  • 52 |
53 |
    54 |
  • the common folder for all the terminals installed on a computer - usually located in the directory C:\Documents and Settings\All Users\Application Data\MetaQuotes\Terminal\Common\Files.
  • 55 |
56 |

There is a program method to obtain names of these catalogs using the
57 | TerminalInfoString() function, using the ENUM_TERMINAL_INFO_STRING
58 | enumeration:

59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 |
TERMINAL_PATHFolder from which the terminal is startedstring
TERMINAL_DATA_PATHFolder in which terminal data are storedstring
TERMINAL_COMMONDATA_PATHCommon path for all of the terminals installed on a computerstring
76 |

We have chosen to install to the TERMINAL_DATA_PATH to give people the
77 | option of having multiple Mt4 installations, each configured differently.

78 | 79 |

The long hex directory name is the md5 hash of the installation directory, then

80 |
    81 |
  • convert path to uppercase with no trailing slash
  • 82 |
  • convert to base64 string using unicode encoding
  • 83 |
  • MD5 has the result from step 2See https://forum.mql4.com/60897/page2
  • 84 |
85 | 86 | -------------------------------------------------------------------------------- /share/html/OTLibJsonFormat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OTLib Json Format 6 | 7 | 8 | 9 | 10 |

MQL4/Libraries/OTMql4/OTLibJsonFormat.mq4

11 | 12 |

JSON formatting for sending information to clients.
13 | This is simple string formatting: a JSON structure or class is never used.

14 | 15 |

string jOTAccountInformation()
16 | Retrieve the Account information as a JSON structure.
17 | This brings back all of the ususal Account* calls,
18 | with the values formatted as strings, intergers or floats.

19 | 20 |

string jOTOrdersTickets()

21 | 22 |

string jOTOrdersTrades()

23 | 24 |

string jOTOrdersHistory()

25 | 26 |

string jOTOrders(int iMode)

27 | 28 |

string jOTOrderInformationByTicket(int iTicket)

29 | 30 |

string jOTMarketInformation(string uSymbol)

31 | 32 |

string jOTTickInformation(string uSymbol, int iTimeFrame)

33 | 34 |

string jOTBarInformation(string uSymbol, int iTimeFrame, int iBar)

35 | 36 |

string jOTTimerInformation()

37 | 38 |

Source code: https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4/OTLibJsonFormat.mq4

39 | 40 |

This file is automatically generated from the source code: do not edit.

41 |
42 | 43 |

Parent: CodeLibraries

44 | 45 | -------------------------------------------------------------------------------- /share/html/OTLibLog.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OTLib Log 6 | 7 | 8 | 9 | 10 |

MQL4/Libraries/OTMql4/OTLibLog.mq4

11 | 12 |

This will provide our logging functions, but is just a
13 | skeleton for now. See OTLibPyLog for logging with Python.

14 | 15 |

void vLogInit()
16 | Initializes the logging environment. This should be called
17 | from your OnInit() function. It is safe to call it a second time;
18 | subsequent calls will just be ignored.

19 | 20 |

void vSetLogLevel(int i)

21 | 22 |

int iGetLogLevel()

23 | 24 |

void vLog(int iLevel, string sMess)

25 | 26 |

void vError(string sMess)

27 | 28 |

void vWarn(string sMess)

29 | 30 |

void vInfo(string sMess)

31 | 32 |

void vDebug(string sMess)

33 | 34 |

void vTrace(string sMess)

35 | 36 |

Source code: https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4/OTLibLog.mq4

37 | 38 |

This file is automatically generated from the source code: do not edit.

39 |
40 | 41 |

Parent: CodeLibraries

42 | 43 | -------------------------------------------------------------------------------- /share/html/OTLibMt4ProcessCmd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OTLib Mt4Process Cmd 6 | 7 | 8 | 9 | 10 |

MQL4/Libraries/OTMql4/OTLibMt4ProcessCmd.mq4

11 | 12 |

string zOTLibMt4ProcessCmd(string uMess)
13 | This is the replacement for what should be Eval in Mt4:
14 | take a string expression and evaluate it.
15 | zMt4LibProcessCmd only handles base Mt4 expressions.
16 | Returns the result of processing the command as a string
17 | in the form "type|value" where type is one of:
18 | string, int, double, bool, datetime, void, json
19 | Returns "error|explanation" if there is an error.
20 | Returns "" if the the command was not recognized;
21 | you can use this fact to process the standard Mt4 commands
22 | with zOTLibMt4ProcessCmd, and if it returns "",
23 | write your own zMyProcessCmd to process your additions.

24 | 25 |

string zProcessCmdTer(string uCmd, string uChartId, string uIgnore, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5)

26 | 27 |

string zProcessCmdWin(string uCmd, string uChartId, string uIgnore, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5)

28 | 29 |

string zProcessCmdAcc(string uCmd, string uChartId, string uIgnore, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5)

30 | 31 |

string zProcessCmdGlo(string uCmd, string uChartId, string uIgnore, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5)

32 | 33 |

Source code: https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4/OTLibMt4ProcessCmd.mq4

34 | 35 |

This file is automatically generated from the source code: do not edit.

36 |
37 | 38 |

Parent: CodeLibraries

39 | 40 | -------------------------------------------------------------------------------- /share/html/OTLibProcessCmd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OTLib Process Cmd 6 | 7 | 8 | 9 | 10 |

MQL4/Libraries/OTMql4/OTLibProcessCmd.mq4

11 | 12 |

This is the replacement for what should be Eval in Mt4:
13 | take a string expression and evaluate it.
14 | We know this is verbose and could be done more compactly,
15 | but it's clean and robust so we'll leave it like this for now.
16 | If you want to extend this for your own functions you have declared in Mql4,
17 | look at how zOTLibProcessCmd calls zMt4LibProcessCmd and then
18 | goes on and handles it if zMt4LibProcessCmd didn't.

19 | 20 |

string zOTLibProcessCmd(string uMess)
21 | This is the replacement for what should be Eval in Mt4:
22 | take a string expression and evaluate it.
23 | zMt4LibProcessCmd handles base Mt4 expressions, and
24 | zOTLibProcessCmd also handles base OpenTrading expressions.
25 | Returns the result of processing the command.
26 | Returns "" if there is an error.

27 | 28 |

string uProcessCmdi (string uCmd, string uChartId, string uIgnore, string uMark, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5, string uArg6, string uArg7)

29 | 30 |

string uProcessCmdOT(string uCmd, string uChartId, string uIgnore, string uMark, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5, string uArg6, string uArg7)

31 | 32 |

string uProcessCmdgOT(string uCmd, string uChartId, string uIgnore, string uMark, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5, string uArg6, string uArg7)

33 | 34 |

Source code: https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4/OTLibProcessCmd.mq4

35 | 36 |

This file is automatically generated from the source code: do not edit.

37 |
38 | 39 |

Parent: CodeLibraries

40 | 41 | -------------------------------------------------------------------------------- /share/html/OTLibServerErrors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OTLib Server Errors 6 | 7 | 8 | 9 | 10 |

MQL4/Libraries/OTMql4/OTLibServerErrors.mq4

11 | 12 |

One of the many fundamental defects of the Mql4 language
13 | is that there is no Object Oriented error handling.
14 | This leads to Mq4 returning hundreds of different errors
15 | that are not grouped so that we can take actions based
16 | on classes of errors.
17 | We try to group the large number of errors into 9 groups
18 | so that we can for example retry a trade when there is
19 | some kind of network error.

20 | 21 |

bool bOTLibServerErrorIsContinuable(int iErr)

22 | 23 |

bool bOTLibServerErrorType(int iErr)
24 | Group the errors returned from trade server
25 | so that we can take action based on classes of errors.

26 | 27 |

Source code: https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4/OTLibServerErrors.mq4

28 | 29 |

This file is automatically generated from the source code: do not edit.

30 |
31 | 32 |

Parent: CodeLibraries

33 | 34 | -------------------------------------------------------------------------------- /share/html/OTLibSimpleFormatCmd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OTLib Simple Format Cmd 6 | 7 | 8 | 9 | 10 |

MQL4/Libraries/OTMql4/OTLibSimpleFormatCmd.mq4

11 | 12 |

This is the replacement for what should be Eval in Mt4:
13 | it takes a string expression and evaluates it.
14 | I know this is verbose and could be done more compactly,
15 | but it's clean and robust so I'll leave it like this for now.
16 | If you want to extend this for your own functions you have declared in Mql4,
17 | look at how OTLibProcessCmd.mq4 calls zMt4LibProcessCmd and then
18 | goes on and handles it if zMt4LibProcessCmd didn't.

19 | 20 |

string zOTLibSimpleFormatCmd(string uType, string uChartId, int iIgnore, string uMark, string uCmd)
21 | uType is cmd or exec
22 | Both will be handled by ProcessCmd, but
23 | cmd commands will be put back on the wire as a retval.
24 | If uType is not cmd or exec then "" is returned to signal failure.

25 | 26 |

string zOTLibSimpleFormatBar(string uType, string uChartId, int iIgnore, string uMark, string uInfo)
27 | uType should be one of: bar
28 | Both will be put on the wire as a their type topics.
29 | If uType is not tick timer or bar, then "" is returned to signal failure.

30 | 31 |

string zOTLibSimpleFormatTimer(string uType, string uChartId, int iIgnore, string uMark, string uInfo)
32 | uType should be one of: tick or timer
33 | Both will be put on the wire as a their type topics.
34 | If uType is not tick timer or bar, then "" is returned to signal failure.

35 | 36 |

string zOTLibSimpleFormatTick(string uType, string uChartId, int iIgnore, string uMark, string uInfo)
37 | uType should be one of: tick or timer
38 | Both will be put on the wire as a their type topics.
39 | If uType is not tick timer or bar, then "" is returned to signal failure.

40 | 41 |

string zOTLibSimpleFormatRetval(string uType, string uChartId, int iIgnore, string uMark, string uInfo)
42 | uType should be one of: retval
43 | Will be put on the wire as a its type topic.
44 | If uType is not retval, then "" is returned to signal failure.

45 | 46 |

string eOTLibSimpleUnformatCmd(string& aArrayAsList[])

47 | 48 |

Source code: https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4/OTLibSimpleFormatCmd.mq4

49 | 50 |

This file is automatically generated from the source code: do not edit.

51 |
52 | 53 |

Parent: CodeLibraries

54 | 55 | -------------------------------------------------------------------------------- /share/html/OTLibStrings.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OTLib Strings 6 | 7 | 8 | 9 | 10 |

MQL4/Libraries/OTMql4/OTLibStrings.mq4

11 | 12 |

Miscellaneous functions that help handling strings.
13 | This includes Ansi to Unicode "issues".

14 | 15 |

string uAnsi2Unicode(int iStringMemory)

16 | 17 |

void vStringToArray(string uInput, string& uOutput[], string uDelim)

18 | 19 |

string uStringReplace(string uHaystack, string uNeedle, string uReplace)

20 | 21 |

Source code: https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4/OTLibStrings.mq4

22 | 23 |

This file is automatically generated from the source code: do not edit.

24 |
25 | 26 |

Parent: CodeLibraries

27 | 28 | -------------------------------------------------------------------------------- /share/html/OTLibTest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OTLib Test 6 | 7 | 8 | 9 | 10 |

MQL4/Scripts/OTMql4/OTLibTest.mq4

11 | 12 |

A simple test Script that doesn't do much, but it's a start.
13 | Attach it to a chart, select the tests you want to run,
14 | and a MessageBox will pop up to tell you if it passed or failed.
15 | We will put each test as a boolean external input so the user
16 | can select which tests to run.

17 | 18 |

void vAlert(string uText)

19 | 20 |

string eTestStrings()
21 | Test our parsing of strings with vStringToArray

22 | 23 |

string eTestOTLibProcessCmd()

24 | 25 |

void OnStart()

26 | 27 |

void OnDeinit(const int iReason)

28 | 29 |

Source code: https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Scripts/OTMql4/OTLibTest.mq4

30 | 31 |

This file is automatically generated from the source code: do not edit.

32 |
33 | 34 |

Parent: CodeScripts

35 | 36 | -------------------------------------------------------------------------------- /share/html/OTLibTrading.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OTLib Trading 6 | 7 | 8 | 9 | 10 |

MQL4/Libraries/OTMql4/OTLibTrading.mq4

11 | 12 |

int iOTOrderSelect(int iIndex, int iSelect, int iPool=MODE_TRADES)
13 | int slippage, double stoploss, double fTakeprofit,

14 | 15 |

int iOTOrderCloseMarket(int iTicket, int iSlippage=3, color cColor=CLR_NONE)

16 | 17 |

int iOTOrderCloseFull(int iTicket, double fPrice, int iSlippage=3, color cColor=CLR_NONE)

18 | 19 |

int iOTOrderClose(int iTicket, double fLots, double fPrice, int iSlippage, color cColor=CLR_NONE)

20 | 21 |

int iOTSetTradeIsBusy( int iMaxWaitingSeconds = 60 )

22 | 23 |

int iOTSetTradeIsNotBusy()
24 | The function sets the value of the global variable fTradeIsBusy = 0.
25 | If the fTradeIsBusy does not exist, the function creates it.

26 | 27 |

double fOTExposedEcuInMarket(int iOrderEAMagic = 0)

28 | 29 |

bool bOTIsTradeAllowed()

30 | 31 |

int iOTRefreshRates()

32 | 33 |

int iOTMarketInfo(string s, int iMode)

34 | 35 |

double fOTMarketInfo(string s, int iMode)

36 | 37 |

bool bOTContinueOnOrderError(int iTicket)

38 | 39 |

Source code: https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4/OTLibTrading.mq4

40 | 41 |

This file is automatically generated from the source code: do not edit.

42 |
43 | 44 |

Parent: CodeLibraries

45 | 46 | -------------------------------------------------------------------------------- /share/html/TitleIndex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title Index 6 | 7 | 8 | 9 | 10 |

Title Index

11 | 12 | 31 |
32 | 33 |

This file is automatically generated from the source code: do not edit.

34 | 35 | -------------------------------------------------------------------------------- /wiki/CodeLibraries.creole: -------------------------------------------------------------------------------- 1 | === Libraries === 2 | 3 | 4 | See [[MQL4/Libraries/OTMql4/|https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4]] 5 | 6 | 7 | * [[OTLibJsonFormat]] 8 | * [[OTLibLog]] 9 | * [[OTLibMt4ProcessCmd]] 10 | * [[OTLibProcessCmd]] 11 | * [[OTLibServerErrors]] 12 | * [[OTLibSimpleFormatCmd]] 13 | * [[OTLibStrings]] 14 | * [[OTLibTrading]] 15 | 16 | This file is automatically generated from the source code: do not edit. 17 | ---- 18 | Parent: [[Home]] 19 | -------------------------------------------------------------------------------- /wiki/CodeScripts.creole: -------------------------------------------------------------------------------- 1 | === Scripts === 2 | 3 | 4 | See [[MQL4/Scripts/OTMql4/|https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Scripts/OTMql4]] 5 | 6 | 7 | * [[OTLibTest]] 8 | 9 | This file is automatically generated from the source code: do not edit. 10 | ---- 11 | Parent: [[Home]] 12 | -------------------------------------------------------------------------------- /wiki/DevelopmentStyle.creole: -------------------------------------------------------------------------------- 1 | 2 | === Coding Style === 3 | 4 | Metatrader has been a great international success, putting into the 5 | hands of end-users the ability to do programmed trading, something 6 | that was only previously available to large trading houses. It has 7 | been widely adopted, provides a credible platform for Forex trading, 8 | and there are a huge number of "experts" and programs that have been 9 | developed for it. 10 | 11 | However, Metatrader as a language is not without some significant 12 | drawbacks. The language is very rudimentary from the computer science 13 | point of view, and is a closed sole-source product. Very importantly 14 | for writing robust, well-tested and easily maintained code, it lacks 15 | proper error handling flow-of-control constructs, such as are found in 16 | Java, Python or Lisp. This leads to poor quality code, as can be seen 17 | by much of the MQL code in existence, including the code from the 18 | manufacturer, MetaQuotes. The poor nature of the language combines 19 | with the very poor coding practices of the community (e.g. not 20 | checking error codes and no documentation or testing) to create a very 21 | poor programming environment. 22 | 23 | ==== Type Prefixing ==== 24 | 25 | We prefix all variable, function and method names with a lowercase letter 26 | that indicates the type; it helps you anticipate what type a quantity 27 | is, and to make explicit type conversions. This is not a rigid requirement, 28 | but it helps cut down on a very common type of mistake, pun intended. 29 | 30 | If the type changes, give it a new name with the initial letter changed. 31 | In Mql, this scheme has the added advantage of avoiding any naming 32 | conflict with Mql built-ins, or most Python standard library modules. 33 | 34 | Choose the initial letter from the following list: 35 | 36 | || Prefix Letter || Variable Type || 37 | || a || array || 38 | || b || boolean || 39 | || c || complex (unused) || 40 | || d || alist or dictionary || 41 | || e || error string return value, empty for success || 42 | || f || double || 43 | || g || generic - unknown or mutable || 44 | || h || hypertext - HTML/XML entity encoded string || 45 | || i || integer || 46 | || j || json string || 47 | || l || list or tuple (unused) || 48 | || o || instance or pointer to a class || 49 | || r || series || 50 | || s || ASCII string || 51 | || t || date/time value || 52 | || u || Unicode string || 53 | || v || void - return value not to be used || 54 | || z || non-empty string return - empty is a failure || 55 | 56 | * [[DirectoryStructure]] 57 | 58 | ---- 59 | Parent: [[Home]] 60 | -------------------------------------------------------------------------------- /wiki/DirectoryStructure.creole: -------------------------------------------------------------------------------- 1 | 2 | === Directory Structure === 3 | 4 | We adopt a standard directory structure for all projects, so that it 5 | will be obvious what directory things should go in as the projects 6 | progress, and it will make it easier to share code and transfer 7 | knowledge between projects. The directory structure must be complete 8 | so that it will support the final wrapping of the deliverable, 9 | including all documentation. 10 | 11 | The standardized Unix layout works for both MultiPlatformCoding under 12 | both Unix and Windows, and many configuration tools assume its layout. The 13 | layout is the defacto-standard created by the [[http://www.fsf.org/|GNU]] 14 | toolchain. 15 | 16 | In your top project directory you should find: 17 | 18 | * **bin**: binary directory. This will contain executables, for 19 | either the main program, or support tools. For multi-platform work 20 | assume that there may be platform and OS dependent subdirectories 21 | such as 22 | * {{{bin/windows-x86}}}: windows subdirectory 23 | * {{{bin/linux-x86}}}: linux subdirectory 24 | 25 | * **etc**: configuration files - may be empty. 26 | 27 | * **lib**: library directory. This will contain object libraries, for 28 | either the main program, or support tools. For multi-platform work, 29 | assume that there will be platform and OS dependent files under {{{lib}}}. 30 | 31 | * **net**: Repository for files downloaded from the net, for all 32 | bundled prerquisites of code or tools required by the program. It 33 | may also contain the orginal version of code that this project 34 | extends, so that it's easy to compare the preoject with its origins. 35 | Make protocol subdirectories such as {{{net/Http}}} {{{net/Ftp}}} 36 | and in these subdirectories, put the name of the site the package 37 | was downloaded from. 38 | 39 | * **share**: platform independent library directories. For example, 40 | the on-line documentation might go in {{{share/doc}}} or in {{{share/html}}} 41 | and icons might go in {{{share/icons}}} etc. 42 | 43 | * **src**: The source code for the application and any of the tools 44 | it requires. 45 | 46 | * **var**: variable run-time data, initially empty. May have 47 | subdirectories like {{{var/log}}} for log files, 48 | {{{var/cache}}} for runtime files, {{{var/tmp}}} for temporary files etc. 49 | 50 | ---- 51 | Parent: [[DevelopmentStyle]] 52 | -------------------------------------------------------------------------------- /wiki/FrontPage.creole: -------------------------------------------------------------------------------- 1 | OpenTrading Mt4 Library Code 2 | https://github.com/OpenTrading/OTMql4Lib 3 | 4 | The OTMql4Lib aims to provide a high-quality library of code to Metatrader 4, 5 | with testing and documentation, that can serve as a basis to other projects. 6 | It is the common library of Mt4 code to all of the OpenTrading projects: 7 | https://github.com/OpenTrading/ and is required as a prerequisite by OpenTrader 8 | https://github.com/OpenTrading/OpenTrader 9 | 10 | One of the key funtionalities that it provides is the {{{ProcessCmd}}} functions 11 | which is a simple replacement for what should be an {{{Eval}}} command in Mt4, 12 | to allow an Expert to evaluate arbirtary Mt4 commands. This can be used by 13 | any Remote Procedure Call libraries to send commands to Mt4 for evaluation. 14 | 15 | **This is a work in progress - a developers' version.** 16 | 17 | === Installation === 18 | 19 | There is now an installer in the Releases section on github: 20 | see https://github.com/OpenTrading/OTMql4Lib/wiki/Installation 21 | 22 | === Project === 23 | 24 | Please file any bugs in the issues tracker: 25 | https://github.com/OpenTrading/OTMql4Lib/issues 26 | 27 | Use the Wiki to start topics for discussion: 28 | https://github.com/OpenTrading/OTMql4Lib/wiki/Home 29 | It's better to use the wiki for knowledge capture, and then we can pull the 30 | important pages back into the documentation in the {{{share/doc}}} directory. 31 | You will need to be signed into github.com to edit in the wiki. 32 | 33 | * [[Home|https://github.com/OpenTrading/OTMql4Lib/wiki/Home]] 34 | 35 | * [[TitleIndex|https://github.com/OpenTrading/OTMql4Lib/wiki/TitleIndex]] 36 | -------------------------------------------------------------------------------- /wiki/Home.creole: -------------------------------------------------------------------------------- 1 | Welcome to the OTMql4Lib project! 2 | 3 | The OTMql4Lib aims to provide a high-quality library of code to Metatrader 4, 4 | with testing and documentation, that can serve as a basis to other projects. 5 | It is the common library of Mt4 code to all of the OpenTrading projects: 6 | https://github.com/OpenTrading/ and is required as a prerequisite by OpenTrader 7 | https://github.com/OpenTrading/OpenTrader 8 | 9 | One of the key funtionalities that it provides is the {{{ProcessCmd}}} functions 10 | which is a simple replacement for what should be an {{{Eval}}} command in Mt4, 11 | to allow an Expert to evaluate arbirtary Mt4 commands. This can be used by 12 | any Remote Procedure Call libraries to send commands to Mt4 for evaluation. 13 | 14 | === Documentation === 15 | 16 | There is now an installer in the Releases section on github: see 17 | * [[Installation]] 18 | 19 | * [[CodeLibraries]] 20 | * [[CodeScripts]] 21 | 22 | * [[DevelopmentStyle]] 23 | 24 | * [[TitleIndex]] 25 | 26 | === Project === 27 | 28 | Please file any bugs in the issues tracker: 29 | https://github.com/OpenTrading/OTMql4Lib/issues 30 | 31 | Use the Wiki to start topics for discussion: 32 | https://github.com/OpenTrading/OTMql4Lib/wiki 33 | It's better to use the wiki for knowledge capture, and then we can pull 34 | the important pages back into the documentation in the share/doc directory. 35 | You will need to be signed into github.com to see or edit in the wiki. 36 | 37 | -------------------------------------------------------------------------------- /wiki/Installation.creole: -------------------------------------------------------------------------------- 1 | 2 | === Binary Installer === 3 | 4 | There is now an installer in the Releases section on github: 5 | https://github.com/OpenTrading/OTMql4Lib/releases 6 | It's a simple installer that asks where you want the software installed, 7 | and the location of your personal {{{AppData}}} Metatrader directory, 8 | and copies the files to the right places; it installs a copy of the 9 | documentation too. Usually you could just overwrite old releases with 10 | new ones, but for now, we recommend uninstalling old releases before 11 | installing new ones in case the filenames or locations have changed. 12 | 13 | If you have a recent (2016) release of Mt4, the location of your personal 14 | Metatrader directory to install into is no longer the {{{Program Files}}} 15 | directory (something like {{{c:\Program Files\MetaTrader 4 Terminal}}}) 16 | but rather your personal {{{AppData}}} directory (something like 17 | {{{c:\Users\Administrator\AppData\Roaming\MetaQuotes\Terminal\LONGHEXNAME}}}). 18 | 19 | When you start Metatrader, look for the {{{Data Directory:}}} message 20 | in the Journal log. Usually there are 2 possibilities: if you have a 21 | subdirectory of your {{{Users\AppData\Roaming\MetaQuotes\Terminal}}} and 22 | then a long hexadecimal name, use it. Otherwise look in {{{c:\Program Files}}} 23 | for the {{{Metatrader directory}}}. Use the Browse button to select it, 24 | then click Next. 25 | 26 | 27 | === Install from Source === 28 | 29 | Alernatively, you can just "git clone" or download the zip from github.com 30 | and unzip into an empty directory. Then recursively copy the folder 31 | {{{MQL4}}} over the {{{MQL4}}} folder of your personal {{{AppData...}}} directory 32 | (something like 33 | {{{c:\Users\Administrator\AppData\Roaming\MetaQuotes\Terminal\LONGHEXNAME}}}). 34 | It will not overwrite any system files, and keeps its files in subdirectories 35 | called {{{OTMql4}}}. 36 | 37 | ==== New Mt4 Layout ==== 38 | 39 | From the [[Mt4 Files Documentation|https://docs.mql4.com/files]] : 40 | 41 | There are two directories (with subdirectories) in which working files can be located: 42 | 43 | * {{{terminal_data_folder\MQL4\Files}}} (in the terminal menu select to view "File" - "Open the data directory"); 44 | 45 | * the common folder for all the terminals installed on a computer - usually located in the directory {{{C:\Documents and Settings\All Users\Application Data\MetaQuotes\Terminal\Common\Files}}}. 46 | 47 | There is a program method to obtain names of these catalogs using the 48 | {{{TerminalInfoString()}}} function, using the {{{ENUM_TERMINAL_INFO_STRING}}} 49 | enumeration: 50 | | TERMINAL_PATH | Folder from which the terminal is started | string | 51 | | TERMINAL_DATA_PATH | Folder in which terminal data are stored | string | 52 | | TERMINAL_COMMONDATA_PATH | Common path for all of the terminals installed on a computer | string | 53 | 54 | We have chosen to install to the {{{TERMINAL_DATA_PATH}}} to give people the 55 | option of having multiple Mt4 installations, each configured differently. 56 | 57 | The long hex directory name is the md5 hash of the installation directory, then 58 | * convert path to uppercase with no trailing slash 59 | * convert to base64 string using unicode encoding 60 | * MD5 has the result from step 2 61 | See https://forum.mql4.com/60897/page2 62 | -------------------------------------------------------------------------------- /wiki/OTLibJsonFormat.creole: -------------------------------------------------------------------------------- 1 | === MQL4/Libraries/OTMql4/OTLibJsonFormat.mq4 === 2 | 3 | 4 | JSON formatting for sending information to clients. 5 | This is simple string formatting: a JSON structure or class is never used. 6 | 7 | {{{string jOTAccountInformation() }}} 8 | Retrieve the Account information as a JSON structure. 9 | This brings back all of the ususal Account* calls, 10 | with the values formatted as strings, intergers or floats. 11 | 12 | {{{string jOTOrdersTickets() }}} 13 | 14 | {{{string jOTOrdersTrades() }}} 15 | 16 | {{{string jOTOrdersHistory() }}} 17 | 18 | {{{string jOTOrders(int iMode) }}} 19 | 20 | {{{string jOTOrderInformationByTicket(int iTicket) }}} 21 | 22 | {{{string jOTMarketInformation(string uSymbol) }}} 23 | 24 | {{{string jOTTickInformation(string uSymbol, int iTimeFrame) }}} 25 | 26 | {{{string jOTBarInformation(string uSymbol, int iTimeFrame, int iBar) }}} 27 | 28 | {{{string jOTTimerInformation() }}} 29 | 30 | Source code: [[MQL4/Libraries/OTMql4/OTLibJsonFormat.mq4|https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4/OTLibJsonFormat.mq4]] 31 | 32 | 33 | 34 | This file is automatically generated from the source code: do not edit. 35 | ---- 36 | Parent: [[CodeLibraries]] 37 | -------------------------------------------------------------------------------- /wiki/OTLibLog.creole: -------------------------------------------------------------------------------- 1 | === MQL4/Libraries/OTMql4/OTLibLog.mq4 === 2 | 3 | 4 | This will provide our logging functions, but is just a 5 | skeleton for now. See OTLibPyLog for logging with Python. 6 | 7 | {{{void vLogInit() }}} 8 | Initializes the logging environment. This should be called 9 | from your OnInit() function. It is safe to call it a second time; 10 | subsequent calls will just be ignored. 11 | 12 | {{{void vSetLogLevel(int i) }}} 13 | 14 | {{{int iGetLogLevel() }}} 15 | 16 | {{{void vLog(int iLevel, string sMess) }}} 17 | 18 | {{{void vError(string sMess) }}} 19 | 20 | {{{void vWarn(string sMess) }}} 21 | 22 | {{{void vInfo(string sMess) }}} 23 | 24 | {{{void vDebug(string sMess) }}} 25 | 26 | {{{void vTrace(string sMess) }}} 27 | 28 | Source code: [[MQL4/Libraries/OTMql4/OTLibLog.mq4|https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4/OTLibLog.mq4]] 29 | 30 | 31 | 32 | This file is automatically generated from the source code: do not edit. 33 | ---- 34 | Parent: [[CodeLibraries]] 35 | -------------------------------------------------------------------------------- /wiki/OTLibMt4ProcessCmd.creole: -------------------------------------------------------------------------------- 1 | === MQL4/Libraries/OTMql4/OTLibMt4ProcessCmd.mq4 === 2 | 3 | 4 | 5 | {{{string zOTLibMt4ProcessCmd(string uMess) }}} 6 | This is the replacement for what should be Eval in Mt4: 7 | take a string expression and evaluate it. 8 | zMt4LibProcessCmd only handles base Mt4 expressions. 9 | Returns the result of processing the command as a string 10 | in the form "type|value" where type is one of: 11 | string, int, double, bool, datetime, void, json 12 | Returns "error|explanation" if there is an error. 13 | Returns "" if the the command was not recognized; 14 | you can use this fact to process the standard Mt4 commands 15 | with zOTLibMt4ProcessCmd, and if it returns "", 16 | write your own zMyProcessCmd to process your additions. 17 | 18 | {{{string zProcessCmdTer(string uCmd, string uChartId, string uIgnore, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5) }}} 19 | 20 | {{{string zProcessCmdWin(string uCmd, string uChartId, string uIgnore, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5) }}} 21 | 22 | {{{string zProcessCmdAcc(string uCmd, string uChartId, string uIgnore, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5) }}} 23 | 24 | {{{string zProcessCmdGlo(string uCmd, string uChartId, string uIgnore, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5) }}} 25 | 26 | Source code: [[MQL4/Libraries/OTMql4/OTLibMt4ProcessCmd.mq4|https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4/OTLibMt4ProcessCmd.mq4]] 27 | 28 | 29 | 30 | This file is automatically generated from the source code: do not edit. 31 | ---- 32 | Parent: [[CodeLibraries]] 33 | -------------------------------------------------------------------------------- /wiki/OTLibProcessCmd.creole: -------------------------------------------------------------------------------- 1 | === MQL4/Libraries/OTMql4/OTLibProcessCmd.mq4 === 2 | 3 | 4 | This is the replacement for what should be Eval in Mt4: 5 | take a string expression and evaluate it. 6 | We know this is verbose and could be done more compactly, 7 | but it's clean and robust so we'll leave it like this for now. 8 | If you want to extend this for your own functions you have declared in Mql4, 9 | look at how zOTLibProcessCmd calls zMt4LibProcessCmd and then 10 | goes on and handles it if zMt4LibProcessCmd didn't. 11 | 12 | {{{string zOTLibProcessCmd(string uMess) }}} 13 | This is the replacement for what should be Eval in Mt4: 14 | take a string expression and evaluate it. 15 | zMt4LibProcessCmd handles base Mt4 expressions, and 16 | zOTLibProcessCmd also handles base OpenTrading expressions. 17 | Returns the result of processing the command. 18 | Returns "" if there is an error. 19 | 20 | {{{string uProcessCmdi (string uCmd, string uChartId, string uIgnore, string uMark, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5, string uArg6, string uArg7) }}} 21 | 22 | {{{string uProcessCmdOT(string uCmd, string uChartId, string uIgnore, string uMark, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5, string uArg6, string uArg7) }}} 23 | 24 | {{{string uProcessCmdgOT(string uCmd, string uChartId, string uIgnore, string uMark, string uArg1, string uArg2, string uArg3, string uArg4, string uArg5, string uArg6, string uArg7) }}} 25 | 26 | Source code: [[MQL4/Libraries/OTMql4/OTLibProcessCmd.mq4|https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4/OTLibProcessCmd.mq4]] 27 | 28 | 29 | 30 | This file is automatically generated from the source code: do not edit. 31 | ---- 32 | Parent: [[CodeLibraries]] 33 | -------------------------------------------------------------------------------- /wiki/OTLibServerErrors.creole: -------------------------------------------------------------------------------- 1 | === MQL4/Libraries/OTMql4/OTLibServerErrors.mq4 === 2 | 3 | 4 | One of the many fundamental defects of the Mql4 language 5 | is that there is no Object Oriented error handling. 6 | This leads to Mq4 returning hundreds of different errors 7 | that are not grouped so that we can take actions based 8 | on classes of errors. 9 | We try to group the large number of errors into 9 groups 10 | so that we can for example retry a trade when there is 11 | some kind of network error. 12 | 13 | {{{bool bOTLibServerErrorIsContinuable(int iErr) }}} 14 | 15 | {{{bool bOTLibServerErrorType(int iErr) }}} 16 | Group the errors returned from trade server 17 | so that we can take action based on classes of errors. 18 | 19 | Source code: [[MQL4/Libraries/OTMql4/OTLibServerErrors.mq4|https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4/OTLibServerErrors.mq4]] 20 | 21 | 22 | 23 | This file is automatically generated from the source code: do not edit. 24 | ---- 25 | Parent: [[CodeLibraries]] 26 | -------------------------------------------------------------------------------- /wiki/OTLibSimpleFormatCmd.creole: -------------------------------------------------------------------------------- 1 | === MQL4/Libraries/OTMql4/OTLibSimpleFormatCmd.mq4 === 2 | 3 | 4 | This is the replacement for what should be Eval in Mt4: 5 | it takes a string expression and evaluates it. 6 | I know this is verbose and could be done more compactly, 7 | but it's clean and robust so I'll leave it like this for now. 8 | If you want to extend this for your own functions you have declared in Mql4, 9 | look at how OTLibProcessCmd.mq4 calls zMt4LibProcessCmd and then 10 | goes on and handles it if zMt4LibProcessCmd didn't. 11 | 12 | {{{string zOTLibSimpleFormatCmd(string uType, string uChartId, int iIgnore, string uMark, string uCmd) }}} 13 | uType is cmd or exec 14 | Both will be handled by ProcessCmd, but 15 | cmd commands will be put back on the wire as a retval. 16 | If uType is not cmd or exec then "" is returned to signal failure. 17 | 18 | {{{string zOTLibSimpleFormatBar(string uType, string uChartId, int iIgnore, string uMark, string uInfo) }}} 19 | uType should be one of: bar 20 | Both will be put on the wire as a their type topics. 21 | If uType is not tick timer or bar, then "" is returned to signal failure. 22 | 23 | {{{string zOTLibSimpleFormatTimer(string uType, string uChartId, int iIgnore, string uMark, string uInfo) }}} 24 | uType should be one of: tick or timer 25 | Both will be put on the wire as a their type topics. 26 | If uType is not tick timer or bar, then "" is returned to signal failure. 27 | 28 | {{{string zOTLibSimpleFormatTick(string uType, string uChartId, int iIgnore, string uMark, string uInfo) }}} 29 | uType should be one of: tick or timer 30 | Both will be put on the wire as a their type topics. 31 | If uType is not tick timer or bar, then "" is returned to signal failure. 32 | 33 | {{{string zOTLibSimpleFormatRetval(string uType, string uChartId, int iIgnore, string uMark, string uInfo) }}} 34 | uType should be one of: retval 35 | Will be put on the wire as a its type topic. 36 | If uType is not retval, then "" is returned to signal failure. 37 | 38 | {{{string eOTLibSimpleUnformatCmd(string& aArrayAsList[]) }}} 39 | 40 | Source code: [[MQL4/Libraries/OTMql4/OTLibSimpleFormatCmd.mq4|https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4/OTLibSimpleFormatCmd.mq4]] 41 | 42 | 43 | 44 | This file is automatically generated from the source code: do not edit. 45 | ---- 46 | Parent: [[CodeLibraries]] 47 | -------------------------------------------------------------------------------- /wiki/OTLibStrings.creole: -------------------------------------------------------------------------------- 1 | === MQL4/Libraries/OTMql4/OTLibStrings.mq4 === 2 | 3 | 4 | Miscellaneous functions that help handling strings. 5 | This includes Ansi to Unicode "issues". 6 | 7 | {{{string uAnsi2Unicode(int iStringMemory) }}} 8 | 9 | {{{void vStringToArray(string uInput, string& uOutput[], string uDelim) }}} 10 | 11 | {{{string uStringReplace(string uHaystack, string uNeedle, string uReplace) }}} 12 | 13 | Source code: [[MQL4/Libraries/OTMql4/OTLibStrings.mq4|https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4/OTLibStrings.mq4]] 14 | 15 | 16 | 17 | This file is automatically generated from the source code: do not edit. 18 | ---- 19 | Parent: [[CodeLibraries]] 20 | -------------------------------------------------------------------------------- /wiki/OTLibTest.creole: -------------------------------------------------------------------------------- 1 | === MQL4/Scripts/OTMql4/OTLibTest.mq4 === 2 | 3 | 4 | A simple test Script that doesn't do much, but it's a start. 5 | Attach it to a chart, select the tests you want to run, 6 | and a MessageBox will pop up to tell you if it passed or failed. 7 | We will put each test as a boolean external input so the user 8 | can select which tests to run. 9 | 10 | {{{void vAlert(string uText) }}} 11 | 12 | {{{string eTestStrings() }}} 13 | Test our parsing of strings with vStringToArray 14 | 15 | {{{string eTestOTLibProcessCmd() }}} 16 | 17 | {{{void OnStart() }}} 18 | 19 | {{{void OnDeinit(const int iReason) }}} 20 | 21 | Source code: [[MQL4/Scripts/OTMql4/OTLibTest.mq4|https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Scripts/OTMql4/OTLibTest.mq4]] 22 | 23 | 24 | 25 | This file is automatically generated from the source code: do not edit. 26 | ---- 27 | Parent: [[CodeScripts]] 28 | -------------------------------------------------------------------------------- /wiki/OTLibTrading.creole: -------------------------------------------------------------------------------- 1 | === MQL4/Libraries/OTMql4/OTLibTrading.mq4 === 2 | 3 | 4 | 5 | {{{int iOTOrderSelect(int iIndex, int iSelect, int iPool=MODE_TRADES) }}} 6 | int slippage, double stoploss, double fTakeprofit, 7 | 8 | {{{int iOTOrderCloseMarket(int iTicket, int iSlippage=3, color cColor=CLR_NONE) }}} 9 | 10 | {{{int iOTOrderCloseFull(int iTicket, double fPrice, int iSlippage=3, color cColor=CLR_NONE) }}} 11 | 12 | {{{int iOTOrderClose(int iTicket, double fLots, double fPrice, int iSlippage, color cColor=CLR_NONE) }}} 13 | 14 | {{{int iOTSetTradeIsBusy( int iMaxWaitingSeconds = 60 ) }}} 15 | 16 | {{{int iOTSetTradeIsNotBusy() }}} 17 | The function sets the value of the global variable fTradeIsBusy = 0. 18 | If the fTradeIsBusy does not exist, the function creates it. 19 | 20 | {{{double fOTExposedEcuInMarket(int iOrderEAMagic = 0) }}} 21 | 22 | {{{bool bOTIsTradeAllowed() }}} 23 | 24 | {{{int iOTRefreshRates() }}} 25 | 26 | {{{int iOTMarketInfo(string s, int iMode) }}} 27 | 28 | {{{double fOTMarketInfo(string s, int iMode) }}} 29 | 30 | {{{bool bOTContinueOnOrderError(int iTicket) }}} 31 | 32 | Source code: [[MQL4/Libraries/OTMql4/OTLibTrading.mq4|https://github.com/OpenTrading/OTMql4Lib/raw/master/MQL4/Libraries/OTMql4/OTLibTrading.mq4]] 33 | 34 | 35 | 36 | This file is automatically generated from the source code: do not edit. 37 | ---- 38 | Parent: [[CodeLibraries]] 39 | -------------------------------------------------------------------------------- /wiki/TitleIndex.creole: -------------------------------------------------------------------------------- 1 | 2 | == Title Index 3 | 4 | * [[CodeLibraries]] 5 | * [[CodeScripts]] 6 | * [[DevelopmentStyle]] 7 | * [[DirectoryStructure]] 8 | * [[FrontPage]] 9 | * [[Home]] 10 | * [[Installation]] 11 | * [[OTLibJsonFormat]] 12 | * [[OTLibLog]] 13 | * [[OTLibMt4ProcessCmd]] 14 | * [[OTLibProcessCmd]] 15 | * [[OTLibServerErrors]] 16 | * [[OTLibSimpleFormatCmd]] 17 | * [[OTLibStrings]] 18 | * [[OTLibTest]] 19 | * [[OTLibTrading]] 20 | * [[TitleIndex]] 21 | 22 | ---- 23 | This file is automatically generated from the source code: do not edit. 24 | -------------------------------------------------------------------------------- /wiki/_Footer.creole: -------------------------------------------------------------------------------- 1 | [[Home]] 2 | -------------------------------------------------------------------------------- /wiki/_Sidebar.creole: -------------------------------------------------------------------------------- 1 | **Index** 2 | 3 | * [[TitleIndex]] 4 | --------------------------------------------------------------------------------