はじめに
MQL5ソースコードの紹介です。大した事はやってませんが、主に初心者の方の参考になれば幸いです。自分用に書いたものなのでコーディング規約はありません。変数名などに統一性が無く見づらい部分も多々ありますので、予めご了承ください。
機能
過去120日分の日足における最高値と最安値に水平ラインを描画するインジケーターです。描画されたラインはタイムフレームを変更しても同じ値に描画されます。
ソースコード
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
input ENUM_TIMEFRAMES Rate_TimeFrame = PERIOD_D1; //タイムフレーム
input int RatesCount =120; //計算対象となるローソク足の本数
input color HighLineColor =clrHotPink; //最高値ラインの色
input color LowLineColor =clrHotPink; //最安値ラインの色
string HighLineName ="HgihLine"; //チャートに描画する最高値ラインの名称
string LowLineName ="LowLine"; //チャートに描画する最安値ラインの名称
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//最高値ラインの生成
ObjectCreate(0,HighLineName,OBJ_HLINE,0,0,0);
ObjectSetInteger(0,HighLineName,OBJPROP_COLOR,HighLineColor);
//最安値ラインの生成
ObjectCreate(0,LowLineName,OBJ_HLINE,0,0,0);
ObjectSetInteger(0,LowLineName,OBJPROP_COLOR,LowLineColor);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//オブジェクトの削除
ObjectsDeleteAll(0,-1,-1);
}
//+------------------------------------------------------------------+
//| 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[])
{
MqlRates rt[];
if(CopyRates(_Symbol,Rate_TimeFrame,0,RatesCount,rt)!=RatesCount)
{
Print("チャート履歴の取得に失敗しました!");
return(rates_total);
}
double Price_High =0;
double Price_Low =0;
for(int i=0;i<RatesCount;i++)
{
//最高値
if(rt[i].high>Price_High || Price_High==0){Price_High=rt[i].high;}
//最安値
if(rt[i].low<Price_Low || Price_Low==0){Price_Low=rt[i].low;}
}
ObjectMove(0,HighLineName,0,0,NormalizeDouble(Price_High,_Digits));
ObjectMove(0,LowLineName,0,0,NormalizeDouble(Price_Low,_Digits));
return(rates_total);
}
結果
①日足
過去120日における最高値(110.287)と最安値(105.735)にピンク色の水平ラインが引かれます。
②週足
日足で算出した最高値(110.287)と最安値(105.735)に水平ラインが引かれます。
③4時間足
同じく110.287と105.735に水平ラインが引かれます。
ソースコードの説明
- 1~3行目
インジケーターの設定値。お決まり文句みたいなもの。 - 5~8行目
パラメータ。変数の前に「input」を付けることで外部から変更可能なパラメータとなります。変数名の後ろにコメントを付け加えると、変数名の表示がコメントの内容に変わります。
タイムフレーム:プルダウン式で1分~1ヶ月の時間軸が選択できます。
計算対象となるローソク足の本数:タイムフレームで選択した時間軸におけるローソク足の本数が計算対象となります。
最高値ラインの色/最安値ラインの色:ラインの色を変更できるようにしてあります。
- 10~11行目
水平ラインの名称。固定。 - 13~26行目
インジケーターの初回ロード時に実行される処理。最高値と最安値の水平ラインを生成して色を設定しています。 - 27~34行目
インジケーターを削除する時に実行される処理。全てのオブジェクト(ここでは最高値と最安値の水平ライン)を削除します。 - 35~71行目
最高値と最安値を計算する処理。 - 50行目
ローソク足の各値を格納するオブジェクト rt[] を宣言 - 51~55行目
50行目で宣言したrt[]にローソク足のデータを格納します。
Copyratesという関数を使用します。_Symbolは画面に表示されている通貨を表し、Rate_TimeFrameは上記で設定したパラメータ(1 Day)、0はコピーの開始位置、RatesCountも上記で設定したパラメータ(120)、rtはコピー先の配列。
120本分のローソク足のデータを配列にコピーし、コピーに成功したデータが120本分じゃなかったらエラーログを出力する感じです。 - 57~58行目
最高値と最安値を格納する変数。 - 59~65行目
ループ開始(120回)。rtに格納されたローソク足の情報を基に、高値と安値を比較しながらより高い値とより安い値を変数に格納します。 - 67~68行目
求めた最高値と最安値の位置に水平ラインを移動します。
作ろうと思ったきっかけ
自作EAのロジックを検討する際、過去半年間(あるいは過去1年とか1ヶ月とか)でどのくらいの価格変動があったのか?その変動幅は上位足で見た時、半年以上前と比べて大きいのか小さいのか?直近の下位足では変動幅は大きくなっているのか小さくなっているのか?を調べてみたくなり、最初は手動でラインを引いて分析してましたが面倒になったのでインジケーター化しました。
補足
これだけを使った手法のようなものはありませんが、なんらかの理由でMQL5で水平ラインを引く方法をお探しの方の参考になれば幸いです。ヒゲを含まない実体部分だけでの最高値/最安値の水平ラインや任意の時間での垂直ラインの描画方法も別の機会に紹介したいと思います。