はじめに
ここでは、GUIでストップ狩りを回避するラインを実装します。
GitHubにソースを公開しました。細かい修正は、こちらをご覧下さい。
GitHub : KEG_Qiita_EA
GitHub : KEG_Qiita_EA 差分
前回までの記事を理解しているのが前提です。
【MQL4 : MT4】GUI で ストップ狩りを回避するライン を実装した EA を作る。③
作成手順としては、以下の通りです。
- ComboBoxにライン作成Listを追加
- 2本のライン作成処理
GUIを拡張(横スクロールできる予定)- ライン情報( pips, 損益,
RR)を表示 - 仕掛けに対して、ラインで決済できる処理
- 細かい修正etc...
今回は、6. 細かい修正etc... を実装します。
本当に細かいところは、GitHubにてご確認ください。
※ネーミングセンスはありません。なるだけ分かりやすくしているつもりです!
いろいろと初心者な為、至らない部分もありますが、宜しくお願いします。
フォルダ構造のアドバイスなどを頂けると助かります。
- Experts/
- Sample/
- Common/
- CMD.mqh
- Common.mqh
- Plugin/
- ExitCurrency.mqh
- LineOrder.mqh
- KEG_Order.mq4
- AppWindow.mqh
- Event.mqh
- Common/
- Sample/
実行結果
細かい修正etc...
KEG_Order.mq4
void OnTimer()
{
LineOrder.check();
if( b_check0 )
LineOrder.getLine( str_lineName0 );
else if( AppWindow.m_labelPips0.Text() != "" )
LineOrder.reset( str_lineName0 );
if( b_check1 )
LineOrder.getLine( str_lineName1 );
else if( AppWindow.m_labelPips1.Text() != "" )
LineOrder.reset( str_lineName1 );
LineOrder.exitCheck();
}
KEG_Order.mq4 の ソースコード詳細
毎秒実行するコードを出来るだけ少なくしたつもりです。
ラインの有無をチェックし、
あったら、ラインの情報取得。
ない 且つ Labelに文字があったら、文字を消します。
else if( AppWindow.m_labelPips0.Text() != "" )
Event.mqh
bool CEvent::btnLine( const int id, const long lparam, const double dparam, const string sparam )
{
if( id == 1000 && ( !b_lineCreate0 || !b_lineCreate1 ) ) // 1000ってなに。。。w
{
if( StringFind( sparam, "btnLine0", 4 ) != -1 )
b_lineCreate0 = true;
if( StringFind( sparam, "btnLine1", 4 ) != -1 )
b_lineCreate1 = true;
}
if( id == CHARTEVENT_CLICK )
{
if( b_lineCreate0 )
if( !LineOrder.create( str_lineName0, dparam ) )
CMD.Error( "LineOrder : Create0" );
else
b_lineCreate0 = false;
if( b_lineCreate1 )
if( !LineOrder.create( str_lineName1, dparam ) )
CMD.Error( "LineOrder : Create1" );
else
b_lineCreate1 = false;
}
return true;
}
Event.mqh の ソースコード詳細
if( id == 1000 && ( !b_lineCreate0 || !b_lineCreate1 ) )
onChartEventの id の 1000ってなんの定数?w
恐らく、マウスクリックを離したときだけど、何も見てないから確信がもてない。。。
LineOrder.mqh
#include "../Common/Common.mqh"
class CLineOrder
{
public:
bool check();
bool exitCheck();
bool getLine( string str_lineName );
bool create( string str_name, double d_param );
bool reCreate( string str_name, int i_type );
bool reset( string str_lineName );
private:
bool exit( int i_ticket );
};
~
略
~
bool CLineOrder::reset( string str_lineName ) // --- 1
{
if( str_lineName == str_lineName0 )
{
AppWindow.m_labelPips0.Text( "" );
AppWindow.m_labelProfit0.Text( "" );
}else if( str_lineName == str_lineName1 )
{
AppWindow.m_labelPips1.Text( "" );
AppWindow.m_labelProfit1.Text( "" );
}
return true;
}
bool CLineOrder::create( string str_name, double d_param ) // --- 2
{
int i_sub;
datetime dt_x;
double d_y;
ChartXYToTimePrice( ChartID(), 0, (int)d_param, i_sub, dt_x, d_y );
if( !ObjectCreate( str_name, OBJ_HLINE, 0, Time[0], NormalizeDouble( d_y, Digits() ) ) )
return false;
ObjectSet( str_name, OBJPROP_STYLE, STYLE_DASHDOTDOT );
ObjectSet( str_name, OBJPROP_COLOR, clrRed );
ObjectSet( str_name, OBJPROP_HIDDEN, true );
ObjectSet( str_name, OBJPROP_SELECTED, true );
return true;
}
bool CLineOrder::reCreate( string str_name, int i_type ) // --- 3
{
double d_line = ObjectGet( str_name, OBJPROP_PRICE1 );
ObjectDelete( ChartID(), str_name );
string str_type;
color c_line;
if( i_type == 0 )
{
if( d_line > Close[0] )
{
str_type = "LongProfit";
c_line = clrRoyalBlue;
}else{
str_type = "LongLoss";
c_line = clrDeepPink;
}
}else{
if( d_line < Close[0] )
{
str_type = "SellProfit";
c_line = clrRoyalBlue;
}else{
str_type = "SellLoss";
c_line = clrDeepPink;
}
}
if( !OrderSelect( OrdersTotal() - 1, SELECT_BY_POS, MODE_TRADES ) )
{
return false;
}else{
string str_exName = "KEG_" + Symbol() + "_" + (string)OrderTicket() + "_" + str_type;
if( !ObjectCreate( ChartID(), str_exName, OBJ_HLINE, 0, 0, d_line ) )
return false;
ObjectSet( str_exName, OBJPROP_WIDTH, 2 );
ObjectSet( str_exName, OBJPROP_COLOR, c_line );
ObjectSet( str_exName, OBJPROP_HIDDEN, true );
ObjectSet( str_exName, OBJPROP_SELECTED, true );
}
return true;
}
bool CLineOrder::getLine( string str_lineName ) // --- 4
{
double DigitsValue = MathPow( 10, Digits() - 1 );
double d_line = ObjectGet( str_lineName, OBJPROP_PRICE1 );
double d_pips = ( d_line - Close[0] ) * DigitsValue;
double d_profit = ( d_pips * (double)AppWindow.m_editLots.Text() ) * 1000;
if( str_lineName == str_lineName0 )
{
AppWindow.m_labelPips0.Text( DoubleToString( d_pips, 0 ) + " pips" );
AppWindow.m_labelProfit0.Text( DoubleToString( d_profit, 0 ) + " yen" );
}else if( str_lineName == str_lineName1 )
{
AppWindow.m_labelPips1.Text( DoubleToString( d_pips, 0 ) + " pips" );
AppWindow.m_labelProfit1.Text( DoubleToString( d_profit, 0 ) + " yen" );
}
return true;
}
~
略
~
LineOrder.mqh の ソースコード詳細
1. reset関数
ラインがなかったら、Labelの表示を消します。
bool CLineOrder::reset( string str_lineName )
{
if( str_lineName == str_lineName0 )
{
AppWindow.m_labelPips0.Text( "" );
AppWindow.m_labelProfit0.Text( "" );
}else if( str_lineName == str_lineName1 )
{
AppWindow.m_labelPips1.Text( "" );
AppWindow.m_labelProfit1.Text( "" );
}
return true;
}
2. create関数
bool CLineOrder::create( string str_name, double d_param )
{
int i_sub;
datetime dt_x;
double d_y;
ChartXYToTimePrice( ChartID(), 0, (int)d_param, i_sub, dt_x, d_y );
if( !ObjectCreate( str_name, OBJ_HLINE, 0, Time[0], NormalizeDouble( d_y, Digits() ) ) )
return false;
ObjectSet( str_name, OBJPROP_STYLE, STYLE_DASHDOTDOT );
ObjectSet( str_name, OBJPROP_COLOR, clrRed );
ObjectSet( str_name, OBJPROP_HIDDEN, true );
ObjectSet( str_name, OBJPROP_SELECTED, true );
return true;
}
ラインのレイアウトを見やすく変更しました。
ObjectSet( str_name, OBJPROP_STYLE, STYLE_DASHDOTDOT );
スタイルを、ダッシュDDに。
ObjectSet( str_name, OBJPROP_COLOR, clrRed );
からーを赤に。
ObjectSet( str_name, OBJPROP_HIDDEN, true );
表示中のライン等からの非表示に。
ObjectSet( str_name, OBJPROP_SELECTED, true );
ライン生成時、選択された状態に。
2. reCreate関数
2本のラインを同時に生成しましたが、引数をつかって、一つづつに。
また、色をProfitは、赤。Lossを、青にしました。
bool CLineOrder::reCreate( string str_name, int i_type )
{
double d_line = ObjectGet( str_name, OBJPROP_PRICE1 );
ObjectDelete( ChartID(), str_name );
string str_type;
color c_line;
if( i_type == 0 )
{
if( d_line > Close[0] )
{
str_type = "LongProfit";
c_line = clrRoyalBlue;
}else{
str_type = "LongLoss";
c_line = clrDeepPink;
}
}else{
if( d_line < Close[0] )
{
str_type = "SellProfit";
c_line = clrRoyalBlue;
}else{
str_type = "SellLoss";
c_line = clrDeepPink;
}
}
if( !OrderSelect( OrdersTotal() - 1, SELECT_BY_POS, MODE_TRADES ) )
{
return false;
}else{
string str_exName = "KEG_" + Symbol() + "_" + (string)OrderTicket() + "_" + str_type;
if( !ObjectCreate( ChartID(), str_exName, OBJ_HLINE, 0, 0, d_line ) )
return false;
ObjectSet( str_exName, OBJPROP_WIDTH, 2 );
ObjectSet( str_exName, OBJPROP_COLOR, c_line );
ObjectSet( str_exName, OBJPROP_HIDDEN, true );
ObjectSet( str_exName, OBJPROP_SELECTED, true );
}
return true;
}
2. getLine関数
こちらも、2本のラインを同時に取得しましたが、引数をつかって、一つづつに。
引数の文字列によって、Labelにセットする場所を変えてます。
bool CLineOrder::getLine( string str_lineName )
{
double DigitsValue = MathPow( 10, Digits() - 1 );
double d_line = ObjectGet( str_lineName, OBJPROP_PRICE1 );
double d_pips = ( d_line - Close[0] ) * DigitsValue;
double d_profit = ( d_pips * (double)AppWindow.m_editLots.Text() ) * 1000;
if( str_lineName == str_lineName0 )
{
AppWindow.m_labelPips0.Text( DoubleToString( d_pips, 0 ) + " pips" );
AppWindow.m_labelProfit0.Text( DoubleToString( d_profit, 0 ) + " yen" );
}else if( str_lineName == str_lineName1 )
{
AppWindow.m_labelPips1.Text( DoubleToString( d_pips, 0 ) + " pips" );
AppWindow.m_labelProfit1.Text( DoubleToString( d_profit, 0 ) + " yen" );
}
return true;
}
さいごに
今回は、6. 細かい修正etc... を実装しました。
次回は、Lineタッチで、LineAppにメッセージを送信 を実装する予定です。
今日まで毎日更新をしてきましたが、他に新しい事を始めたので、週1ペースで更新します。
GitHubにソースを公開しました。細かい修正は、こちらをご覧下さい。
2年振りぐらいなので、いろいろと覚えてなかった。。。
GitHub : KEG_Qiita_EA
GitHub : KEG_Qiita_EA 差分
前回のコードは、GitHubにてダウンロードしてください。
当EAを利用し、予期せぬエラーにより利用者が損失した場合、一切責任を持ちません。
YoutubeでLive配信しながら作ってます。
https://www.youtube.com/channel/UCcTw_iVgpLfrep9f94KxwLg?sub_confirmation=1
チャンネル登録お願いします
Twitterでは毎日呟いています。
https://twitter.com/IceSeed_bz
フォローお願いします
お疲れ様。
コメント