基礎から学ぶシステムトレード
シストレブログ人気ランキング  

シストレ徹底攻略シストレマスターへの道ワールド・トレーディング・エッジ基礎から学ぶシステムトレードシストレニュースシストレツールシストレナビTOPへ

 

2012年10月08日(月)

MT5で両建てシステム(12)〜複数の仮想ポジションで両建て [MQL5]



MT5で両建てシステム」というタイトルで続けてきたコラムですが、ずいぶんプログラムも長くなってしまったので、今回で一旦おしまいとします。

最後は、タイトル通り、一つのEAで「両建てシステム」を作ってみます。

といっても、売買ルールのところは省略して、スクリプトで買いポジションと売りポジションを仮想的に建てるところまでです。

さて、両建てするには、少なくとも二つの仮想ポジションが必要となります。

そこで、ポジションの情報を保存した変数を配列にしてみます。

つまり、これまで

MyPosition MyPos;

としていたところを

MyPosition MyPos[2];

のように、二つの要素をもつ配列とします。もっと一般的には、

#define POSITIONS 2
MyPosition MyPso[POSITIONS];

としておくと、POSITIONSの値を変えることでポジションの数も自由に変えられて便利です。

このように仮想ポジションを配列にした売買スクリプトプログラムを以下に示します。

#property script_show_inputs

#define POSITIONS 2

input string COMMENT = "Script2"; // コメント
input double Lots = 0.1; // 売買ロット数
input ulong Slippage = 20; // スリッページ

// 仮想ポジションの構造体
struct MyPosition
{
ulong ticket;
double lots;
double price;
};

MyPosition MyPos[POSITIONS]; // 仮想ポジションデータ
ulong MAGIC_B[POSITIONS]; // 買いポジションのマジックナンバー
ulong MAGIC_S[POSITIONS]; // 売りポジションのマジックナンバー

// スタート関数
void OnStart()
{
InitPosition(1000);
ShowPosition();

int ret = MessageBox("Buy at market", "TradeTest", MB_OKCANCEL);
if(ret == IDOK) OrderSendMarket(0, ORDER_TYPE_BUY, Lots, COMMENT+"-BuyOpen");
ShowPosition();

ret = MessageBox("Sell at market", "TradeTest", MB_OKCANCEL);
if(ret == IDOK) OrderSendMarket(1, ORDER_TYPE_SELL, Lots, COMMENT+"-SellOpen");
ShowPosition();

ret = MessageBox("Close Buy Position", "TradeTest", MB_OKCANCEL);
if(ret == IDOK) OrderClose(0, COMMENT+"-BuyClose");
ShowPosition();

ret = MessageBox("Close Sell Positon", "TradeTest", MB_OKCANCEL);
if(ret == IDOK) OrderClose(1, COMMENT+"-SellClose");
ShowPosition();
}

// 新規成行注文
bool OrderSendMarket(int pos_id, ENUM_ORDER_TYPE type, double volume, string comment)
{
if(MyPos[pos_id].lots != 0) return(false);

MqlTradeRequest request={0};
MqlTradeResult result={0};

MqlTick tick;
SymbolInfoTick(_Symbol, tick);

if(type == ORDER_TYPE_BUY)
{
request.magic = MAGIC_B[pos_id];
request.price = tick.ask;
}
else if(type == ORDER_TYPE_SELL)
{
request.magic = MAGIC_S[pos_id];
request.price = tick.bid;
}
else return(false);

request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = volume;
request.deviation = Slippage;
request.type = type;
request.type_filling = ORDER_FILLING_FOK;
request.comment = comment;

OrderSend(request,result);
if(result.retcode != TRADE_RETCODE_DONE)
{
Print("OrderSendRetCode=", result.retcode);
return(false);
}
MyPos[pos_id].ticket = result.deal;
MyPos[pos_id].lots = result.volume;
MyPos[pos_id].price = result.price;
if(type == ORDER_TYPE_SELL) MyPos[pos_id].lots = -MyPos[pos_id].lots;
return(true);
}

// ポジションの決済
bool OrderClose(int pos_id, string comment)
{
if(MyPos[pos_id].lots == 0) return(false);

MqlTradeRequest request={0};
MqlTradeResult result={0};

MqlTick tick;
SymbolInfoTick(_Symbol, tick);

double lots = MyPos[pos_id].lots;
if(lots > 0)
{
request.type = ORDER_TYPE_SELL;
request.magic = MAGIC_B[pos_id];
request.price = tick.bid;
}
else if(lots < 0)
{
request.type = ORDER_TYPE_BUY;
request.magic = MAGIC_S[pos_id];
request.price = tick.ask;
}
else return(true);

request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.deviation = Slippage;
request.volume = MathAbs(lots);
request.type_filling = ORDER_FILLING_FOK;
request.comment = comment;

OrderSend(request,result);
if(result.retcode != TRADE_RETCODE_DONE)
{
Print("OrderCloseRetCode=", result.retcode);
return(false);
}
ZeroMemory(MyPos[pos_id]);
return(true);
}

