まずアラート音を鳴らすにはPlaySound関数を使用します。
PlaySound関数は引数は一つだけでファイル名を指定します。
bool PlaySound(
string filename //ファイル名
);
ここでのファイル名は、MT4インストールフォルダ内のSoundsフォルダのWAVファイルを指定可能です。
もし自分でオリジナルアラート音を追加したい場合はWAVファイルにして、このフォルダに入れる必要があります。WAVファイルの作成ツールはたくさんありますので、そちらを利用します。あまり再生時間が長すぎるととても大きなファイルになるため注意です。
■MT4 Soundsフォルダ
初期ファイルとして、すでにいくつかファイルがあります。alert.wavを鳴らす場合は
PlaySound("alerf.wav");
と指定します。
ちなみに再生中の音を止めるには PlaySound(NULL);と指定するようです。
メールの送信はSendMail関数で行います。
bool SendMail(
string subject, // メールタイトル
string some_text // メール本文
);
この関数は送信先アドレスなどの設定は行えません。
MT4で設定できるため、そちらで設定しておく必要があります。
MT4のメニューからツール→オプションでオプション画面を開き
E-メールタブで編集します。
■E-メール設定
各項目は、使用しているプロパイダから取得できますので、プロパイダの設定手順書などを参考にしてみてください。
Gmailとかも使える様子。なんだか使えないっていう記事も見かけますが。海外のほうではつながったーという記事も多々あるため、古いMT4の問題なんだろうなーと。現状でもつながらない場合は、たぶんGmailのAPPPINとかの問題ではないかなーとか。もし問題になっている人がいるようなら、今度調べて手順を記事にしてみようかな。ローカルにSMTPサーバー立てて中継させるとか面倒なことはせずとも対応可能なはず。
さておき、メールの設定が終わってテストが通っている前提で下記のインジケータを作成しました。
表示中チャートの終値が、表示中時間足ボリンジャーバンドの?σを超えた場合、音を鳴らしてメールを送信するプログラムです。
それぞれ、IsAlertMailとIsAlertSoundをFalseにすることで、機能を停止することができるようにしておきました。
FX-ONにも無料インジケータとして登録しましたので、コンパイルが面倒な方はそちらからダウンロードしてみてください。
余談)
お盆明けにPCが壊れたため、SkylakeなWindows10 PCに入れ替えました。
MT4は問題なく動作しております。
CPU使用率は相変わらず低い感じです。最近CPUとか、もうどうでもいい感じですよね^^;;;CPUパワー不足で困ったことがほとんどない・・。そして、やっぱりSSDサイコー!w
FX-ONブログランキングにご協力よろしくお願いいたしますm(_ _ )m
//------------------------------------------------------------------ // 色が変わるボリンジャーバンド 上位時間足版 アラート機能付き #property copyright "Copyright 2015, Daisuke" #property link "http://mt4program.blogspot.jp/" #property version "1.00" #property strict #property indicator_chart_window //バッファーを指定する。 #property indicator_buffers 10 //プロット数を指定する。 #property indicator_plots 10 #property indicator_label1 "CenterUp" #property indicator_type1 DRAW_LINE #property indicator_color1 clrAqua #property indicator_style1 STYLE_SOLID #property indicator_width1 1 #property indicator_label2 "HIGH1UP" #property indicator_type2 DRAW_LINE #property indicator_color2 clrSlateBlue #property indicator_style2 STYLE_SOLID #property indicator_width2 1 #property indicator_label3 "HIGH2UP" #property indicator_type3 DRAW_LINE #property indicator_color3 clrSlateBlue #property indicator_style3 STYLE_SOLID #property indicator_width3 1 #property indicator_label4 "LOW1UP" #property indicator_type4 DRAW_LINE #property indicator_color4 clrSlateBlue #property indicator_style4 STYLE_SOLID #property indicator_width4 1 #property indicator_label5 "LOW2UP" #property indicator_type5 DRAW_LINE #property indicator_color5 clrSlateBlue #property indicator_style5 STYLE_SOLID #property indicator_width5 1 #property indicator_label6 "CenterDown" #property indicator_type6 DRAW_LINE #property indicator_color6 clrIndianRed #property indicator_style6 STYLE_SOLID #property indicator_width6 1 #property indicator_label7 "HIGH1DOWN" #property indicator_type7 DRAW_LINE #property indicator_color7 clrWheat #property indicator_style7 STYLE_SOLID #property indicator_width7 1 #property indicator_label8 "HIGH2DOWN" #property indicator_type8 DRAW_LINE #property indicator_color8 clrWheat #property indicator_style8 STYLE_SOLID #property indicator_width8 1 #property indicator_label9 "LOW1DOWN" #property indicator_type9 DRAW_LINE #property indicator_color9 clrWheat #property indicator_style9 STYLE_SOLID #property indicator_width9 1 #property indicator_label10 "LOW2DOWN" #property indicator_type10 DRAW_LINE #property indicator_color10 clrWheat #property indicator_style10 STYLE_SOLID #property indicator_width10 1 // 対象タイムフレーム extern ENUM_TIMEFRAMES TargetPeriod = PERIOD_H4; // 入力パラメータ 移動平均期間 extern int MaPeriod = 21; //入力パラメータ 表示移動 extern int MaShift = 0; //入力パラメータ 移動平均種別 extern ENUM_MA_METHOD MaMethod = MODE_EMA; //入力パラメータ 適用価格 extern ENUM_APPLIED_PRICE MaPrice = PRICE_MEDIAN; //標準偏差期間 extern int StdPeriod = 21; //標準偏差算出方法 extern ENUM_MA_METHOD StdMethod = MODE_SMA; //σ1 extern double Sigma1 = 1; //σ2 extern double Sigma2 = 2; //条件に一致した場合、サウンドを鳴らす。 extern bool IsAlertSound = true; //再生サウンド名 extern string SoundFileName = "alert.wav"; //条件に一致した場合、メールを送信する。 extern bool IsAlertMail = true; //終値が次シグマを超えた場合アラートを鳴らす extern double AlertSigma = 1; double centerUp[]; double high1Up[]; double high2Up[]; double low1Up[]; double low2Up[]; double centerDown[]; double high1Down[]; double high2Down[]; double low1Down[]; double low2Down[]; //------------------------------------------------------------------ //初期化 int OnInit() { //インジケーターバッファを初期化する。 SetIndexBuffer(0,centerUp); SetIndexBuffer(1,high1Up); SetIndexBuffer(2,high2Up); SetIndexBuffer(3,low1Up); SetIndexBuffer(4,low2Up); SetIndexBuffer(5,centerDown); SetIndexBuffer(6,high1Down); SetIndexBuffer(7,high2Down); SetIndexBuffer(8,low1Down); SetIndexBuffer(9,low2Down); SetIndexDrawBegin(0, MaPeriod); SetIndexDrawBegin(1, MaPeriod); SetIndexDrawBegin(2, MaPeriod); SetIndexDrawBegin(3, MaPeriod); SetIndexDrawBegin(4, MaPeriod); SetIndexDrawBegin(5, MaPeriod); SetIndexDrawBegin(6, MaPeriod); SetIndexDrawBegin(7, MaPeriod); SetIndexDrawBegin(8, MaPeriod); SetIndexDrawBegin(9, MaPeriod); string short_name = "ClBB(" + IntegerToString(MaPeriod) + ")"; IndicatorShortName(short_name); return(INIT_SUCCEEDED); } //------------------------------------------------------------------ //計算イベント 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[]) //スプレット { if( Period() > TargetPeriod ) return rates_total ; for( int i = (rates_total - prev_calculated - 1); i >= 0 && !IsStopped(); i-- ) { if( i >= rates_total - 2 ) continue; int shift1 = iBarShift(NULL, TargetPeriod, time[i], false); int shift2 = iBarShift(NULL, TargetPeriod, time[i + 1], false); double ma1 = iMA(NULL, TargetPeriod, MaPeriod, 0, MaMethod, MaPrice, shift1); double ma2 = iMA(NULL, TargetPeriod, MaPeriod, 0, MaMethod, MaPrice, shift1 + 1); //ひとつ前の値は、表示している時間足の切り替えが発生したかどうかで変わる。 double minus1Center = shift1 == shift2 ? ma1 : ma2; // 移動平均の方向によって値を設定するバッファーを変更する。 if( ma1 < ma2 ) { centerDown[i] = ma1; centerDown[i + 1] = minus1Center; } else { centerUp[i] = ma1; centerUp[i + 1] = minus1Center; } double std1 = iStdDev(NULL, TargetPeriod, StdPeriod, 0, StdMethod, MaPrice, shift1); double std2 = iStdDev(NULL, TargetPeriod, StdPeriod, 0, StdMethod, MaPrice, shift1 + 1); //ひとつ前の値は、表示している時間足の切り替えが発生したかどうかで変わる。 double minus1Std = shift1 == shift2 ? std1 : std2; // 標準偏差の大きさによって値を入れるバッファを切り替える。 if( std1 < std2 ) { high1Down[i] = ma1 + std1 * Sigma1; high2Down[i] = ma1 + std1 * Sigma2; low1Down[i] = ma1 - std1 * Sigma1; low2Down[i] = ma1 - std1 * Sigma2; high1Down[i + 1] = minus1Center + minus1Std * Sigma1; high2Down[i + 1] = minus1Center + minus1Std * Sigma2; low1Down[i + 1] = minus1Center - minus1Std * Sigma1; low2Down[i + 1] = minus1Center - minus1Std * Sigma2; } else { high1Up[i] = ma1 + std1 * Sigma1; high2Up[i] = ma1 + std1 * Sigma2; low1Up[i] = ma1 - std1 * Sigma1; low2Up[i] = ma1 - std1 * Sigma2; high1Up[i + 1] = minus1Center + minus1Std * Sigma1; high2Up[i + 1] = minus1Center + minus1Std * Sigma2; low1Up[i + 1] = minus1Center - minus1Std * Sigma1; low2Up[i + 1] = minus1Center - minus1Std * Sigma2; } // 最終アラート発生時刻 static datetime lastAlertTime = 0; // 前回がアラートシグマ未満で、今回がアラートシグマ以上なら音をならしてメールを送信する。 // 過去データの計算でアラートが発生するのを防止するため、iが1の時のみ。 if( i == 1 && (IsAlertMail || IsAlertSound ) && lastAlertTime != time[i] ) { double alertStd1 = std1 * AlertSigma; double alertStd2 = minus1Std * AlertSigma; if( (close[i + 1] < (minus1Center + alertStd2) && close[i] >= (ma1 + alertStd1)) || (close[i + 1] > (minus1Center - alertStd2) && close[i] <= (ma1 - alertStd1))) { if( IsAlertSound ) { PlaySound(SoundFileName); } if( IsAlertMail ) { //タイトル string subject = StringFormat("ColorfulMTBB アラート %s[%d] %s", Symbol(), Period(), TimeToStr(time[i]) ); //本文 string message = "ColorfulMTBBの設定によりアラートメールを送信しました。\r\n"; StringAdd(message, StringFormat("MA:%f\r\n", ma1)); StringAdd(message, StringFormat("LowerStd:%f\r\n", ma1 - alertStd1)); StringAdd(message, StringFormat("UpperStd:%f\r\n", ma1 + alertStd1)); StringAdd(message, StringFormat("Close:%f\r\n", close[i])); SendMail(subject, message); } lastAlertTime = time[i]; } } } return(rates_total - 1); }