mql5言語の特徴、微妙なニュアンスとテクニック - ページ 201

 
マクロを呼び出す際に、パラメータを指定しない(省略する)ことができますが、指定されていないパラメータでマクロを動作させることを特別に許可したい場合があります。


そんなときのために、補助マクロを紹介します。

IS_PARAMETER_SET(p) は、p がセットされていれば (文字列変数 ==NULL でも) true を返す式を定義しています。

注意: この式はコンパイル時の前処理で評価されます!!! つまり、#ifdef IS_PARAMETER_SET(p) #else のような実装には使えません (これは以下の他のマクロにも当てはまります)。

2.パラメータが指定されていない場合のコンパイル エラーを避けるために、 パラメータの値を明示的に文字列に変換する必要がある場合は、 __EVAL_STR(p) を使用します。 p が定義されていない場合、または NULL リテラルで明示的に定義されている場合は、 "" が返されます。配列、構造体、クラスには適用されません。

パラメータを明示的に数値に変換する場合は、__EVAL_NON_STR(p)となる。pが設定されていない場合は0を返す。pが文字列の場合は動作しない!

コードと使用例です。

//Expression returns true if macro's parameter is specified.
#define  IS_PARAMETER_SET(p) ("" != #p || __hlp_macro_func(p))
bool __hlp_macro_func(const string p = NULL) {return "" == p;}
template<typename T> bool __hlp_macro_func(T p)    {return true;}
template<typename T> bool __hlp_macro_func(T& p)   {return true;}
template<typename T> bool __hlp_macro_func(T& p[]) {return true;}


//Expression returns parameter p; if parameter is not specified returns NULL; if p is string returns p
//Error for arrays and objects
#define __EVAL(p) (""==#p?NULL:p+NULL)


//Explicit conversion to string. If parameter is not specified or is constant NULL returns ""
//Error for arrays and objects
#define __EVAL_STR(p) (""==#p || "NULL"==#p? "" :(string)(p+NULL))


//Explicit conversion to number. If parameter is not specified returns 0. Works incorrect if p is string!
//Error for arrays and objects
#define __EVAL_NON_STR(p) ("" == #p? 0 : p+0)


struct S1
  {   int               a; };
class C1
  { int               a; };

void OnStart()
  {
//---
   Print(IS_PARAMETER_SET());                //false
   Print(IS_PARAMETER_SET(""));              //true
   Print(IS_PARAMETER_SET("test"));          //true
   Print(IS_PARAMETER_SET(NULL));            //true
   Print(IS_PARAMETER_SET(0));               //true
   Print(IS_PARAMETER_SET(1));               //true
   string str;
   Print(IS_PARAMETER_SET(str));             //true

   int arr[1];
   Print(IS_PARAMETER_SET(arr));             //true
   S1 _struct;
   Print(IS_PARAMETER_SET(_struct));         //true
   C1 _class;
   Print(IS_PARAMETER_SET(_class));          //true

#define   MACRO1_(a,b)  (IS_PARAMETER_SET(b)?a:-a)
   Print(MACRO1_(1, 0));                     //1
   Print(MACRO1_(1,));                       //-1

#define   MACRO2_(a,b,c)  Print(a," = ",b + c)
#define   MACRO3_(a,b,c)  Print(__EVAL_STR(a)," = ",__EVAL_NON_STR(b) + __EVAL_NON_STR(c))

 //MACRO2_(, 2,);                            // ',' - syntax error, parameter missed
   MACRO3_(, 2,);                            // = 2
   MACRO3_("a", 2, 3);                       // a = 5
  }


 
fxsaber:

RannForex-Serverの デモ口座で以下のコードで、このアドバイザーを実行すると、この状況をすぐに再現することができます。


結果


ところで、このスクリプトでは、同期的にOrderSendを実行する際のバグが(初めてとは限らない)示されています。

OrderSendが数十/数百ミリ秒実行された後、注文価格はOrderSendが成功したものでなく、古いものになります。


