ウィザードからカスタムインジケータ用のファイルを作成して、チャート上にスプレッドを表示するプログラムを書いてみます。
今回作成したコードでは、インジケータ削除時にラベルが消えません……
スプレッドの取得
スプレッドの取得と、ラベルテキストの更新はOnCalculate()で行います。
1 | ObjectSetString(0,valueLabelName,OBJPROP_TEXT,double(spread[ArraySize(spread)-1]/10.0)+"pips"); |
スプレッドの取得とラベルテキストの更新をまとめて書いています。ラベルテキストの設定にはObjectSetString()を使います。描画オブジェクトのプロパティを設定するにはObjectSet…()という関数を使って、設定するプロパティと値を指定するようにします。今回の場合はテキストを設定するのでOBJPROP_TEXTを、ラベルテキストにはspread[ArraySize(spread)-1]/10.0)+”pips”としています。
スプレッドはspreadという名前の配列で渡されるのでこれを使います。ArraySetAsSeries()を使えば配列が逆順に変換されますが、今回はしていないので最新のスプレッドは配列の末尾に格納されています。そのため、ArraySize(spread)-1として末尾のインデックスを指定しています。後の/10.0と+”pips”はポイントからpipsへの変換プラスαです。
UIの作成
描画オブジェクトを作成するにはObjectCreate()を使います。
1 | bool ObjectCreate(long chart_id, string name, ENUM_OBJECT type, sub_window, datetime time1, double price1,...) |
最低限必要なのは順に、作成先のチャートID(現在のチャートは0)、描画オブジェクト名、描画オブジェクトの種類、作成先のサブウィンドウ番号(メインチャートの場合は0)、time1、price1は今回は関係ないので0を指定します。
このコードで描画オブジェクトが作成されるので、後はオブジェクトの色やテキストなどのプロパティを設定するだけです。
今回作成したのは、背景用の矩形とライン(OBJ_RECTANGLE_LABEL)とラベル(OBJ_LABEL)です。OBJ_RECTANGLEという描画オブジェクトもありますが、これは時間座標による位置指定なので、チャートの移動によってオブジェクトが動いてしまうため今回のケースでは使いません。またラインの表現はOBJ_RECTANGLE_LABELで高さ1の矩形によって表現しました。
設定したプロパティは次のようになりました。
座標とサイズのプロパティ
座標の指定はOBJPROP_XDISTANCEとOBJPROP_YDISTANCEで行います。また配置の基点を設定するプロパティとしてOBJPROP_CORNERとOBJPROP_ANCHORがあります。OBJPROP_CORNERは座標指定の原点となるチャート上の位置を設定します。つまり、座標の原点がチャートの左上なのか右下なのかということです。OBJPROP_ANCHORはオブジェクト自体の基点となる位置です。背景とラインに関してはANCHOR_CENTERを指定しているのでオブジェクトの中心が基点になります。
OBJ_RECTANGLE_LABELに関しては矩形のサイズを指定しています。幅と高さはそれぞれOBJPROP_XDISTANCEとOBJPROP_YDISTANCEで指定します。
外観のプロパティ
まず背景色と前景色はそれぞれOBJPROP_BGCOLORとOBJ_COLORで指定します。色は色名(clrRedなど)、リテラル(C’255,25,5,255’など)または16進数表現(0xFFFFFFなど)が使えます。
OBJ_RECTANGLE_LABELについてはOBJPROP_BORDER_TYPE、OBJPROP_STYLE、OBJPROP_WIDTH、OBJPROP_FILLというプロパティを指定していますが、順に境界スタイル(フラットとか出っ張ってるとか)、輪郭線の種類、輪郭線の太さと矩形内部を塗りつぶすかどうかを設定しています。
フォント関係
フォント関係は最低限使用するフォント名とサイズを指定しておけば使えるようです。フォント名はOBJPROP_FONTで、フォントサイズはOBJPROP_FONTSIZEで指定します。表示するテキストはOBJPROP_TEXTで指定します。
その他のプロパティ
それ以外のプロパティですが、OBJPROP_SELECTABLEは選択可能かどうか、OBJPROP_HIDDENはオブジェクトリストダイアログに表示するかどうかを設定しています。今回のつくったラベルではユーザーによる操作を禁止したいため、選択を出来ないようにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | // 背景 ObjectCreate(0,backgroundRectName,OBJ_RECTANGLE_LABEL,0,0,0); ObjectSetInteger(0,backgroundRectName,OBJPROP_XDISTANCE,105+5); ObjectSetInteger(0,backgroundRectName,OBJPROP_YDISTANCE,5); ObjectSetInteger(0,backgroundRectName,OBJPROP_XSIZE,100); ObjectSetInteger(0,backgroundRectName,OBJPROP_YSIZE,55); ObjectSetInteger(0,backgroundRectName,OBJPROP_BGCOLOR,C'39,39,214'); ObjectSetInteger(0,backgroundRectName,OBJPROP_BORDER_TYPE,BORDER_FLAT); ObjectSetInteger(0,backgroundRectName,OBJPROP_CORNER,CORNER_RIGHT_UPPER); ObjectSetInteger(0,backgroundRectName,OBJPROP_COLOR,C'0,0,175'); ObjectSetInteger(0,backgroundRectName,OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(0,backgroundRectName,OBJPROP_WIDTH,1); ObjectSetInteger(0,backgroundRectName,OBJPROP_ANCHOR,ANCHOR_CENTER); ObjectSetInteger(0,backgroundRectName,OBJPROP_SELECTABLE,false); ObjectSetInteger(0,backgroundRectName,OBJPROP_HIDDEN,true); ObjectSetInteger(0,backgroundRectName,OBJPROP_FILL,true); // ライン ObjectCreate(0,separaterLine,OBJ_RECTANGLE_LABEL,0,0,0); ObjectSetInteger(0,separaterLine,OBJPROP_XDISTANCE,105); ObjectSetInteger(0,separaterLine,OBJPROP_YDISTANCE,5+27); ObjectSetInteger(0,separaterLine,OBJPROP_XSIZE,90); ObjectSetInteger(0,separaterLine,OBJPROP_YSIZE,1); ObjectSetInteger(0,separaterLine,OBJPROP_BGCOLOR,C'0,0,175'); ObjectSetInteger(0,separaterLine,OBJPROP_BORDER_TYPE,BORDER_RAISED); ObjectSetInteger(0,separaterLine,OBJPROP_CORNER,CORNER_RIGHT_UPPER); ObjectSetInteger(0,separaterLine,OBJPROP_COLOR,C'0,0,175'); ObjectSetInteger(0,separaterLine,OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(0,separaterLine,OBJPROP_WIDTH,1); ObjectSetInteger(0,separaterLine,OBJPROP_ANCHOR,ANCHOR_CENTER); ObjectSetInteger(0,separaterLine,OBJPROP_SELECTABLE,false); ObjectSetInteger(0,separaterLine,OBJPROP_HIDDEN,true); ObjectSetInteger(0,separaterLine,OBJPROP_FILL,true); // タイトル用ラベル ObjectCreate(0,spreadLabelName,OBJ_LABEL,0,0,0); ObjectSetInteger(0,spreadLabelName,OBJPROP_XDISTANCE,60); ObjectSetInteger(0,spreadLabelName,OBJPROP_YDISTANCE,20); ObjectSetInteger(0,spreadLabelName,OBJPROP_CORNER,CORNER_RIGHT_UPPER); ObjectSetString(0,spreadLabelName,OBJPROP_TEXT,"Spread"); ObjectSetString(0,spreadLabelName,OBJPROP_FONT,"Rounded M+ 1c medium"); ObjectSetInteger(0,spreadLabelName,OBJPROP_FONTSIZE,10); ObjectSetInteger(0,spreadLabelName,OBJPROP_ANCHOR,ANCHOR_CENTER); ObjectSetInteger(0,spreadLabelName,OBJPROP_COLOR,clrWhite); ObjectSetInteger(0,spreadLabelName,OBJPROP_BACK,false); ObjectSetInteger(0,spreadLabelName,OBJPROP_SELECTABLE,false); ObjectSetInteger(0,spreadLabelName,OBJPROP_HIDDEN,true); // スプレッドの数値用ラベル ObjectCreate(0,valueLabelName,OBJ_LABEL,0,0,0); ObjectSetInteger(0,valueLabelName,OBJPROP_XDISTANCE,60); ObjectSetInteger(0,valueLabelName,OBJPROP_YDISTANCE,44); ObjectSetInteger(0,valueLabelName,OBJPROP_CORNER,CORNER_RIGHT_UPPER); ObjectSetString(0,valueLabelName,OBJPROP_FONT,"Rounded M+ 1c medium"); ObjectSetInteger(0,valueLabelName,OBJPROP_FONTSIZE,14); ObjectSetInteger(0,valueLabelName,OBJPROP_ANCHOR,ANCHOR_CENTER); ObjectSetInteger(0,valueLabelName,OBJPROP_COLOR,clrWhite); ObjectSetInteger(0,valueLabelName,OBJPROP_BACK,false); ObjectSetInteger(0,valueLabelName,OBJPROP_SELECTABLE,false); ObjectSetInteger(0,valueLabelName,OBJPROP_HIDDEN,true); |
後処理
今回は上手く機能していないのですが、一応オブジェクトを削除するコードはこんな感じになります。
1 | ObjectDeleteAll(0,"sl"); |
第一引数は削除するオブジェクトが存在するチャート番号(0は現在のチャート)ですが、”sl”は削除対象のオブジェクト名のプレフィックスです。なのでslで始まる名前の描画オブジェクトが削除されます。
全コード
今回書いたコードは以下のようになりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | #property version "1.00" #property indicator_chart_window string valueLabelName = "sl_spreadValueLabel"; string spreadLabelName = "sl_spreadLabel"; string backgroundRectName = "sl_backgroundRect"; string separaterLine = "sl_separaterLine"; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping // 背景 ObjectCreate(0,backgroundRectName,OBJ_RECTANGLE_LABEL,0,0,0); ObjectSetInteger(0,backgroundRectName,OBJPROP_XDISTANCE,105+5); ObjectSetInteger(0,backgroundRectName,OBJPROP_YDISTANCE,5); ObjectSetInteger(0,backgroundRectName,OBJPROP_XSIZE,100); ObjectSetInteger(0,backgroundRectName,OBJPROP_YSIZE,55); ObjectSetInteger(0,backgroundRectName,OBJPROP_BGCOLOR,C'39,39,214'); ObjectSetInteger(0,backgroundRectName,OBJPROP_BORDER_TYPE,BORDER_FLAT); ObjectSetInteger(0,backgroundRectName,OBJPROP_CORNER,CORNER_RIGHT_UPPER); ObjectSetInteger(0,backgroundRectName,OBJPROP_COLOR,C'0,0,175'); ObjectSetInteger(0,backgroundRectName,OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(0,backgroundRectName,OBJPROP_WIDTH,1); ObjectSetInteger(0,backgroundRectName,OBJPROP_ANCHOR,ANCHOR_CENTER); ObjectSetInteger(0,backgroundRectName,OBJPROP_SELECTABLE,false); ObjectSetInteger(0,backgroundRectName,OBJPROP_HIDDEN,true); ObjectSetInteger(0,backgroundRectName,OBJPROP_FILL,true); // ライン ObjectCreate(0,separaterLine,OBJ_RECTANGLE_LABEL,0,0,0); ObjectSetInteger(0,separaterLine,OBJPROP_XDISTANCE,105); ObjectSetInteger(0,separaterLine,OBJPROP_YDISTANCE,5+27); ObjectSetInteger(0,separaterLine,OBJPROP_XSIZE,90); ObjectSetInteger(0,separaterLine,OBJPROP_YSIZE,1); ObjectSetInteger(0,separaterLine,OBJPROP_BGCOLOR,C'0,0,175'); ObjectSetInteger(0,separaterLine,OBJPROP_BORDER_TYPE,BORDER_RAISED); ObjectSetInteger(0,separaterLine,OBJPROP_CORNER,CORNER_RIGHT_UPPER); ObjectSetInteger(0,separaterLine,OBJPROP_COLOR,C'0,0,175'); ObjectSetInteger(0,separaterLine,OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(0,separaterLine,OBJPROP_WIDTH,1); ObjectSetInteger(0,separaterLine,OBJPROP_ANCHOR,ANCHOR_CENTER); ObjectSetInteger(0,separaterLine,OBJPROP_SELECTABLE,false); ObjectSetInteger(0,separaterLine,OBJPROP_HIDDEN,true); ObjectSetInteger(0,separaterLine,OBJPROP_FILL,true); // タイトル用ラベル ObjectCreate(0,spreadLabelName,OBJ_LABEL,0,0,0); ObjectSetInteger(0,spreadLabelName,OBJPROP_XDISTANCE,60); ObjectSetInteger(0,spreadLabelName,OBJPROP_YDISTANCE,20); ObjectSetInteger(0,spreadLabelName,OBJPROP_CORNER,CORNER_RIGHT_UPPER); ObjectSetString(0,spreadLabelName,OBJPROP_TEXT,"Spread"); ObjectSetString(0,spreadLabelName,OBJPROP_FONT,"Rounded M+ 1c medium"); ObjectSetInteger(0,spreadLabelName,OBJPROP_FONTSIZE,10); ObjectSetInteger(0,spreadLabelName,OBJPROP_ANCHOR,ANCHOR_CENTER); ObjectSetInteger(0,spreadLabelName,OBJPROP_COLOR,clrWhite); ObjectSetInteger(0,spreadLabelName,OBJPROP_BACK,false); ObjectSetInteger(0,spreadLabelName,OBJPROP_SELECTABLE,false); ObjectSetInteger(0,spreadLabelName,OBJPROP_HIDDEN,true); // スプレッドの数値用ラベル ObjectCreate(0,valueLabelName,OBJ_LABEL,0,0,0); ObjectSetInteger(0,valueLabelName,OBJPROP_XDISTANCE,60); ObjectSetInteger(0,valueLabelName,OBJPROP_YDISTANCE,44); ObjectSetInteger(0,valueLabelName,OBJPROP_CORNER,CORNER_RIGHT_UPPER); ObjectSetString(0,valueLabelName,OBJPROP_FONT,"Rounded M+ 1c medium"); ObjectSetInteger(0,valueLabelName,OBJPROP_FONTSIZE,14); ObjectSetInteger(0,valueLabelName,OBJPROP_ANCHOR,ANCHOR_CENTER); ObjectSetInteger(0,valueLabelName,OBJPROP_COLOR,clrWhite); ObjectSetInteger(0,valueLabelName,OBJPROP_BACK,false); ObjectSetInteger(0,valueLabelName,OBJPROP_SELECTABLE,false); ObjectSetInteger(0,valueLabelName,OBJPROP_HIDDEN,true); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| 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[]) { //--- ObjectSetString(0,valueLabelName,OBJPROP_TEXT,double(spread[ArraySize(spread)-1]/10.0)+"pips"); //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- delete objects ObjectsDeleteAll(0,"sl"); ChartRedraw(); //--- } |