以降のEA関係の記事は、このファイルがInclude/Customフォルダの下にTradingWrapper.mqhというファイル名で保存されている前提です。
//------------------------------------------------------------------ // 注文関係ラッパークラス #property copyright "Copyright 2015, Daisuke" #property link "http://mt4program.blogspot.jp/" #property version "1.10" #property strict #include#include #include //------------------------------------------------------------------ // 注文関係ラッパークラス class CTradingWrapper { private: // マジックナンバー int m_magicNumber; // 最大ポジション数 int m_maxPosition; // Pips倍率 int m_pipsRate; // 対象通貨ペア string m_symbol; // 保有ポジション CArrayInt m_positions ; // タイムアウト値 uint m_timeout; // 少数桁数 int m_digit; public: //------------------------------------------------------------------ // コンストラクタ CTradingWrapper( string symbol, //対象通貨ペア int magicNumber, //マジックナンバー int maxPosition, //最大ポジション数 uint timeout //タイムアウト ); //------------------------------------------------------------------ // デストラクタ ~CTradingWrapper(); //------------------------------------------------------------------ // 発注する // Return 発注成功時インデックス それ以外-1 int SendOrder( int cmd, //売買種別 double volume, //売買ロット double price, //価格 uint slippage, //許容スリッピング(Pips単位) uint stoploss, //ストップロス(Pips単位) uint takeprofit, //利確値(Pips単位) string comment, //コメント datetime expiration, //注文有効期限 color arrowColor //注文矢印の色 ); //------------------------------------------------------------------ // 成行き決済を行う。 // Return 発注成功時ture それ以外false bool CloseOrder( int index, //決済するインデックス uint slippage, //許容スリッピング color arrowColor = clrNONE //注文矢印の色 ); //------------------------------------------------------------------ // 全ポジションを成行き決済を行う。 // Return 発注成功時ture それ以外false bool CloseOrderAll( uint slippage, //許容スリッピング color arrowColor = clrNONE //注文矢印の色 ); //------------------------------------------------------------------ // 注文を変更する。 // Return 発注成功時ture それ以外false bool ModifyOrder( int index, //決済するインデックス double price, //価格 uint stoploss, //ストップロス(Pips単位) uint takeprofit, //利確値(Pips単位) datetime expiration, //注文有効期限 color arrowColor //注文矢印の色 ); //------------------------------------------------------------------ // すべての注文を変更する。 bool ModifyOrderAll( double price, //価格 uint stoploss, //ストップロス(Pips単位) uint takeprofit, //利確値(Pips単位) datetime expiration, //注文有効期限 color arrowColor //注文矢印の色 ); //------------------------------------------------------------------ // 注文を変更する。 // Return 発注成功時ture それ以外false bool ModifyOrder( int index, //決済するインデックス uint stoploss, //ストップロス(Pips単位) uint takeprofit, //利確値(Pips単位) color arrowColor //注文矢印の色 ); //------------------------------------------------------------------ // すべての注文を変更する。 bool ModifyOrderAll( uint stoploss, //ストップロス(Pips単位) uint takeprofit, //利確値(Pips単位) color arrowColor //注文矢印の色 ); //------------------------------------------------------------------ // 現在のポジション数を取得する。 // Return 現在のポジション数を取得する。 int GetPositionCount(){ return m_positions.Total(); }; //------------------------------------------------------------------ // 最大のポジション数を取得する。 // Return 最大のポジション数を取得する。 int GetMaxPosition() { return m_maxPosition; } ; //------------------------------------------------------------------ // 1pipsあたりの値を取得する。 // Return 1pipあたりの値 double GetPipsValue() { return Point() * m_pipsRate; } ; //------------------------------------------------------------------ // ポジションリストを更新する。 void RefreshPositions(); private: //------------------------------------------------------------------ // 設定パラメータが安全かどうか // Return 安全ture それ以外false bool IsSafeParameter(); }; //------------------------------------------------------------------ // コンストラクタ CTradingWrapper::CTradingWrapper( string symbol, //対象通貨ペア int magicNumber = 0, //マジックナンバー int maxPosition = 3, //最大ポジション数 uint timeout = 1000 //タイムアウト(ms) ) { m_symbol = symbol; m_magicNumber = magicNumber; m_maxPosition = maxPosition; m_timeout = timeout; m_positions.Resize(m_maxPosition); //Pips計算 小数点桁数が3or5の場合、Point()*10=1pips m_digit = (int)MarketInfo(m_symbol, MODE_DIGITS); m_pipsRate = m_digit == 3 || m_digit == 5 ? 10 : 1; for( int i = 0 ; i < OrdersTotal(); i++) { if( OrderSelect(i, SELECT_BY_POS) ) { if( OrderMagicNumber() == m_magicNumber && OrderSymbol() == m_symbol) { m_positions.Add(OrderTicket()); } } } } //------------------------------------------------------------------ // デストラクタ CTradingWrapper::~CTradingWrapper() { } //------------------------------------------------------------------ // 発注する // Return 発注成功時インデックス それ以外-1 int CTradingWrapper::SendOrder( int cmd, //売買種別 double volume, //売買ロット double price, //価格(成行き時は現在値を自動設定) uint slippage, //許容スリッピング(Pips単位) uint stoploss = 0, //ストップロス(Pips単位) uint takeprofit = 0, //利確値(Pips単位) string comment = NULL, //コメント datetime expiration = 0, //注文有効期限 color arrowColor = clrNONE //注文矢印の色 ) { if( !this.IsSafeParameter() ) return -1; if( m_positions.Total() >= m_positions.Max() ) return -1 ; // 計算用 負数フラグ int flag = cmd == OP_BUY || cmd == OP_BUYLIMIT || cmd == OP_BUYSTOP ? 1 : -1; uint start = GetTickCount(); while(true) { if( (GetTickCount() - start ) > m_timeout ) return -1; double bid = MarketInfo(m_symbol, MODE_BID); double ask = MarketInfo(m_symbol, MODE_ASK); if( cmd == OP_SELL ) price = bid; if( cmd == OP_BUY ) price = ask; double closeTarget = cmd == OP_BUY || cmd == OP_BUYLIMIT || cmd == OP_BUYSTOP ? bid : ask; //pips値からストップロス値、利益確定値を取得する。 double stoplossValue = 0 ; double takeprofitValue = 0; if( stoploss != 0 ) { stoplossValue = NormalizeDouble(closeTarget - this.GetPipsValue() * stoploss * flag, m_digit ); } if( takeprofit != 0) { takeprofitValue = NormalizeDouble(closeTarget + this.GetPipsValue() * takeprofit * flag, m_digit ); } if( IsTradeAllowed() ) { if( AccountFreeMarginCheck(m_symbol, cmd, volume) < 0 ) { return -1; } int tiket = ::OrderSend(m_symbol, cmd, volume, price, slippage * m_pipsRate, stoplossValue, takeprofitValue, comment, m_magicNumber, expiration, arrowColor); if( tiket >= 0 ) { m_positions.Add(tiket); return m_positions.Total() - 1; } else { int errorCode = GetLastError(); // リトライしても仕方がないエラーの時は終了してしまう。 if( errorCode == ERR_INVALID_PRICE || errorCode == ERR_INVALID_STOPS || errorCode == ERR_INVALID_TRADE_VOLUME || errorCode == ERR_NOT_ENOUGH_MONEY ) { return -1; } } } Sleep(100); } Print("SendOrder Timeout"); return -1; } //------------------------------------------------------------------ // 成行き決済を行う。 // Return 発注成功時ture それ以外false bool CTradingWrapper::CloseOrder( int index, //決済するインデックス uint slippage, //許容スリッピング color arrowColor = clrNONE //注文矢印の色 ) { uint start = GetTickCount(); while(true) { if( (GetTickCount() - start ) > m_timeout ) return false; if( IsTradeAllowed() ) { // オーダーが選択できない状態(すでに存在しない)場合は、リストから削除して終了する。 int targetTicket = m_positions.At(index); if( !OrderSelect(targetTicket, SELECT_BY_TICKET) ) { m_positions.Delete(index); return false; } if( OrderClose(OrderTicket(),OrderLots(), OrderClosePrice(), slippage * m_pipsRate, arrowColor) ) { m_positions.Delete(index); return true; } else { int errorCode = GetLastError(); Print("Close Error[", errorCode, "] "); // リトライしても仕方がないエラーの時は終了してしまう。 if( errorCode == ERR_INVALID_TICKET) { m_positions.Delete(index); return false; } } } Sleep(100); } Print("CloseOrder Timeout"); return false; } //------------------------------------------------------------------ // 全ポジションを成行き決済を行う。 // Return 発注成功時ture それ以外false bool CTradingWrapper::CloseOrderAll( uint slippage, // 許容スリッピング color arrowColor = clrNONE // 注文矢印の色 ) { RefreshPositions(); bool result = true; for( int i = m_positions.Total() - 1; i >= 0; i--) { result &= this.CloseOrder(i, slippage, arrowColor); } return result; } //------------------------------------------------------------------ // 注文を変更する。 // Return 発注成功時ture それ以外false bool CTradingWrapper::ModifyOrder( int index, //決済するインデックス double price, //価格 uint stoploss = 0, //ストップロス(Pips単位) uint takeprofit = 0, //利確値(Pips単位) datetime expiration = 0, //注文有効期限 color arrowColor = clrNONE // 注文矢印の色 ) { uint start = GetTickCount(); while(true) { if( (GetTickCount() - start ) > m_timeout ) return false; if( IsTradeAllowed() ) { // オーダーが選択できない状態(すでに存在しない)場合は、リストから削除して終了する。 int targetTicket = m_positions.At(index); if( !OrderSelect(targetTicket, SELECT_BY_TICKET) ) { m_positions.Delete(index); return false; } double bid = MarketInfo(m_symbol, MODE_BID); double ask = MarketInfo(m_symbol, MODE_ASK); int cmd = OrderType(); // 計算用 負数フラグ int flag = cmd == OP_BUY || cmd == OP_BUYLIMIT || cmd == OP_BUYSTOP ? 1 : -1; double closeTarget = cmd == OP_BUY || cmd == OP_BUYLIMIT || cmd == OP_BUYSTOP ? bid : ask; //pips値からストップロス値、利益確定値を取得する。 double stoplossValue = 0 ; double takeprofitValue = 0; if( stoploss != 0 ) { stoplossValue = NormalizeDouble(closeTarget - this.GetPipsValue() * stoploss * flag, m_digit ); } if( takeprofit != 0) { takeprofitValue = NormalizeDouble(closeTarget + this.GetPipsValue() * takeprofit * flag, m_digit ); } if( OrderModify(targetTicket, price, stoplossValue, takeprofitValue, expiration, arrowColor )) { return true; } else { int errorCode = GetLastError(); Print("Order Error[", errorCode, "] "); // リトライしても仕方がないエラーの時は終了してしまう。 if( errorCode == ERR_INVALID_PRICE || errorCode == ERR_INVALID_STOPS || errorCode == ERR_INVALID_TRADE_VOLUME || errorCode == ERR_NOT_ENOUGH_MONEY) { return false; } } } } Print("ModifyOrder Timeout"); return false; } //------------------------------------------------------------------ // すべての注文を変更する。 bool CTradingWrapper::ModifyOrderAll( double price, //価格 uint stoploss = 0, //ストップロス(Pips単位) uint takeprofit = 0, //利確値(Pips単位) datetime expiration = 0, //注文有効期限 color arrowColor = clrNONE // 注文矢印の色 ) { RefreshPositions(); bool result = true; for( int i = m_positions.Total() - 1; i >= 0; i--) { result &= this.ModifyOrder(i, price, stoploss, takeprofit, expiration, arrowColor); } return result; } //------------------------------------------------------------------ // 注文を変更する。 // Return 発注成功時ture それ以外false bool CTradingWrapper::ModifyOrder( int index, //決済するインデックス uint stoploss, //ストップロス(Pips単位) uint takeprofit = 0, //利確値(Pips単位) color arrowColor = clrNONE //注文矢印の色 ) { return this.ModifyOrder(index, 0, stoploss, takeprofit, 0, arrowColor); } //------------------------------------------------------------------ // すべての注文を変更する。 bool CTradingWrapper::ModifyOrderAll( uint stoploss, //ストップロス(Pips単位) uint takeprofit = 0, //利確値(Pips単位) color arrowColor = clrNONE //注文矢印の色 ) { RefreshPositions(); return this.ModifyOrderAll(0, stoploss, takeprofit, 0, arrowColor); } //------------------------------------------------------------------ // 設定パラメータが安全かどうか // Return 安全ture それ以外false bool CTradingWrapper::IsSafeParameter() { if( m_symbol == NULL ) return false; if( m_maxPosition == 0 ) return false; return true; } //------------------------------------------------------------------ // ポジションリストを更新する。 void CTradingWrapper::RefreshPositions() { m_positions.Clear(); for( int i = 0 ; i < OrdersTotal(); i++) { if( OrderSelect(i, SELECT_BY_POS) ) { if( OrderMagicNumber() == m_magicNumber && OrderSymbol() == m_symbol) { m_positions.Add(OrderTicket()); } } } }
2015.4.17 クラスのコードを修正しました。
2015.5.15 新しい記事をアップしています。