Forex Factory
  • Home
  • Forums
  • Trades
  • News
  • Calendar
  • Market
  • Brokers
  • Login
  • User/Email: Password:
  • 8:35am
  • Search
Menu
  • Forums
  • Trades
  • News
  • Calendar
  • Market
  • Brokers
  • Login
  • 8:35am
Search

Options

Search

Bookmark Thread

First Page First Unread Last Page Last Post

Printable Version

Similar Threads

Modify Indicator to run scripts? Please Help 0 replies

Calling Scripts from another file 5 replies

Calling to all Programmers! let's remake this 123 indicator 1 reply

One Indicator calling another indicator in MQL4 3 replies

Calling all Divergence traders; what's your favorite indicator? 5 replies

  • Platform Tech
  • /
  • Reply to Thread
  • Subscribe
  • 5
Attachments: calling scripts from indicator
Exit Attachments

calling scripts from indicator

  • Post #1
  • Quote
  • First Post: Dec 3, 2018 6:53am Dec 3, 2018 6:53am
  •  buju
  • Joined Nov 2009 | Status: Member | 139 Posts
hi there
if anyone reading this has experience with c/c++ coding windows .dll's and could help me out with this:

https://www.mql5.com/en/code/11139

https://www.mql5.com/en/forum/28922#comment_9670539

its a couple years old and probably did work but it aint working now , if some kind dev can make it work it would be awesome .




----------------------

This is script calling library for MT4 build 600 and later.
This library is for callingl scripts from your indicator and expert advisors.
On earlier build of MT4, this can be achieved with this method.
Around build 509, message parameter may have been changed.
wParam is 0x11, and lParam is the ordinal of Navigator tree view, starts from 0 (the top script is 0).
This library includes DLL and a MQL class library.
Source:
Source is hosted on GitHub (CodeBase version might be outdated. Check here for new release).
If you are in trouble:
I'm welcome bug reports on GitHub Issue.
How to use:

  1. Add the following include line to your indicator or expert advisor
    #include <ScriptCaller.class.mqh>
  2. Add the following code to initialize/deinitialize class instance.
    ScriptCaller* g_scriptCaller = NULL; int OnInit() { g_scriptCaller = new ScriptCaller(); return INIT_SUCCEEDED; } void OnDeinit(const int reason) { if (g_scriptCaller) { delete g_scriptCaller; } }
  3. Finally, put the following code to call script!
    g_scriptCaller.callScript("ScriptName"); // Do not end with .mq4
  4. If the script shows input dialog, and you want to close it automatically, call as follows.
    g_scriptCaller.callScript("ScriptName", true);

Shogun manual trading method All Time Return: -68.9%
  • Post #2
  • Quote
  • Dec 3, 2018 7:07am Dec 3, 2018 7:07am
  •  Charlo
  • | Joined Oct 2018 | Status: Member | 4 Posts
Did you change all commands from A to W as it is written in one of the posts:

Replace all PosMessageA with PostMessageW and RegisterWindowMessageA with RegisterWindowMessageW.
This has been so since build 600+, when W (wide) or Unicode form of the functions was introduced.
  • Post #3
  • Quote
  • Dec 3, 2018 2:14pm Dec 3, 2018 2:14pm
  •  buju
  • Joined Nov 2009 | Status: Member | 139 Posts
thanks Charlo
unfortunately Im not familiar with c/c++ , that was never my background in programming , but hey , Im going to see what I can do.
Shogun manual trading method All Time Return: -68.9%
  • Post #4
  • Quote
  • Dec 3, 2018 2:59pm Dec 3, 2018 2:59pm
  •  buju
  • Joined Nov 2009 | Status: Member | 139 Posts
Quoting Charlo
Disliked
Did you change all commands from A to W as it is written in one of the posts: Replace all PosMessageA with PostMessageW and RegisterWindowMessageA with RegisterWindowMessageW. This has been so since build 600+, when W (wide) or Unicode form of the functions was introduced.
Ignored

it is W

