23/09/22追記
note購入者はDMして下されば続きが読めます!
https://note.com/iceseeds/n/nfdae2c5ac2ef
はじめに
ここでは、GUIで全決済、個別決済を実装します。
前回までの記事を理解しているのが前提です。
[【MQL4 : MT4】GUI で 売買機能を実装した EA を作る。③]
作成手順としては、以下の通りです。
- ComboBoxの作成
- 全決済、個別決済処理
- Event.mqhに処理を追加
※前回とは画面サイズを変えています。
if( !AppWindow.Create( ChartID(), "SampleTitle", 0, 0, 0, 250, 100 ) )
↓↓↓↓
if( !AppWindow.Create( ChartID(), "SampleTitle", 0, 0, 0, 250, 120 ) )
.
※ネーミングセンスはありません。なるだけ分かりやすくしているつもりです!
いろいろと初心者な為、至らない部分もありますが、宜しくお願いします。
フォルダ構造のアドバイスなどを頂けると助かります。
- Experts/
- Sample/
- Plugin/ ←これから機能を追加していくフォルダを作りました。
- ExitCurrency.mqh ←今回のメインファイルです。
- guiwindow.mq4
- AppWindow.mqh
- Event.mqh
- Plugin/ ←これから機能を追加していくフォルダを作りました。
- Sample/
実行結果
All Exitを選択し、Pushすると、仕掛けているポジションを全て決済します。
This Exitを選択し、Pushすると、Pushした通貨のポジションを全て決済します。
( この場合は、USDJPYのポジションを全て決済します )
全決済、個別決済機能
前回までが理解できていれば、GUI部分は簡単です。
AppWindow.mqh
#include <Controls\Dialog.mqh>
#include <Controls\Button.mqh>
#include <Controls\Edit.mqh>
#include <Controls\ComboBox.mqh> // --- 1
class CPanelDialog : public CAppDialog
{
public:
CPanelDialog();
~CPanelDialog();
/* create */
virtual bool Create( const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2 );
/* chart event handler */
virtual bool OnEvent( const int id, const long &lparam, const double &dparam, const string &sparam );
CEdit m_editLots;
CButton m_btnBuy;
CButton m_btnSell;
CButton m_btnUp;
CButton m_btnDown;
CComboBox m_combCreate;
CButton m_btnComb;
protected:
bool CreateEditLots();
bool CreateBtnBuy();
bool CreateBtnSell();
bool CreateBtnUp();
bool CreateBtnDown();
bool CreateCombCreate();
bool CreateBtnComb();
void OnClickBtnUp();
void OnClickBtnDown();
};
EVENT_MAP_BEGIN( CPanelDialog )
ON_EVENT( ON_CLICK, m_btnUp, OnClickBtnUp )
ON_EVENT( ON_CLICK, m_btnDown, OnClickBtnDown )
EVENT_MAP_END( CAppDialog )
CPanelDialog::CPanelDialog(){}
CPanelDialog::~CPanelDialog(){}
bool CPanelDialog::Create( const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2 )
{
if( !CAppDialog::Create( chart, name, subwin, x1, y1, x2, y2 ) )
return false;
if( !CreateEditLots() ) return false;
if( !CreateBtnUp() ) return false;
if( !CreateBtnDown() ) return false;
if( !CreateBtnBuy() ) return false;
if( !CreateBtnSell() ) return false;
if( !CreateCombCreate() ) return false;
if( !CreateBtnComb() ) return false;
return true;
}
bool CPanelDialog::CreateEditLots()
{
int widths = ClientAreaWidth() / 5;
int x1 = widths;
int y1 = 0;
int x2 = widths * 4;
int y2 = 20;
if( !m_editLots.Create( m_chart_id, m_name + "Edit", m_subwin, x1, y1, x2, y2 ) ) return false;
if( !m_editLots.ReadOnly( false ) ) return false;
if( !Add( m_editLots ) ) return false;
m_editLots.TextAlign( ALIGN_CENTER );
m_editLots.Text( "0.10" );
return true;
}
~
中略
~
bool CPanelDialog::CreateCombCreate() // --- 2
{
int widths = ClientAreaWidth() / 5;
int x1 = 0;
int y1 = ClientAreaHeight() - 20;
int x2 = widths * 4;
int y2 = ClientAreaHeight();
if( !m_combCreate.Create( m_chart_id, m_name + "comboCreate", m_subwin, x1, y1, x2, y2 ) ) return false;
m_combCreate.AddItem( "All Exit", 0 );
m_combCreate.AddItem( "This Exit", 1 );
if( !Add( m_combCreate ) ) return false;
return true;
}
bool CPanelDialog::CreateBtnComb()
{
int widths = ClientAreaWidth() / 5;
int x1 = widths * 4;
int y1 = ClientAreaHeight() - 20;
int x2 = ClientAreaWidth();
int y2 = ClientAreaHeight();
if( !m_btnComb.Create( m_chart_id, m_name + "btnComb", m_subwin, x1, y1, x2, y2 ) ) return false;
if( !m_btnComb.Text( "Push" ) ) return false;
if( !Add( m_btnComb ) ) return false;
return true;
}
/* Event Handle */
void CPanelDialog::OnClickBtnUp()
{
m_btnUp.Pressed( false );
string str_editText = m_editLots.Text();
double d_lots = StringToDouble( str_editText );
d_lots += 0.01;
m_editLots.Text( DoubleToStr( d_lots, 2 ) );
}
void CPanelDialog::OnClickBtnDown()
{
m_btnDown.Pressed( false );
string str_editText = m_editLots.Text();
double d_lots = StringToDouble( str_editText );
if( d_lots > 0.01 )
{
d_lots -= 0.01;
m_editLots.Text( DoubleToStr( d_lots, 2 ) );
}
}
AppWindo.mqh の ソースコード詳細
1. [ AppWindow.mqh ] include文
今回は、プルダウンを使うので、ComboBoxをインクルードします。
#include <Controls\ComboBox.mqh>
2. [ AppWindow.mqh ] CreateCombCreate()関数
Createって2回言っとるよ...
AddItemでプルダウンメニューの中身を追加します。
m_combCreate.AddItem( "All Exit", 0 );
m_combCreate.AddItem( "This Exit", 1 );
メンバ変数 . AddItem( 表示文字列, 番号 );
bool CPanelDialog::CreateCombCreate()
{
int widths = ClientAreaWidth() / 5;
int x1 = 0;
int y1 = ClientAreaHeight() - 20;
int x2 = widths * 4;
int y2 = ClientAreaHeight();
if( !m_combCreate.Create( m_chart_id, m_name + "comboCreate", m_subwin, x1, y1, x2, y2 ) ) return false;
m_combCreate.AddItem( "All Exit", 0 );
m_combCreate.AddItem( "This Exit", 1 );
if( !Add( m_combCreate ) ) return false;
return true;
}
ExitCurrency.mqh ( New )
class CExitCurrency
{
public:
bool exit();
bool exit( string str_symbol );
};
bool CExitCurrency::exit() // --- 3
{
if( OrdersTotal() == 0 )
Alert( "not Order" );
else
{
for( int i = OrdersTotal() - 1; i >= 0; i-- )
{
if( !OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) ) continue;
if( !OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), 0 ) ) return false;
Sleep( 10 );
}
}
return true;
}
bool CExitCurrency::exit( string str_symbol ) // --- 4
{
for( int i = OrdersTotal() - 1; i >= 0; i-- )
{
if( !OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) ) continue;
if( OrderSymbol() != str_symbol ) continue;
if( !OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), 0 ) ) return false;
Sleep( 10 );
}
return true;
}
ExitCurrency.mqh の ソースコード詳細
3. [ ExitCurrency.mqh ] exit関数 ( 全決済 )
ポジションがあれば、全決済をします。
bool CExitCurrency::exit() // --- 3
{
if( OrdersTotal() == 0 )
Alert( "not Order" );
else
{
for( int i = OrdersTotal() - 1; i >= 0; i-- )
{
if( !OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) ) continue;
if( !OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), 0 ) ) return false;
Sleep( 10 );
}
}
return true;
}
if( OrdersTotal() == 0 )
OrdersTotal()を使い、ポジションがあるかどうかを判別してます。
for( int i = OrdersTotal() - 1; i >= 0; i-- )
MT4では、いったんポジションが決済されると、
各ポジションに付されたインデックスが再び古いものから順に『0』から振り直されるので、
( ポジション合計数 - 1 ) になります。
なので、新しい → → → 古い と検索します。
if( !OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) ) continue;
OrderSelect関数を使って、エントリー中の注文を選択します。
OrderSelectで選択できなかったら、continue; で戻ります。
if( !OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), 0 ) ) return false;
上記を全てクリアしたら、いよいよ決済です。
OrderClose関数を使用して、決済します。
OrderSelectでポジションを選択済みなので、( チケット、ロット、価格、スリップページ ) を使って決済します。
Sleep( 100 );
OrderCloseは、負荷が掛かるので、0.1秒 休止させます。
※Sleepしないと、次のポジション決済に影響がでる可能性があります。
4. [ ExitCurrency.mqh ] exit関数 ( 個別決済 )
通貨ペアの比較で、個別決済を実装します。
他は、全決済と同じです。
bool CExitCurrency::exit( string str_symbol )
{
for( int i = OrdersTotal() - 1; i >= 0; i-- )
{
if( !OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) ) continue;
if( OrderSymbol() != str_symbol ) continue;
if( !OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), 0 ) ) return false;
Sleep( 10 );
}
return true;
}
bool CExitCurrency::exit( string str_symbol )
引数で、Pushをした通貨ペアを取得します
if( OrderSymbol() != str_symbol ) continue;
全ポジションを比較し、通貨ペアが同じなら、決済します。
Event.mqh
#include "AppWindow.mqh"
#include "Plugin/ExitCurrency.mqh"
CPanelDialog AppWindow;
CExitCurrency ExitCurrency;
class CEvent
{
public:
bool OnEvent( const int id, const long lparam, const double dparam, const string sparam );
private:
bool btnOrder( const int id, const long lparam, const double dparam, const string sparam );
bool Order( int i_type, double d_lots );
bool combSelect( const int id, const long lparam, const double dparam, const string sparam );
};
bool CEvent::OnEvent( const int id, const long lparam, const double dparam, const string sparam )
{
if( !btnOrder( id, lparam, dparam, sparam ) )
Alert( "Error : " + (string)GetLastError() );
if( !combSelect( id, lparam, dparam, sparam ) )
Alert( "Error : " + (string)GetLastError() );
return true;
}
bool CEvent::btnOrder( const int id, const long lparam, const double dparam, const string sparam )
{
if( ( StringFind( sparam, "btnBuy", 4 ) != -1 ) && id == CHARTEVENT_OBJECT_CLICK )
{
if( !Order( 0, (double)AppWindow.m_editLots.Text() ) )
Alert( "Error : " + (string)GetLastError() );
}else if( ( StringFind( sparam, "btnSell", 4 ) != -1 ) && id == CHARTEVENT_OBJECT_CLICK )
{
if( !Order( 1, (double)AppWindow.m_editLots.Text() ) )
Alert( "Error : " + (string)GetLastError() );
}
return true;
}
bool CEvent::Order( int i_type, double d_lots )
{
if( OrderSend( Symbol(), i_type, d_lots, Close[0], 0, 0, 0, "GUISample", 999, 0, clrRed ) == -1 )
return false;
else
Alert( "OrderSend Success!!\n Lots = " + (string)d_lots + "\n type = " + (string)i_type );
return true;
}
bool CEvent::combSelect( const int id, const long lparam, const double dparam, const string sparam )
{
if( ( StringFind( sparam, "btnComb", 4 ) != -1 ) && id == CHARTEVENT_OBJECT_CLICK )
{
switch( (int)AppWindow.m_combCreate.Value() ) // --- 5
{
case 0: // to All Exit
if( !ExitCurrency.exit() )
Alert( "Error : " + (string)GetLastError() );
break;
case 1: // to This Exit
if( !ExitCurrency.exit( Symbol() ) )
Alert( "Error : " + (string)GetLastError() );
break;
default:
Alert( "not select" );
}
}
return true;
}
Event.mqh の ソースコード詳細
5. [ Exit.mqh ] combSelect関数
Pushのボタンを押した際に、ComboBoxの番号を取得します。
switch文で、番号ごとの命令を追加。
bool CEvent::combSelect( const int id, const long lparam, const double dparam, const string sparam )
{
if( ( StringFind( sparam, "btnComb", 4 ) != -1 ) && id == CHARTEVENT_OBJECT_CLICK )
{
switch( (int)AppWindow.m_combCreate.Value() )
{
case 0: // to All Exit
if( !ExitCurrency.exit() )
Alert( "Error : " + (string)GetLastError() );
break;
case 1: // to This Exit
if( !ExitCurrency.exit( Symbol() ) )
Alert( "Error : " + (string)GetLastError() );
break;
default:
Alert( "not select" );
}
}
return true;
}
switch( (int)AppWindow.m_combCreate.Value() )
Editのロットを取得したのと同じ様に、ComboBoxの値を取得します。
AppWindow. メンバ変数 . Value()
if( !ExitCurrency.exit( Symbol() ) )
( case 1 )個別決済だったら、exitの引数に、通貨ペアを渡します。
さいごに
今回は、全決済、個別決済を実装しました。
コードが長そうに見えますが、凄く単純です。
次回は、水平ラインタッチで、決済(ストップ狩りの対処かも?) を実装します。
コードをGithubに up した方がいいのかな。。。
YoutubeでLive配信しながら作ってます。
https://www.youtube.com/channel/UCcTw_iVgpLfrep9f94KxwLg?sub_confirmation=1
チャンネル登録お願いします
Twitterでは毎日呟いています。
https://twitter.com/IceSeed_bz
フォローお願いします
お疲れ様。