同じチケットの話に戻ると、いくつかの結論が導き出されます。

  1. 部分指値注文がぶら下がっている場合、「注文と取引」タブには、生成された取引は表示されません。
  2. ヘッジでは、1つの注文が異なる価格の複数のIN取引を生み出すことがあります。その結果、ポジションの始値は端数(pipsに相対する)となります。
  3. 生成されたポジションは、Partial Putを削除することなく決済することができます。しかし、その後、保留中の注文がトリガーされた場合、前に決済されたポジションのチケットと同じチケットでトレードが開始されます。つまり、あるチケットでポジションをクローズする場面があるかもしれません。そして、同じティッカーでポジションが再表示されます。
  4. ブローカーのソフトウェアにより、部分執行の実装が異なる場合があります。上記はMT5の標準的な実装です。

もし、他の取引サーバーで再現できた方がいらっしゃいましたら、その名前を教えてください。

検索文字列:Oshibka 010.

再び部分実行の問題に戻ります。

1.3.の「部分約定を解除せずに、形成したポジションを決済することができる」について教えてください。しかし、その後に注文がトリガーされた場合、前に決済したポジションのチケットと同じチケットでトレードが開始されます。つまり、あるチケットでポジションをクローズする場面があるかもしれません。そして、同じチケットで再びポジションが出現する」
この場合、POSITION_IDENTIFIERは POSITION_TICKETと 等しかった のか、 そうでなかったのでしょうか。

2.以前、「POSITION_TICKET != POSITION_IDENTIFIER」のスレッドで、MT5の別のロジックを実証していただきました。

https://www.mql5.com/ru/forum/227423/page2#comment_6543129

fxsaber:

結論

これがブローカーハックの特殊性ではなく、MT5の正常な動作であると仮定すると、以下のようになります。

  • ORDER_STATE_PARTIAL は履歴の注文に存在しません。
  • 実行された注文は常にORDER_STATE_FILLEDのステータスになります。
  • 注文の一部が約定すると、取引サーバ(ORDER_REASON_CLIENT - 最初の注文が自動発注(EXPERT)であっても)により対応する新しい成行 注文が作成されます。
  • 古いライブ注文(チケットは変更されていない)は、数量(ORDER_VOLUME_CURRENT)が減少した状態で保留されたままです。
  • この場合の古いライブ注文のステータスはORDER_STATE_PARTIALです。実際には、このフラグは ORDER_VOLUME_CURRENT と ORDER_VOLUME_INITIAL を比較した結果である。
  • すべてのオープンポジションは、ID==OrderTicketを受け取ります。ここで、OrderTicket はトレードサーバーで生成されたチケットです。
  • 取引は常に正確に1つの履歴注文を持ち、そのステータスはORDER_STATE_FILLEDです。
  • 実行されたヒストリカル注文は、それぞれ正確に1つの取引となります。
  • 実行された注文のORDER_VOLUME_INITIALは、その注文が実行されたボリュームと同じです。すなわち、キャンセルされた最初の注文でさえ、それが生み出した取引のボリュームと同じORDER_VOLUME_INITITALを持っています。
  • 最初の注文(部分的に約定したもの)の時刻は変わらず、その約定時刻と同じにはなりません。
  • 履歴表は注文時間(ORDER_TIME_SETUP)でソートされますが、取引時間ではソートされません。そのため、HistorySelect from DEAL_TIMEを実行しても、対応する注文を履歴テーブルに取得することができません。
  • HistorySelectByPositionは、常に必要な取引/注文のセットを返します。
  • どのような取引でもスリッページを計算することができます。

経験上、MT5が適用されるケースやモードは一般的にどのようなパターンでしょうか?

3.結局、「POSITION_TICKET != POSITION_IDENTIFIER」のような状況が実際にあったのでしょうか?

POSITION_TICKET != POSITION_IDENTIFIER
POSITION_TICKET != POSITION_IDENTIFIER
  • 2018.02.12
  • www.mql5.com