void ScriptCaller::callScript(int ordinal)
{
PostMessageW(m_chartWindowHandle, m_mt4InternalMessage, MT4_WPARAM_START_SCRIPT, ordinal);
}

{
m_mt4InternalMessage = RegisterWindowMessageW(MT4_INTERNAL_MESSAGE);
}
Shogun manual trading method All Time Return: -68.9%
  • Post #5
  • Quote
  • Edited at 10:43pm Dec 3, 2018 9:50pm | Edited at 10:43pm
  •  emmzett
  • Joined Apr 2008 | Status: a Foo walks into a Bar... | 139 Posts
Quoting buju
Disliked
...if anyone reading this has experience with c/c++ coding windows .dll's and could help me out with this...
Ignored
The library you mention makes it way too complicated to load a script. There has always been a much more simple and standard way to call any MQL program (script, expert or indicator). With "always" I mean at least since build 225 (July 2009) and with "standard" I mean a way which works for all builds the same. And with "more simple" I mean that you don't need to know script positions in the navigator tree etc. All you need to know is the file name, you can load any MQL program almost like a regular file.

However the libary has one advantage: It has a boolean flag for controling script loading behaviour. If your script needs input parameters and opens the input dialog the library can automatically confirm and close that dialog (but it can't enter values) and thus let the script start immediately. This automatic behaviour has always been tricky and by using it it's possible to make MetaTrader crash or hang. It's not good to rely on software that "automatically clicks on buttons on behalf of the user" (essentially that's what it internally does).

Instead I recommend to load scripts meant for automated execution without the input parameters dialog.
Inserted Code
//#property show_inputs         // no inputs dialog
If the script needs additional input it can read it from elsewhere, e.g. a config file. Or you can pre-configure multiple scripts and load each one for its specific purpose. Both approaches are much more safe and stable.

How to load a script?
Inserted Code
// pseudo code (for documentation only)
 
#define MT4_LOAD_STANDARD_INDICATOR      13
#define MT4_LOAD_CUSTOM_INDICATOR        15
#define MT4_LOAD_EXPERT                  14
#define MT4_LOAD_SCRIPT                  16
 
int hWnd = WindowHandle();
string scriptName = "MyScript";
PostMessage(hWnd, WM_MT4(), MT4_LOAD_SCRIPT, GetStringAddress(scriptName));

This snippet will not work out of the box like that. PostMessage() needs to switch between ANSI and Unicode but the tricky thing is the function GetStringAddress(). Instead of pointing the terminal to navigator tree positions you can directly pass a string buffer with the file name to the terminal API. To get the address of the buffer you need a little DLL which only gives back the address of the buffer.

In my framework on Github I use a much more complex setup as I needed to dynamically pass input parameters to scripts. There I use QuickChannel for passing anything to a script but for this thread it would be overkill. If somebody wants to implement the function GetStringAddress() he may copy the original DLL example distributed by MetaQuotes with MQL4. It already has such a function. Download original MetaQuotes setup build 225: mt4setup.exe. Or one can use the open source MT4 expander DLL from my framework which also has that function: source GetStringAddress() (just ignore all the other stuff).


Otherwise I could setup a tiny example project just for this single function (and maybe add some candy). But I'm quite busy at the moment so it would take me a few days. I would welcome if somebody wants to try by himself.

Any questions? Just ask...

PS: More tricks: The comment "pseudo code" deserves its place. PostMessage() is an asynchronous API. It will immediately return but the message will not yet be processed by the terminal. Instead the message will sit in the Windows message queue and wait (a few microseconds). When it finally is processed by the terminal the user has to make sure that the buffer with the script name still exists and that the address is valid and points to accessible memory. A simple function call in MQL passing a MQL string directly will not do that and leads most probably to a crash.

PPS: Btw, yes you can ignore Unicode in newer terminal builds (600+) and control a new terminal by commands with ANSI strings. It's not the way meant to by MetaQuotes but it's possible. If you want to...
  • Post #6
  • Quote
  • Dec 4, 2018 5:16pm Dec 4, 2018 5:16pm
  •  buju
  • Joined Nov 2009 | Status: Member | 139 Posts
