2015年9月20日日曜日

[MT4インジケータ&プログラミング]状況に応じて色が変わるボリンジャーバンドで音を鳴らしてメールを送る。

上位時間足を表示するカラフルなボリンジャーバンドをさらに改造して、アラート音とメールを出せるようにします。

まずアラート音を鳴らすにはPlaySound関数を使用します。
PlaySound関数は引数は一つだけでファイル名を指定します。
bool PlaySound(
string filename //ファイル名
);

ここでのファイル名は、MT4インストールフォルダ内のSoundsフォルダのWAVファイルを指定可能です。
もし自分でオリジナルアラート音を追加したい場合はWAVファイルにして、このフォルダに入れる必要があります。WAVファイルの作成ツールはたくさんありますので、そちらを利用します。あまり再生時間が長すぎるととても大きなファイルになるため注意です。

■MT4 Soundsフォルダ
Sounds.PNG
初期ファイルとして、すでにいくつかファイルがあります。alert.wavを鳴らす場合は
PlaySound("alerf.wav");
と指定します。
ちなみに再生中の音を止めるには PlaySound(NULL);と指定するようです。


メールの送信はSendMail関数で行います。
bool SendMail(
string subject, // メールタイトル
string some_text // メール本文
);

この関数は送信先アドレスなどの設定は行えません。
MT4で設定できるため、そちらで設定しておく必要があります。
MT4のメニューからツール→オプションでオプション画面を開き
E-メールタブで編集します。

■E-メール設定
EmailSettings.PNG

各項目は、使用しているプロパイダから取得できますので、プロパイダの設定手順書などを参考にしてみてください。
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);
}