目的
MetaTraderで,水平線を引いたとき,現在価格が水平線にタッチしたときアラートを鳴らしたい。
アラートを出す際の考え方
図のようにNOWという現在価格に対して,上の破線や下の破線と同価格になったときに,アラートを出したいと思います。
上の破線は,下から同価格になったときのみに反応し,下の破線はその逆になるようにしたいため,方向性という考え方を持たせています(ソースコード中のdirection)。
また,アラート制御用のボタンとしてラベルを水平線の近くに配置します。
このラベルは,水平線と紐づけするため,水平線の価格をラベルの説明文に付与してタグ付けしておきます。
例としては,
//水平線を探した後は,水平線にラベルがセットされてるか探す。
if(StringFind(ObjectDescription(ownObjName),objName,0) > -1)
といった具合に,ラベルをチェックし,水平線と紐づけされているか見ています。
基本的には
- 水平線を探す
- ラベルが水平線と紐づけされているか調べる
- ラベルがアラートをオンするか調べる
というのを,価格が更新される都度実施しています。
全ソースコード
#property strict
#property indicator_chart_window
input string msg = "目標価格に到達しました!";//価格到達時のメッセージ
string objName = "HLineTouch";
color backGroundDark = clrYellow;
color backGroundWhite = clrDeepSkyBlue;
extern bool debugMode = false;//サポートモード
string dmsg;
color fontColor;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
dmsg = "\r\n" +msg+" :" + "\r\n";
ChartSetInteger(0,CHART_EVENT_OBJECT_CREATE, true);
if(ChartGetInteger(0,CHART_COLOR_BACKGROUND,0) > 800000)
{
fontColor = backGroundWhite;
}
else
{
fontColor = backGroundDark;
}
int objNum = ObjectsTotal();
int i;
if(objNum > 0)
{
//水平線を探す処理
for(i = 0; i < objNum; i++)
{
string ownObjName = ObjectName(i);
if(ObjectType(ownObjName) == OBJ_HLINE)
{
if(debugMode)
Print("object no setsumei :"+ObjectDescription(ownObjName));
//水平線を探した後は,水平線にラベルがセットされてるか探す。
if(StringFind(ObjectDescription(ownObjName),objName,0) > -1)
{
float value = (float)ObjectGetDouble(0, ownObjName, OBJPROP_PRICE,0); //自分の価格を取得
//long dateTime = ObjectGetInteger(0,ownObjName,OBJPROP_TIME,0);
moveLabel(ObjectDescription(ownObjName),value,fontColor);
}
}
}
}
//---
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[])
{
//---
//水平線を探してから,labelを探して,Alert ONを探す
int objNum = ObjectsTotal();
int i;
if(objNum > 0)
{
//水平線を探す処理
for(i = 0; i < objNum; i++)
{
string ownObjName = ObjectName(i);
if(ObjectType(ownObjName) == OBJ_HLINE)
{
//説明欄が空白であることが条件
if(StringFind(ObjectDescription(ownObjName),objName,0)>-1)
{
for(int j = 0; j< objNum; j++)
{
string ownObjName2 = ObjectName(j);
if(ObjectType(ownObjName2) == OBJ_LABEL)
{
if(StringFind(ownObjName2,ObjectDescription(ownObjName),0) > -1)
{
string srcStr = ObjectGetString(0,ownObjName2,OBJPROP_TEXT,0);
double value = ObjectGetDouble(0, ownObjName, OBJPROP_PRICE,0); //自分の価格を取得
moveLabel(ownObjName2,(float)value,fontColor);
if(srcStr == "Alert ON")
{
double nowValue = close[0];
string name[];
int sep_num = StringSplit(ownObjName2,',',name);
int direction = StrToInteger(name[2]);
if(direction * (nowValue - value) <= 0)
{
Alert("Line Touch!!!");
ObjectSetString(0,ownObjName2,OBJPROP_TEXT,"Alert OFF"); // 表示するテキスト
}
}
}
}
}
}
}
}
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
//---
if(ChartGetInteger(0,CHART_COLOR_BACKGROUND,0) > 800000)
{
fontColor = backGroundWhite;
}
else
{
fontColor = backGroundDark;
}
int objNum = ObjectsTotal();
int i;
//新たにオブジェクトが作成された
if(id == CHARTEVENT_OBJECT_CREATE)
{
if(objNum > 0)
{
//水平線を探す処理
for(i = 0; i < objNum; i++)
{
string ownObjName = ObjectName(i);
if(ObjectType(ownObjName) == OBJ_HLINE)
{
//説明欄が空白であることが条件
if(StringFind(ObjectDescription(ownObjName),objName,0)<0)
{
//水平線にフラグをセットしてラベルを立てる。
datetime time = TimeLocal();
float value = (float)ObjectGetDouble(0, ownObjName, OBJPROP_PRICE,0); //自分の価格を取得
string lblName = objName+" "+ TimeToStr(time)+ IntegerToString(TimeSeconds(time)) ;
int selectBar = iBarShift(NULL,PERIOD_CURRENT,iTime(NULL,PERIOD_CURRENT,0),false);
if(debugMode)
Print("時間足制御 バー:"+IntegerToString(selectBar));
double selectClose;
selectClose = iClose(NULL,PERIOD_CURRENT,selectBar);
int q = value < selectClose ? 1:-1;
ObjectSetText(ownObjName,lblName,0,NULL,clrNONE);
lblName = lblName+","+DoubleToStr(selectClose ) +","+IntegerToString(q);
labelCreate(lblName,value,fontColor);
}
}
}
}
}
if(id == CHARTEVENT_OBJECT_CLICK)
{
if(ObjectType(sparam) == OBJ_LABEL)
{
//if(debugMode)
// Print(sparam);
string srcStr = ObjectGetString(0,sparam,OBJPROP_TEXT,0);
//if(debugMode)
// Print(srcStr);
if(srcStr == "Alert OFF")
{
ObjectSetString(0,sparam,OBJPROP_TEXT,"Alert ON"); // 表示するテキスト
}
else
{
ObjectSetString(0,sparam,OBJPROP_TEXT,"Alert OFF"); // 表示するテキスト
}
}
}
if(id == CHARTEVENT_OBJECT_DRAG || id == CHARTEVENT_CHART_CHANGE)
{
if(objNum > 0)
{
//水平線を探す処理
for(i = 0; i < objNum; i++)
{
string ownObjName = ObjectName(i);
if(ObjectType(ownObjName) == OBJ_HLINE)
{
//水平線を探した後は,水平線にラベルがセットされてるか探す。
if(StringFind(ObjectDescription(ownObjName),objName,0) > -1)
{
float value = (float)ObjectGetDouble(0, ownObjName, OBJPROP_PRICE,0); //自分の価格を取得
//long dateTime = ObjectGetInteger(0,ownObjName,OBJPROP_TIME,0);
for(int j = 0; j< objNum; j++)
{
string ownObjName2 = ObjectName(j);
if(ObjectType(ownObjName2) == OBJ_LABEL)
{
if(StringFind(ownObjName2,ObjectDescription(ownObjName),0) > -1)
{
int selectBar = iBarShift(NULL,PERIOD_CURRENT,iTime(NULL,PERIOD_CURRENT,0),false);
if(debugMode)
Print("時間足制御 バー:"+IntegerToString(selectBar));
double selectClose;
selectClose = iClose(NULL,PERIOD_CURRENT,selectBar);
moveLabels(ownObjName2,value,fontColor,(float)selectClose);
//ObjectDescription(ownObjName)っていう名前のラベルがあるはず
}
}
}
}
}
}
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int labelCreate(string myObjName,float value,color col)
{
int x,y;
int chartId = 0;
ChartTimePriceToXY(0,0,TimeCurrent(),value,x,y);
ObjectCreate(0,myObjName, // オブジェクト作成
OBJ_LABEL, // オブジェクトタイプ
0, // サブウインドウ番号
0, // 1番目の時間のアンカーポイント
0 // 1番目の価格のアンカーポイント
);
ObjectSetInteger(chartId,myObjName,OBJPROP_COLOR,col); // 色設定
ObjectSetInteger(chartId,myObjName,OBJPROP_BACK,false); // オブジェクトの背景表示設定
ObjectSetInteger(chartId,myObjName,OBJPROP_SELECTABLE,false); // オブジェクトの選択可否設定
ObjectSetInteger(chartId,myObjName,OBJPROP_SELECTED,false); // オブジェクトの選択状態
ObjectSetInteger(chartId,myObjName,OBJPROP_HIDDEN,true); // オブジェクトリスト表示設定
ObjectSetInteger(chartId,myObjName,OBJPROP_ZORDER,0); // オブジェクトのチャートクリックイベント優先順位
ObjectSetString(chartId,myObjName,OBJPROP_TEXT,"Alert OFF"); // 表示するテキスト
ObjectSetString(chartId,myObjName,OBJPROP_FONT,"MS ゴシック"); // フォント
ObjectSetInteger(chartId,myObjName,OBJPROP_FONTSIZE,14); // フォントサイズ
ObjectSetInteger(chartId,myObjName,OBJPROP_CORNER,CORNER_RIGHT_UPPER); // コーナーアンカー設定
ObjectSetInteger(chartId,myObjName,OBJPROP_XDISTANCE,0); // X座標
ObjectSetInteger(chartId,myObjName,OBJPROP_YDISTANCE,y+14+10); // Y座標
// オブジェクトバインディングのアンカーポイント設定
ObjectSetInteger(chartId,myObjName,OBJPROP_ANCHOR,ANCHOR_RIGHT_LOWER);
return 0;
}
//+------------------------------------------------------------------+
int moveLabel(string myObjName,float value,color col)
{
int x,y;
int chartId = 0;
ChartTimePriceToXY(0,0,TimeCurrent(),value,x,y);
ObjectSetInteger(chartId,myObjName,OBJPROP_COLOR,col); // 色設定
ObjectSetInteger(chartId,myObjName,OBJPROP_YDISTANCE,y+14+5); // Y座標
return 0;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int moveLabels(string myObjName,float value,color col,float myClose)
{
int x,y;
int chartId = 0;
string name[];
int sep_num = StringSplit(myObjName,',',name);
string myNewObjName;
ChartTimePriceToXY(0,0,TimeCurrent(),value,x,y);
string alertStatus = ObjectGetString(chartId,myObjName,OBJPROP_TEXT);
int q = value < myClose ? 1:-1;
myNewObjName = name[0] +","+DoubleToStr(myClose) +","+IntegerToString(q);
ObjectDelete(0,myObjName);
labelCreate(myNewObjName,value,col);
ObjectSetString(chartId,myNewObjName,OBJPROP_TEXT,alertStatus);
return 0;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int moveChangeBackColor(string myObjName)
{
return 0;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
/*
REASON_PROGRAM 0 EAがExpertRemove関数を呼び出して操作を終了しました。
REASON_REMOVE 1 プログラムがチャートから削除されました。
REASON_RECOMPILE 2 プログラムが再コンパイルされました。
REASON_CHARTCHANGE 3 通貨ペアか時間足が変更されました。
REASON_CHARTCLOSE 4 チャートが閉じられました。
REASON_PARAMETERS 5 パラメータがユーザ—によって変更されました。
REASON_ACCOUNT 6 別のアカウントが有効化されるか、アカウントの設定変更によってサーバへの再接続が発生しました。
REASON_TEMPLATE 7 新しいテンプレートが適用されました。
REASON_INITFAILED 8 OnInit関数がゼロ以外の値を返しました。
REASON_CLOSE 9 MT4のターミナルが閉じられた。
*/
if(reason == REASON_REMOVE || reason == REASON_CHARTCLOSE)
{
int objNum = ObjectsTotal();
int i;
if(objNum > 0)
{
//水平線を探す処理
for(i = 0; i < objNum; i++)
{
string ownObjName = ObjectName(i);
if(ObjectType(ownObjName) == OBJ_HLINE)
{
//水平線を探した後は,水平線にラベルがセットされてるか探す。
if(StringFind(ObjectDescription(ownObjName),objName,0) > -1)
{
float value = (float)ObjectGetDouble(0, ownObjName, OBJPROP_PRICE,0); //自分の価格を取得
//long dateTime = ObjectGetInteger(0,ownObjName,OBJPROP_TIME,0);
for(int j = 0; j< objNum; j++)
{
string ownObjName2 = ObjectName(j);
if(ObjectType(ownObjName2) == OBJ_LABEL)
{
if(StringFind(ownObjName2,ObjectDescription(ownObjName),0) > -1)
{
ObjectDelete(0,ownObjName2);
}
}
}
}
}
}
}
}
}
//+------------------------------------------------------------------+
REFERENCEs
なし
さいごに
投資は自己責任!
カレンダー参加者募集してます!
Have a good MQL Life!!!