さて前回は、新たに発見した「ERR_COMMON_ERROR」発生とその状況からの仮説を書きました。今回は、延び延びになっていた、以前のブログ記事で立てた「OrderSelect問題」の仮説検証結果について書いてみたいと思います。
結論から言うと、
仮説は誤りでした。
そもそもどういう仮説だったかと言うと、以前のブログ記事で書いた通り、「OrderSelect()した結果は、1つのMT4で一つの領域に格納されていて、複数チャートでEAを同時実行した場合誤作動してしまう」というモノ。
なので、OrderSelect()した結果の領域は複数あるという結論。
まず、検証方法の概略から。
【OrderSelect問題仮説1検証方法】
--------------------------
1.4つの通貨ペアで同じEAを実行させる
2.EA開始時に発注する
3.発注完了したら、MAGICナンバーと通貨ペアが同じものをOrderSelect()する。
4.OrderSelect()完了したら、一定時間スリープさせた後、以下を比較して異なっていたら、
その旨のExpertログを出力してstart()関数を抜ける。
・Symbol()とOrderSymbol()
・内部変数に格納したチケット番号とOrderTicket()
5.一回発注したら以降は発注しない。
6.検証終了後は、EAを停止させ、オーダを手動削除
7.対象通貨ペアとSleep時間
EURUSD:10000ms
USDCHF:2000ms
GBPUSD:5000ms
USDJPY:3000ms
8.利用したMT4
Forex.com Ver:4.00 Build 229(26 Nov 2010)
--------------------------
【検証に使用したEA-1】
-----------------------------
#property copyright "Copyright 2011, ahaha_fxtrader"#property link "http://blog.livedoor.jp/ahaha_fxtrader/"#include <stdlib.mqh>#include <stderror.mqh>//---- input parametersextern int Magic = 47982738;extern int SleepTime=2000;int init(){MathSrand(TimeCurrent());return(0);}int deinit(){return(0);}int start(){static int ticket = 0;if( ticket<=0 ){int type = MathRand()-(32767.0/2.0);if( type >=0 ){ticket = OrderSend(Symbol(),OP_BUY,MarketInfo(Symbol(),MODE_MINLOT),Ask,10,0,0,NULL,Magic);if( ticket>0 ) Print("[[ORDER]] Symbol("+Symbol()+") Ticket("+ticket+")");}else{ticket = OrderSend(Symbol(),OP_SELL,MarketInfo(Symbol(),MODE_MINLOT),Bid,10,0,0,NULL,Magic);if( ticket>0 ) Print("[[ORDER]] Symbol("+Symbol()+") Ticket("+ticket+")");}}// オーダ一覧取得ループfor( int i=OrdersTotal()-1 ; i>=0 ; i-- ){// オーダ情報取得if( OrderSelect(i,SELECT_BY_POS , MODE_TRADES)==FALSE ){int Errno = GetLastError();Print("[[WARN]] Errno("+Errno+") Description("+ErrorDescription(Errno)+")");continue;}// 対象外であれば次if( (OrderMagicNumber() != Magic) || (OrderSymbol() != Symbol()) ) continue;// 一定時間スリープするSleep(SleepTime);// チャートのシンボルとOrderSelectのシンボルを出力するif( (OrderSymbol()==Symbol()) && (ticket==OrderTicket()) ) Print("[[INFO]] Symbol("+Symbol()+") OrderSymbol("+OrderSymbol()+") Ticket("+ticket+") OrderTicket("+OrderTicket()+")");else Print("[[WARN]] Symbol("+Symbol()+") OrderSymbol("+OrderSymbol()+") Ticket("+ticket+") OrderTicket("+OrderTicket()+")");}return(0);}
------------------------------------
これを、1時間強動作させた結果、OrderSymbol()もしくはOrderTicket()が間違えた値になったログは出力されなかった。
以上、終わり!!
ちゃうちゃう。
そして次考えた仮説としては、OrderSelect対象となるレコード数が変動した場合にずれるかもしれないというケース。
【OrderSelect問題仮説2検証方法】
--------------------------
乱数で買い/売りを決め、スリープ後決済する。
2時間実行し、スリープ後にチケット番号か、シンボルが不一致になれば"[[WARN]]"を出力する。
他の条件は、前述の「OrderSelect問題仮説1」と同じ。
但し、実行時間は2時間。
--------------------------
【検証に使用したEA-2】
-----------------------------
#property copyright "Copyright 2011, ahaha_fxtrader"#property link "http://blog.livedoor.jp/ahaha_fxtrader/"#include <stdlib.mqh>#include <stderror.mqh>//---- input parametersextern int Magic = 47982738;extern int SleepTime=2000;int init(){MathSrand(TimeCurrent());return(0);}int deinit(){return(0);}int start(){static int ticket = 0;bool found = FALSE;if( ticket<=0 ){int type = MathRand()-(32767.0/2.0);if( type >=0 ){ticket = OrderSend(Symbol(),OP_BUY,MarketInfo(Symbol(),MODE_MINLOT),Ask,10,0,0,NULL,Magic);if( ticket>0 ) Print("[[ORDER]] Symbol("+Symbol()+") Ticket("+ticket+")");}else{ticket = OrderSend(Symbol(),OP_SELL,MarketInfo(Symbol(),MODE_MINLOT),Bid,10,0,0,NULL,Magic);if( ticket>0 ) Print("[[ORDER]] Symbol("+Symbol()+") Ticket("+ticket+")");}}if( ticket<=0 ) return(0);// オーダ一覧取得ループfound = FALSE;for( int i=OrdersTotal()-1 ; i>=0 ; i-- ){// オーダ情報取得if( OrderSelect(i,SELECT_BY_POS , MODE_TRADES)==FALSE ){int Errno = GetLastError();Print("[[SELECT]] NotFound!");RefreshRates();continue;}// 対象外であれば次if( (OrderMagicNumber() != Magic) || (OrderSymbol() != Symbol()) ) continue;// 一定時間スリープするSleep(SleepTime);// チャートのシンボルとOrderSelectのシンボルを出力するif( (OrderSymbol()==Symbol()) && (ticket==OrderTicket()) ) Print("[[INFO]] Symbol("+Symbol()+") OrderSymbol("+OrderSymbol()+") Ticket("+ticket+") OrderTicket("+OrderTicket()+")");else Print("[[WARN]] Symbol("+Symbol()+") OrderSymbol("+OrderSymbol()+") Ticket("+ticket+") OrderTicket("+OrderTicket()+")");if( OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),100) ){Print("[[CLOSE]] Symbol("+Symbol()+") OrderSymbol("+OrderSymbol()+") Ticket("+ticket+") OrderTicket("+OrderTicket()+")");ticket = 0;}}return(0);}
-------------------------------------
結果、問題なし。
#つまりExpertログ上に"[[WARN]]"は出力されなかった。
というか、ええ加減
自分のプログラムを疑わんかい!
は、はい。。。
仮説間違えていたということは、間違えた仮説に基づいた処置は根本解決になっていないということ。ただ、問題発生後、start()関数を排他利用させた以外にもEAのプログラムもだいぶ変更したけど、事の発端につながる様なバグはなかったし、同様の問題も再発していない。
つまり、仮説は否定されたけど、原因不明な点は変わらず。
ともかく、
お騒がせしましたm(_ _)m
#先にドキュメント仕上げたいなぁ。。
0 件のコメント:
コメントを投稿