emmzett

thank you for the explanation , but I've used a hot key solution in the end.

- set up a hot key in mt4 on the script , in this case ctrl-M
- used this code to call it:
.....
keybd_event(17, 0x9d, 0, 0); // Ctrl Press
keybd_event(77, 0x9e, 0, 0); // ‘M’ Press
keybd_event(77, 0x9e, KEYEVENTF_KEYUP, 0); // ‘M’ Release
keybd_event(17, 0x9d, KEYEVENTF_KEYUP, 0); // Ctrl Release
Shogun manual trading method All Time Return: -68.9%
  • Post #7
  • Quote
  • Edited at 6:59pm Dec 4, 2018 5:39pm | Edited at 6:59pm
  •  emmzett
  • Joined Apr 2008 | Status: a Foo walks into a Bar... | 139 Posts
Quoting buju
Disliked
emmzett thank you for the explanation , but I've used a hot key solution in the end. - set up a hot key in mt4 on the script , in this case ctrl-M - used this code to call it: ..... keybd_event(17, 0x9d, 0, 0); // Ctrl Press keybd_event(77, 0x9e, 0, 0); // ‘M’ Press keybd_event(77, 0x9e, KEYEVENTF_KEYUP, 0); // ‘M’ Release keybd_event(17, 0x9d, KEYEVENTF_KEYUP, 0); // Ctrl Release
Ignored
Great to hear you got it working. In between I added the launcher functions for any MQL program to my DLL. Attached are two example scripts, an ANSI and a Unicode version. Both essentially do the same.

Once you put the DLL in the library folder you can use the functions from anywhere you like and load programmatically scripts, experts or indicators. The source code for the launcher functions is here:

LoadMqlProgramA(int hChart, int programType, string programName)

and here:

LoadMqlProgramW(int hChart, int programType, string programName)

The attached DLL is the full original library, just ignore all the other stuff. Tested with all builds. Of course ANSI scripts work in current terminal versions and can launch Unicode programs, and the other way around works too. If somebody tries it, please let me know if something is not working as epxected. I guess there may be localization issues with non-latin characters.

PS: As a side effect one can see what happens when a new script is launched on a chart where another script is already running (in this case the launcher script itself). The terminal asks if you want to stop the former and start the other. Of course this only happens when you start a script with a script, as there can be always at most one script running on a chart at the same time.
Attached Files
File Type: mq4 TestScript-Unicode.mq4   < 1 KB | 51 downloads
File Type: ex4 TestScript-Unicode.ex4   5 KB | 44 downloads
File Type: mq4 TestScript-Ansi.mq4   < 1 KB | 53 downloads
File Type: ex4 TestScript-Ansi.ex4   1 KB | 44 downloads
File Type: zip MQL-ProgramLauncher.zip   75 KB | 54 downloads
1
  • Post #8
  • Quote
  • Dec 4, 2018 5:46pm Dec 4, 2018 5:46pm
  •  buju
  • Joined Nov 2009 | Status: Member | 139 Posts
ideally my vision was to pass inputs to the script and the script would automatically execute, my implementation does not do this , I have thought of a workaround , and that is for the script to read global variables , but that could be problematic if the GV's are not updated or outdated.
Shogun manual trading method All Time Return: -68.9%
  • Post #9
  • Quote
  • Dec 4, 2018 6:57pm Dec 4, 2018 6:57pm
  •  emmzett
  • Joined Apr 2008 | Status: a Foo walks into a Bar... | 139 Posts
