[FX] MT5に喋らせる
MT4,MT5には、設定した価格に到達した、売買を行ったなどで、アラート音を出す機能は標準でついてます。
さまざまな音を出すには、インストール先のSounds フォルダ内に好みのwavファイルを入れて、PlaySoundで音を出すこともできます。
しかし、いちいちwavファイルを作成するのは面倒になったので、もう少し柔軟な方法がないか、いろいろネットで調べてみたら、比較的簡単な方法で実現できました。
まあ、ちょっと強引な方法ですが……
参考にしたのは、ここです
https://qiita.com/Pavaux/items/e51ebe991d8a8297a93d
Windowsについている、SAPI.SpVoice を使います。
スクリプトを作成しておいて呼び出す、というものですが、これをそのまま流用して、しゃべらせます。
手順としては、
1.スクリプトファイルを作成する
2.スクリプトを呼び出す
これだけです。
スクリプトはあらかじめ作成してどこかに置いても良いのですが、それも面倒なので、OnInit()内でファイルを作成して置くことにしました
まず、必要なdllをimportします
#import "kernel32.dll"
int CreateFileW(string, uint, int, int, int, int, int);
// int GetFileSize(int, int);
// int ReadFile(int, uchar&[], int, int&[], long);
int WriteFile(int, uchar&[], int, int&[], long);
int CloseHandle(int);
// bool DeleteFileA(string);
// bool GetFileTime(int, ulong&, ulong&, ulong&);
#import
#import "shell32.dll"
int ShellExecuteW(int hwnd,string Operation,string File,string Parameters,string Directory,int ShowCmd);
#import
設定するパラメーターを指定します
input string SoundScriptFileDirectory = "c:\\Temp"; //スクリプトファイルを置く場所
input string Filename = "saysignal.js"; //スクリプトファイル名
input int Language = 411; //言語 411:Japanese 409:English
input double Speed = 0.7; //速度
input int Volume = 20; //音量
input int Gender = 0; //性別 0:male 1:female
次にOninit()内で実行するスクリプトファイルを作成し、
音が出るかテストします
全部まとめたものは以下になります。
//+------------------------------------------------------------------+
//| VoiceTest.mq5 |
//| Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property indicator_chart_window
#import "kernel32.dll"
int CreateFileW(string, uint, int, int, int, int, int);
// int GetFileSize(int, int);
// int ReadFile(int, uchar&[], int, int&[], long);
int WriteFile(int, uchar&[], int, int&[], long);
int CloseHandle(int);
// bool DeleteFileA(string);
// bool GetFileTime(int, ulong&, ulong&, ulong&);
#import
#import "shell32.dll"
int ShellExecuteW(int hwnd,string Operation,string File,string Parameters,string Directory,int ShowCmd);
#import
input string SoundScriptFileDirectory = "c:\\Temp"; //スクリプトファイルを置く場所
input string Filename = "saysignal.js"; //スクリプトファイル名
input int Language = 411; //言語 411:Japanese 409:English
input double Speed = 0.7; //速度
input int Volume = 20; //音量
input int Gender = 0; //性別 0:male 1:female
void OnInit()
{
//......
MakeScriptFile();
if( Language==411 )
VoiceOut("この音量で流れます"); //音が出るかテストする
else
VoiceOut("It plays at this volume");
//......
}
void MakeScriptFile()
{
string MaleFemale;
if( Gender==0 )//&& Language!=411 )
MaleFemale = "Male";
else
MaleFemale = "FeMale";
string commandString = "var args = [];\r\n";
commandString += "for (var i = 0; i < WScript.Arguments.length; i++) {\r\n";
commandString += " args.push(WScript.Arguments.Item(i));\r\n";
commandString += "}\r\n";
commandString += "try {\r\n";
commandString += " var sapi = new ActiveXObject('SAPI.SpVoice');\r\n";
commandString += " sapi.Volume = "+IntegerToString(Volume)+";\r\n";
commandString += " sapi.Rate = "+DoubleToString(Speed,1)+";\r\n";
commandString += " sapi.Voice = sapi.GetVoices(\"Language="+IntegerToString(Language)+"; Gender="+MaleFemale+"\")(0)\r\n";
commandString += " sapi.Speak(args.join(' '));\r\n";
commandString += "} catch (e) {\r\n";
commandString += "// WScript.Echo(\"Error: \" + e.message);\r\n";
commandString += "} finally {\r\n";
commandString += " sapi = null;\r\n";
commandString += " WScript.Sleep(100);\r\n";
commandString += "}\r\n";
string fn = SoundScriptFileDirectory + "\\" + Filename;
int Handle = CreateFileW(fn, 0x40000000 /*GENERIC_WRITE*/, 3 /*SHARE READ|WRITE*/, 0, 2 /*CREATE_ALWAYS*/, 0, 0);
if( Handle>=0 ) {
string writeString = commandString;
uchar buffer[];
int size = StringToCharArray(writeString,buffer,0,-1,0);
int write[1];
WriteFile(Handle,buffer,size-1,write,0);
if( (size-1)!=write[0] )
{
Print("File Write Error ",fn);
CloseHandle(Handle);
return;
}
CloseHandle(Handle);
}
}
void VoiceOut(string s)
{
string command;
command = SoundScriptFileDirectory + "\\" + Filename + " " + s;
ShellExecuteW(0,"open","wscript",command,"",2);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
//---
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
かなり強引です。。
スクリプトの内容は上記のそのままです。
もっとエレガントな方法がないか?と思っていて、
良い方法があれば知りたいです。
スクリプトファイルは、好きな場所においてください。
但しMT5のフォルダ内に置くと動作しません。なぜなのか?理由はわかりません(調べてないです)
Windowsの環境に依るのかもしれませんが、言語や性別によって、しゃべらない組み合わせもあるので、いろいろ試してみてください。
いくつかのPCで試したところ、確実にしゃべるのは日本語(411)、英語(409)の女性(Female)でした。
MT4では、
int WriteFile(int, uchar&[], int, int&[], long);
の最後のlongをintにすれば動作するようです。
int WriteFile(int, uchar&[], int, int&[], int);
プログラミングの専門家ではないので、コードに見苦しいところがあるかと思いますが、ご容赦ください。