2015年9月28日月曜日

[MT4プログラミング]二つのMA間に雲を描く。オブジェクト版

#2016/02/04 修正 対象タイムフレームをCURRENTにすると表示されない件修正しました。

先週末はiPhone 6Sシリーズの発売日でしたね。
iPhone 6はメモリの足りなさから安定しないアプリがありましたが、6Sは今のところ安定しています。証券会社各社のiOS9対応が遅いところもちらほらありますが、対応終了のタイミングで買い替え検討されてもいいかも。
逆に、現在の動作で不具合がない場合は特に買い替え不要な感じですねー。

先週の続きです。
http://mt4program.blogspot.jp/2015/10/mt4_12.html

さて、先週アップしました、ヒストグラムを使用した雲の描画ですが、この描画チャートの前面に表示されてしまいます。チャートが裏に隠れて見えにくいというコメントをいただきました。

■チャートのプロパティ
chartprop.png
現在表示しているチャート右クリック→プロパティを選択から、全般タグの「チャートを前面に表示」にチェックをつけるとチャートが前に出てきますので、とりあえずの対応は可能です。
��ご指摘いただきましたstaplaさんありがとうございます。
この手法は、MT4標準の一目均衡表なでも有効です。

ただ、これですとMT4で描画するチャート全般に当てはまってしまいますので、今度はライン関係の指標がバーの裏に隠れてしまって見えにくい!という方もいらっしゃるかもしれません。

こーいうときにはオブジェクトによる背景描画が有効です。
早速やってみました。

■オブジェクトによる雲の描画
cloudObject.PNG

デフォルトの設定でもチャートと合成描画されるため、すべての情報が表示できているのがわかるかと思います。

コード的には、今までのオブジェクト描画を基本流用しています。
青赤荒れ狂う! MT4でS/Rオシレータのシグナルを青赤帯でチャートに表示する。その2

今回少しだけ改善点として生成した矩形のダブルクリックでの選択&移動を禁止する処理を追加しました。
ObjectSetInteger(chartId, name, OBJPROP_READONLY, true);
ObjectSetInteger(chartId, name, OBJPROP_SELECTABLE, false);
というコードで選択を禁止しています。


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

//オブジェクト名
#define OBJECT_NAME "CLOUDMA"

//バッファーを指定する。
#property indicator_buffers 2

//プロット数を指定する。
#property indicator_plots   2

#property indicator_label1  "MA1"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

#property indicator_label2  "MA2"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrYellow
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

input ENUM_TIMEFRAMES TargetPeriod = PERIOD_H1;//対象タイムフレーム
input int Ma1Period = 13;//移動平均1期間
input ENUM_MA_METHOD Ma1Method = MODE_SMA;//移動平均1種別
input int Ma2Period = 30;//移動平均2期間
input ENUM_MA_METHOD Ma2Method = MODE_SMA;//移動平均2種別
input int   MaShift = 0;//表示移動
input ENUM_APPLIED_PRICE MaPrice = PRICE_MEDIAN;//適用価格
input color UpColor = clrIndigo;//上昇時カラー
input color DownColor = clrBrown;//下降時カラー

//バッファー
double ma1[];
double ma2[];

//------------------------------------------------------------------
//初期化
int OnInit()
{
   SetIndexBuffer(0,ma1);
   SetIndexBuffer(1,ma2);
   
   int maxPeriod = (int)MathMax(Ma1Period, Ma2Period);
   SetIndexDrawBegin(0, maxPeriod);
   SetIndexDrawBegin(1, maxPeriod);
   
   string short_name = "cloud";
   IndicatorShortName(short_name);
   
   return(INIT_SUCCEEDED);
}

//------------------------------------------------------------------
//終了処理
void OnDeinit(const int reason)
{
   long chartId = ChartID();

   int total = ObjectsTotal(chartId);
   //生成したオブジェクトを削除する。
   //0から削除するとインデックス位置がずれて
   //正しく削除できないため、後ろから削除するようにする。
   for( int i = total - 1; i >= 0 ; i--)
   {
      string name = ObjectName(chartId, i);
      
      // 先頭文字列がOBJECT_NAMEと一致する場合、削除する。
      if( StringFind(name, OBJECT_NAME) == 0 )
      {
         ObjectDelete(chartId, name);
      }
   }
}

//------------------------------------------------------------------
//計算イベント
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( TargetPeriod != PERIOD_CURRENT && Period() > TargetPeriod ) return rates_total ;

   for( int i = (rates_total - prev_calculated - 1); i >= 0 && !IsStopped(); i-- )
   {
      int shift = iBarShift(NULL, TargetPeriod, time[i], false);
      
      ma1[i] = iMA(NULL, TargetPeriod, Ma1Period, MaShift, Ma1Method, MaPrice, shift);
      ma2[i] = iMA(NULL, TargetPeriod, Ma2Period, MaShift, Ma2Method, MaPrice, shift);
      
      datetime startTime = iTime(NULL, TargetPeriod, shift);
      datetime endTime = 0;
      if( i > 0 )
      {
         endTime = iTime(NULL, TargetPeriod, shift - 1);
      }
      else
      {
         endTime = startTime + PeriodSeconds(TargetPeriod);
      }
      
      // 最新値が更新される場合は、オブジェクトを再描画する。
      if( i <= 1 )
      {
         DeleteRectangleObject(startTime);
      }
      // オブジェクトを生成する。
      if( ma1[i] > ma2[i] )
      {
         CreateRectangleObject(ma1[i], ma2[i], startTime, endTime, UpColor);
      }
      else
      {
         CreateRectangleObject(ma2[i], ma1[i], startTime, endTime, DownColor);
      }
      
      
   }
   //元となる値を計算する。
   return(rates_total - 1);
}

//------------------------------------------------------------------
//売買シグナルを矩形で描画する。
bool CreateRectangleObject(
   double top,          //上限価格
   double bottom,       //下限価格
   datetime startTime,  //表示開始時間
   datetime endTime,    //表示終了時間
   color backColor      //背景色
)
{
   //オブジェクトを作成する。
   long chartId = ChartID();
   string name = OBJECT_NAME + TimeToStr(startTime);

   if( ObjectFind(chartId, name) >= 0 ) return true;
   
   if( !ObjectCreate(chartId, name, OBJ_RECTANGLE, 0, startTime, top, endTime, bottom) )
   {
      return false;
   }
   // 背景色を設定する。
   ObjectSetInteger(chartId, name, OBJPROP_COLOR, backColor);
   ObjectSetInteger(chartId, name, OBJPROP_READONLY, true);
   ObjectSetInteger(chartId, name, OBJPROP_SELECTABLE, false);
   return true;
}


//------------------------------------------------------------------
//オブジェクトを削除する。
bool DeleteRectangleObject(
   datetime time        //表示時間(横軸)
)
{
   //オブジェクトを作成する。
   long chartId = ChartID();
   string name = OBJECT_NAME + TimeToStr(time);

   if( ObjectDelete(chartId, name) )
   {
#ifdef DEBUG
      Print("Ojbect Deleted " + name);
#endif
   }
   
   return true;
}