// ポジションの初期化
void InitPosition(int Magic)
{
HistorySelect(0, TimeCurrent());
for(int i=0; i<POSITIONS; i++)
{
MAGIC_B[i] = Magic + 2*i;
MAGIC_S[i] = MAGIC_B[i] + 1;
ZeroMemory(MyPos[i]);

for(int k=HistoryDealsTotal()-1; k>=0; k--)
{
ulong ticket = HistoryDealGetTicket(k);
if(HistoryDealGetString(ticket, DEAL_SYMBOL) != _Symbol) continue;
long dmagic = HistoryDealGetInteger(ticket, DEAL_MAGIC);
ENUM_DEAL_TYPE dtype = (ENUM_DEAL_TYPE)HistoryDealGetInteger(ticket, DEAL_TYPE);
// クローズポジション
if((dtype == DEAL_TYPE_SELL && dmagic == MAGIC_B[i]) ||
(dtype == DEAL_TYPE_BUY && dmagic == MAGIC_S[i])) break;
// オープンポジション
if((dtype == DEAL_TYPE_BUY && dmagic == MAGIC_B[i]) ||
(dtype == DEAL_TYPE_SELL && dmagic == MAGIC_S[i]))
{
MyPos[i].ticket = ticket;
MyPos[i].lots = HistoryDealGetDouble(ticket, DEAL_VOLUME);
if(dtype == DEAL_TYPE_SELL) MyPos[i].lots = -MyPos[i].lots;
MyPos[i].price = HistoryDealGetDouble(ticket, DEAL_PRICE);
break;
}
}
}
}

// ポジションの表示
void ShowPosition()
{
string pos_comment = "";
for(int i=0; i<POSITIONS; i++)
{
if(MyPos[i].ticket)
pos_comment = pos_comment + MyPos[i].lots + " lots at " + MyPos[i].price + "¥n";
}
Comment(pos_comment);
}

相当長くなってしまいましたが、前回からの変更点を簡単に説明しておきます。

仮想ポジションMyPosを配列にすると同時に、マジックナンバーも配列にしてあります。

ulong MAGIC_B[POSITIONS]; // 買いポジションのマジックナンバー
ulong MAGIC_S[POSITIONS]; // 売りポジションのマジックナンバー

そして、その値はInitPosition()関数で代入しています。パラメータ「1000」に対して、買いポジションのマジックナンバーを1000, 1002、売りポジションのマジックナンバーを1001, 1003としています。

ここではポジションは二つあるので、MyPos[0]とMyPos[1]それぞれに仮想ポジションがあるかを探します。

OrderSendMarket()とOrderClose()には、ポジションを指定するために、pos_id というパラメータを追加します。このpos_idという変数は、MyPos[pos_id]のように配列のインデックスに対応させます。

実際にオーダーを送信する場合には、

OrderSendMarket(0, ORDER_TYPE_BUY, Lots, COMMENT+"-BuyOpen");
OrderSendMarket(1, ORDER_TYPE_SELL, Lots, COMMENT+"-SellOpen");

のように、最初に0番目のポジションとして買いオーダーを送信します。そして次に1番目のポジションとして売りオーダーを送信します。この時点で両建てとなります。

仮想ポジションの状態については、別途ShowPosition()という関数を作って、それによりチャートの左上に表示させるようにします。

その後、

OrderClose(0, COMMENT+"-BuyClose");
OrderClose(1, COMMENT+"-SellClose");

のように0番目、1番目のポジションを決済して終わりです。ここで決済する順番はどちらでも構いません。

ではこのスクリプトの実行例をみてみましょう。

まず、0番目のポジションとして買いオーダーを送信します。この場合、チャート左上の仮想買いポジションと実際のポジションが見えます。

画像(450x256)・拡大画像(471x268)

次に1番目のポジションとして売りオーダーを送信します。すると、実際のポジションは消えますが、チャート左上に、買いポジションに加えて売りポジションが建っていることがわかります。

画像(450x256)・拡大画像(471x268)

今度は、0番目のポジションを決済します。すると、1番目の売りポジションが残るので、実際のポジションとしても売りポジションが現れます。

画像(450x256)・拡大画像(471x268)

最後に1番目のポジションを決済すると、すべての仮想ポジション、実際のポジションは消えます。

画像(450x256)・拡大画像(471x268)

こんな感じで、あとは実際に売買ロジックを作ってEAに組み込めば、MT5でも両建てシステムのできあがりです。

このテーマの記事は、これでおしまいとします。長い間、ありがとうございました。

次回はまた違うネタを探してきます。


>>“基礎から学ぶシステムトレード”全記事バックナンバーはこちらから




Posted at 10時56分


ページのトップへ ページのトップへ

Sponsor AD

2012/10

  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      

プロフィール

豊嶋久道

2003年よりFX取引を始め、システムトレードの道へ。最近ではFXオプション取引も含めたトレーディングシステムの研究を行っている。システムトレードを基礎から正しく理解するための情報を発信する予定。

PHOTO

ランダムウォークとランダムトレード(6)

ランダムウォークとランダムトレード(6)

カテゴリーリスト

最近の記事

検索


当サイトコメントについて

当コメントは情報提供のみを目的として作成されたものであり、投資に関してはご自身でご判断くださいますようお願い致します。また、当資料は著作物であり著作権法により保護されております。無断で全文または一部を転載することはできません。

RSS1.0

[Login]


powered by a-blog
Copyright (C) 2008 PhiConcept,Inc. All rights reserved.