Quoting buju
Disliked
ideally my vision was to pass inputs to the script and the script would automatically execute, my implementation does not do this , I have thought of a workaround , and that is for the script to read global variables , but that could be problematic if the GV's are not updated or outdated.
Ignored
For your case imho the most simple, stable and reliable solution are plain old .ini files which you can read/write with the Win32 api. Windows will take care of race conditions (you don't need to worry about locking issues or concurrent modifications) and you can pass the basic data types string, int and double. Global terminal variables are cumbersome to handle and limited, they are not reliable and you only have doubles at your disposal. With .ini files you can do whatever you want. I definitely would recommend to go that way.
  • Post #10
  • Quote
  • Dec 5, 2018 2:47am Dec 5, 2018 2:47am
  •  buju
  • Joined Nov 2009 | Status: Member | 139 Posts
maybe im crazy , but I sometimes 'code' stuff in my head , and last night as i was falling asleep i 'coded' what i would need to do using just 1 global variable in order to make the script 'automatic'. i would just have to have the checks in place to make sure the gv is always up to date.
Shogun manual trading method All Time Return: -68.9%
  • Post #11
  • Quote
  • Edited at 1:08pm Dec 5, 2018 12:52pm | Edited at 1:08pm
  •  Nicholishen
  • Joined Jul 2005 | Status: zzzzzzzzzzzzzzzzzzzzzzzzz zzzzzzzzzz | 1,223 Posts
Quoting buju
Disliked
ideally my vision was to pass inputs to the script and the script would automatically execute, my implementation does not do this , I have thought of a workaround , and that is for the script to read global variables , but that could be problematic if the GV's are not updated or outdated.
Ignored
Using winapi and dlls to pass messages is too much work. Instead take advantage of custom chart events... and instead of running a script you can make an EA "worker" that will listen for custom chart events, perform an action, and return a response. Here's a generic example:

Indicator:
Inserted Code
/* INDICATOR "manager" */
#property strict
#property indicator_chart_window
#define     EVENT_REQ_SAY_HELLO  3
#define     EVENT_RESP_SAY_HELLO 4
#define     XEVENT(EVENT) (CHARTEVENT_CUSTOM+EVENT)
ulong g_micro_timer = 0;
int OnInit()
{  
   Comment("WORKER_EXAMPLE_IND click chart for test");
   return(INIT_SUCCEEDED);
}
int start(){return 0;}
 
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
   /*Simple example:
      1. User clicks chart
      2. Indicator sends mssg to worker
      3. Worker sends response.
      4. Indicator receives response
      5. Alerts user with worker response mssg
   */
   if(id == CHARTEVENT_CLICK) {
      for(long c=ChartFirst(); c>=0; c=ChartNext(c))
         EventChartCustom(c, EVENT_REQ_SAY_HELLO, ChartID(), 0.0, "");
      g_micro_timer = GetMicrosecondCount();
      return;
   }
   if(id == XEVENT(EVENT_RESP_SAY_HELLO)) {
      ulong round_trip_time = GetMicrosecondCount() - g_micro_timer;
      Alert(StringFormat("Mssg('%s') | round trip micros: %d",
         sparam, round_trip_time
      ));
   }
}

Expert: "Worker"

Inserted Code
/* EXPERT "Worker" */
#property   strict
#define     EVENT_REQ_SAY_HELLO  3
#define     EVENT_RESP_SAY_HELLO 4
#define     XEVENT(EVENT) (CHARTEVENT_CUSTOM+EVENT)
int OnInit()
{  
   Comment("WORKER_EXAMPLE_EXPERT");
   return(INIT_SUCCEEDED);
}
void OnTick(){}
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
   if(id == XEVENT(EVENT_REQ_SAY_HELLO)) {//incoming event is custom user event
      EventChartCustom(                   //sending custom response via chart events
         lparam,                          //targeting the chart id that was sent in the lparam from request
         EVENT_RESP_SAY_HELLO,            //setting the event id for the receiving program
         ChartID(),                       //sending this chart id in the lparam
         0.0,                             //nothing to send in the dparam, but this could be anything
         say_hello()                      //sending string response, this has a limit in chars so large messages should be passed via file refs
      );
   }
}
//+------------------------------------------------------------------+
string say_hello()
{
   return "Hello from worker EA! :)";
}
2
  • Post #12
  • Quote
  • Dec 5, 2018 2:21pm Dec 5, 2018 2:21pm
  •  robots4me
  • | Joined Dec 2017 | Status: Member | 192 Posts
Quoting Nicholishen
Disliked
Instead take advantage of custom chart events...
Ignored
Holy smokes -- are you saying you can use custom events to communicate between charts -- sort of like WM_COPY messages (if you are familiar with old Win32 programming)? That is way too cool. Thank you, Nicholishen.
1
  • Post #13
  • Quote
  • Edited at 2:19am Dec 6, 2018 1:37am | Edited at 2:19am
  •  Nicholishen
  • Joined Jul 2005 | Status: zzzzzzzzzzzzzzzzzzzzzzzzz zzzzzzzzzz | 1,223 Posts
Quoting robots4me
Disliked
{quote} Holy smokes -- are you saying you can use custom events to communicate between charts -- sort of like WM_COPY messages (if you are familiar with old Win32 programming)? That is way too cool. Thank you, Nicholishen.
Ignored
You can also run workers to place up to 8 concurrent asynchronous trade actions before you run into the trade context busy error (limit)
1
  • Post #14
  • Quote
  • Dec 6, 2018 3:12am Dec 6, 2018 3:12am
  •  robots4me
  • | Joined Dec 2017 | Status: Member | 192 Posts
Quoting Nicholishen
Disliked
You can also run workers to place up to 8 concurrent asynchronous trade actions before you run into the trade context busy error (limit)
Ignored
Very interesting and helpful to know. This gives me some new ideas. Thanks...
  • Post #15
  • Quote
  • Dec 28, 2018 8:43pm Dec 28, 2018 8:43pm
  •  robots4me
  • | Joined Dec 2017 | Status: Member | 192 Posts
Quoting emmzett
Disliked
Great to hear you got it working. In between I added the launcher functions for any MQL program to my DLL.
Ignored
@emmzett -- this afternoon I had a need to launch a script from the command line and also from an EA. At first I tried ScriptCaller and, like others, couldn't get it to work. Then I rediscovered this thread and saw your solution for launching MQL programs. It works great.

I run a portfolio of EAs and like to recalibrate settings every couple of weeks. I use a wonderful script from Ovo called LoadAllHistory -- which downloads the latest data from my broker. I'm usually trading 9 pairs and, so, I need to do this 9 times. But now, I can call a Windows command file to (a) launch a terminal.exe, (b) download the latest history for 9 pairs, (c) convert these to their corresponding *.csv files, (d) copy the *.csv files to the data folder used by Forex Strategy Builder. I then run FSB's optimizer on all the EAs to recalibrate their settings.

Being able to automate most of this using your program launcher saves me a lot of time -- which, in turn, encourages me to re-calibrate more often.

Thanks very much -- your program launcher is a wonderful tool.
  • Post #16
  • Quote
  • Last Post: Dec 28, 2018 9:22pm Dec 28, 2018 9:22pm
  •  emmzett
  • Joined Apr 2008 | Status: a Foo walks into a Bar... | 139 Posts
Quoting robots4me
Disliked
{quote} ...Thanks very much -- your program launcher is a wonderful tool.
Ignored
I'm glad finally somebody can make use of it.
Thread Tools Search this Thread
Show Printable Version Show Printable Version
Email This Thread Email This Thread
Search this Thread:

Advanced Search

  • Platform Tech
  • /
  • calling scripts from indicator
  • Reply to Thread
0 traders viewing now
Top of Page
  • Facebook
  • Twitter
FF Website
  • Homepage
  • Search
  • Members
  • User Guide
  • Report a Bug
FF Products
  • Forums
  • Trades
  • Calendar
  • News
  • Market
  • Brokers
  • Trade Explorer
About FF
  • Mission
  • Products
  • Media Kit
  • Blog
  • Contact
Follow FF
  • Facebook
  • Twitter

Other Markets:

  • Crypto Craft
  • Energy EXCH
  • Metals Mine

Forex Factory® is a brand of Fair Economy, Inc.

Terms of Service / ©2019