зная id позиции можно ли без перебора узнать тикет позиции...
 
mktr8591:
マクロを呼び出す際に、パラメータを省略する(省く)ことが可能ですが、指定されていないパラメータでマクロを動作させることを特別に許可したい場合があります。
どのマクロでも、指定されていないパラメータはコンパイラに空文字列として扱われることが判明していますね。
 
fxsaber:
つまり、どのマクロでも指定されていないパラメータは、コンパイラによって空文字列として扱われることがわかったのですね。

ある意味、そうですね。 でも、「空っぽのような」という言い方のほうがいいかもしれません。明確に表現するのが難しい :-)

しかし、#pは間違いなく文字列==""になってしまいます。

 
mktr8591:

ある意味、そうですね。 でも、「空っぽのような」という言い方のほうがいいかもしれません。明確に表現するのが難しい :-)

しかし、#pは間違いなく文字列==""になってしまいます。

ありがとうございます、面白いニュアンスですね。

 

fxsaber

この問題について調べてみてください。https://www.mql5.com/ru/forum/170952/page201#comment_21964923

Особенности языка mql5, тонкости и приёмы работы
Особенности языка mql5, тонкости и приёмы работы
  • 2021.04.03
  • www.mql5.com
В данной теме будут обсуждаться недокументированные приёмы работы с языком mql5, примеры решения тех, или иных задач...
 
mktr8591:

再び部分性能の問題に戻ります。

1.3.の「部分プット・オプションを外さずに成立したポジションを決済することができる」について教えてください。しかし、その後に注文がトリガーされた場合、前に決済したポジションのチケットと同じチケットでトレードが開始されます。つまり、あるチケットでポジションをクローズする場面があるかもしれません。そして、同じチケットで再びポジションが出現する」
この場合、POSITION_IDENTIFIERは POSITION_TICKETと 等しかった のか、 そうでなかったのか?

2.先ほど、「POSITION_TICKET != POSITION_IDENTIFIER」の分岐で、MT5の別のロジックを示しましたが、そのロジックはどのようなものですか?

https://www.mql5.com/ru/forum/227423/page2#comment_6543129

これまでの経験上、どのようなケース/運用形態でMT5のスキームが適用されるのか、一般的なパターンを示したのでしょうか?

3.結局、「POSITION_TICKET != POSITION_IDENTIFIER」のような状況が実際にあったのでしょうか?

どちらのリンクも、部分実行の異なる実装について述べています。これは、MT5ではなく、ブローカーのソフトウェアによって決定されます。

これまでチケットとIDの不一致は発生していない。

 
ありがとうございます。
 

トレーディング、自動売買システム、ストラテジーテストに関するフォーラム

ライブラリ:使用方法

fxsaber, 2021.05.01 14:17

GetMicrosecondCountは、(ULONGのオーバーフローがない限り)前の呼び出しより小さい値を出力することができます。そのような状況の例。
2021.04.29 06:43:31.915   Alert: NewValue = 296000074313, PrevValue = 296001329284

2021.04.29 06:43:32.149   Alert: NewValue = 296086250613, PrevValue = 296087264090

2021.04.29 06:43:31.868   Alert: NewValue = 295129291901, PrevValue = 295130576710

2021.04.29 06:43:32.180   Alert: NewValue = 295955613012, PrevValue = 295956589070

2021.04.29 06:43:32.180   Alert: NewValue = 295146223171, PrevValue = 295147199454

2021.04.29 06:43:32.149   Alert: NewValue = 295065995432, PrevValue = 295067005968

2021.04.29 06:43:32.149   Alert: NewValue = 295078776581, PrevValue = 295079787357

各ラインは、3つのMT4端末で異なるEAによって取得されています。

そして、MT5ではこのようなことが起こりますが、MT4ではもっと少ない頻度です。

気をつけてください。

 
このトピックに関係のないコメントは、「MQL5 MT5 MetaTrader5初心者からの質問」に移動しました。
理由: