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

 

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

チャート交換の見分け方は?

fxsaber さん 2018.02.08 12:39

void OnTick()
{  
  const long Chart = ChartID();
  string PrevSymbol = _Symbol;
  ENUM_TIMEFRAMES PrevTF = _Period;
    
  while (!IsStopped())
  {
    if ((PrevSymbol != ChartSymbol(Chart)) || (PrevTF != ChartPeriod(Chart))) // ноль указывать НЕЛЬЗЯ!
    {      
      PrevSymbol = ChartSymbol(Chart);
      PrevTF = ChartPeriod(Chart);
      
      Alert(PrevSymbol + " " + EnumToString(PrevTF));      
    }
    
    Sleep(0);
  }
}

一部の関数で、ChartID入力パラメータがゼロの場合、値の再計算が行われない。現在のチャートの実データが必要な場合は、フルIDを使用する必要があります。

 

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

position_ticket != position_identifier

fxsaber さん 2018.02.12 20:14

結論

これがブローカーのハックの特殊性ではなく、通常の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は、常に必要な取引/注文のセットを返します。
  • どのような取引でもスリッページを計算することができます。

弱点

  • ORDER_REASON_PARTIAL、DEAL_REASON_PARTIAL、POSITION_REASON_PARTIALが欠落しています。これらのフラグは、それぞれのリストでREASON_EXPERTの直後に配置する必要があります。
  • 指値注文の一部を成行注文で執行する場合、その性質上、マイナスのスリッページが発生することがあります。これは注文の種類だけのエラーのようで、実際には成行注文はなく、MT5内部で作成されるだけで、外部に出ることはないようです。

ZZY 完全に確定した仮説です。

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

position_ticket != position_identifier

パベル・コルチン さん 2018.02.12 13:31

(よくわからない、確認しにくい、部分的な位置の閉鎖に似ている)

仕組みはこうだ。

1) 保留注文が部分的に発生 - Position_ID = Order_Ticket1 のポジションが開設された。

2)残った注文は新しい注文Order_Ticket2に変換さ れ、実行を待ちます。新しいOrder_Ticket2 != Order_Ticket1 なぜなら同じOrder_Ticketの注文は履歴に2つ存在できないからです。

3) 残りの注文が執行された - Position_ID = Order_Ticket2 のポジションが開かれる

履歴には2つのオーダーがあり、端末には2つのポジションがあり、すべてが対応しています。

 

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

"トレーダー向けLifeHack: 定義にForEachを混ぜる(#define)" に関するディスカッション

fxsaber さん 2018.02.14 10:54

パフォーマンス測定

#define  BENCH(A)                                                              \
{                                                                             \
  const ulong StartTime = GetMicrosecondCount();                              \
  A;                                                                          \
  Print("Time[" + #A + "] = " + (string)(GetMicrosecondCount() - StartTime)); \
}

double GetAsk()
{
  static MqlTick tick = {0};
  
  return(SymbolInfoTick(Symbol(),tick) ? tick.ask : 0);
}

#define  AMOUNT 1 e6

void OnStart()
{
  double Sum = 0;
  
  BENCH(for (int i = 0; i < AMOUNT; i++) Sum += GetAsk())
  BENCH(for (int i = 0; i < AMOUNT; i++) Sum += SymbolInfoDouble(_Symbol, SYMBOL_ASK))
  
  Print(Sum);
}


結果

Time[for(inti=0;i<AMOUNT;i++)Sum+=GetAsk()] = 78952
Time[for(inti=0;i<AMOUNT;i++)Sum+=SymbolInfoDouble(_Symbol,SYMBOL_ASK)] = 162606

完全に勘違いしてました!SymbolInfoDouble は SymbolInfoTick の 2 倍の速度になります。

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

"トレーダー向けLifeHack: 定義にForEachを混ぜる(#define)" に関するディスカッション

fxsaber さん 2018.02.14 11:58

無能。テスターでの結果

2017.09.01 00:00:10   Time[for(inti=0;i<AMOUNT;i++)Sum+=GetAsk()] = 87424
2017.09.01 00:00:10   Time[for(inti=0;i<AMOUNT;i++)Sum+=SymbolInfoDouble(_Symbol,SYMBOL_ASK)] = 83410

パフォーマンスが必要な場合(Optimizer)には、SymbolInfoDoubleを使用 するのがよいでしょう。現実世界では、何の違いもないのです。


ZZY機能速度測定は、性能が重要視される環境で測定すべき - テスター

 

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

バグ、バグ、質問

fxsaber さん 2018.02.12 23:10

2台の取引用デモサーバーでBUYポジションを手動で開設する。


ロボフォレックス-メタトレーダー5

2018.02.13 00:02:08.424 '8520459': market buy 1.00 GBPUSD
2018.02.13 00:02:10.101 '8520459': accepted market buy 1.00 GBPUSD
2018.02.13 00:02:10.101 '8520459': deal #90389019 buy 1.00 GBPUSD at 1.38387 done (based on order #107426544)
2018.02.13 00:02:10.101 '8520459': order #107426544 buy 1.00 / 1.00 GBPUSD at 1.38387 done in 1683.949 ms


FXOpen-MT5

2018.02.13 00:00:25.780 '18000903': market buy 1.00 GBPUSD
2018.02.13 00:00:25.912 '18000903': accepted market buy 1.00 GBPUSD
2018.02.13 00:00:25.922 '18000903': market buy 1.00 GBPUSD placed for execution
2018.02.13 00:00:25.942 '18000903': order #896454 buy 1.00 / 1.00 GBPUSD at market done in 154.252 ms
2018.02.13 00:00:25.942 '18000903': deal #80559 buy 1.00 GBPUSD at 1.38387 done (based on order #896454)

同じ色の線は、同じものを示しています。しかし、明らかに順番が違うことがわかる。Roboでは、注文実行のメッセージは取引が実行された後に出てきます。オープンではBEFORE!このため、OrderSend は運を返しますが、トランザクションはまだありません。つまり、履歴のある非同期OrderSendを取得する。

FXOpen-MT5用コード

#define  PRINT(A) Print(#A + " = " + (string)(A))

void OnStart()
{
  MqlTradeRequest Request = {0};
  
  Request.action = TRADE_ACTION_DEAL;
  Request.symbol = _Symbol;
  Request.volume = 1;
  Request.type_filling = ORDER_FILLING_IOC;
  
  MqlTradeResult Result;
  
  PRINT(OrderSend(Request, Result));
  PRINT(Result.deal);
}


結果

OrderSend(Request,Result) = true
Result.deal = 0


この状況には、次のような説明があります。

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

バグ、バグ、質問

ラシード・ウマロフ さん 2018.02.15 06:25

外部の取引システムに注文を送信した場合、MetaTrader 5取引サーバーはその応答を待たず、直ちに「注文が発注されました」としてリクエストの結果を返します。このため、OrderSend は、約定した取引に関する情報がまだないため、常に deal=0 を返します。OnTradeまたはOnTradeTransactionでキャッチする。

取引イベントリスナーの例は、 MOEX用取引ロボットを作成する際に開始する場所- TradeTransactionListener.mq5 の記事で紹介されています。

OrderSend - 成行注文を送信 します。注文が発注 されました- Result.orderを読み取る必要がありますしかし、誰も取引(複数可)を待ってはいない。取引はたくさんあるかもしれないし、その実行時間の合計も定義されてはいない。

ブローカー側の出力の具体的な実装に依存します。一般的な場合、定義されていません。

ですから、FXOpen-MT5のデモ口座は他のデモとは一線を画しており、コードのテストとして使用することを強くお勧めします。


例えば、MQL5でこのような取引ロジックでスクリプトを書いてみることを提案します(MQL4スタイルはクイックセンス表示のためだけです)。

void OnStart()
{
  OrderCloseBy(OrderSend(_Symbol, OP_BUY, 1, Ask, 0, 0, 0), OrderSend(_Symbol, OP_SELL, 1, Bid, 0, 0, 0));
}

全然、簡単じゃないんです。また、部分実行に取り組むには、前述のデモサーバーをお勧めします。

 
fxsaber
MT5でよくある間違いの一つを解説した投稿を削除しました。
削除されたものの中には入っていません。それは変ですね。もう一度投稿していただけますか?
 
fxsaber

ポストが大きかった。まさか削除されるとは思わなかった。削除の理由を教えてほしい。また削除されるのはマゾいから。

削除された中にないって言ってるんだよ。不具合があったのでは?
 

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

オーダーループの整理

fxsaber さん 2018.02.16 09:40

MT5では全くうまくいっていない。問題を示す例

// Пример неправильного считывания торгового окружения на каждом тике
// Скрипт эмулирует два тика ТС, которая должна открыть одну позицию, если ее нет.

#include <Trade/Trade.mqh>

// Возвращает количество позиций по символу
int GetAmountPositions( const string Symb )
{
  int Res = 0;
  
  // Этот MQL5-код с ошибкой
  for (int i = PositionsTotal() - 1; i >= 0; i--)
    if (PositionGetSymbol(i) == Symb)
      Res++;

/*
  // В MT4 такой код выполняется без ошибки
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (OrderSymbol() == Symb))
      Res++;
*/      
  return(Res);
}

// Пример OnTick
void ExampleOnTick()
{
  static CTrade Trade;
  
  // Если нет позиции, открываем
  if (!GetAmountPositions(_Symbol))
    Trade.Buy(1);    
}

// Эмуляция прихода двух Tick-событий
void OnStart()
{
  ExampleOnTick(); 
  
  Sleep(10); // Между двумя тиками ~10 мс.
  
  ExampleOnTick();
}

このスクリプトをポジションのないシンボルで実行した場合、最終的に何が起こると思いますか?

正解は、1つまたは2つのポジション が空くということです。

その理由は、こうです。最初のOrderSendの後、成行注文が現れ、その実行の瞬間に新しいティックが来れば、まだポジションはなく、2回目のOrderSendが行われる。

このため、一見正常に見えるMT5のパターンも正常に 動作せず、結果としてcodobaseにあるMT5 Expert Advisorのほとんどが 動作しなくなります。同時に、ほぼ同じMT4テンプレートも 問題なく動作し続けます。

PositionTotalの一見良いアイデアは、MT5では成行注文のOrdersTotalも分析する必要があるため、やや影が薄くなっています。

気をつけよう!

 
fxsaber

このため、一見正常に見えるMT5のパターンも正常に動作 せず、結果として、コドベースのほとんどのMT5 EAが 動作しなくなります。

その証拠に、MT5のコドベースのExpert Advisorのほとんどを取り上げることができます。何かを選ぶのではなく、現時点での最新のExpert Advisorを 取り上げましょう。QBでMT5-publishingの経験が豊富な作者が書いているのが良い。

ソースコードには以下のような文字列があります(私のコメントはハイライトされています)。

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//....
   int total=0; // для расчета количества открытых советником позиций
//....
//--- main cycle
   for(int i=PositionsTotal()-1;i>=0;i--)
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
           {
            total++; // расчет количества открытых позиций
//....
   if(total==0) // Если нет открытых советником позиций
     {
      if(!RefreshRates())
        {
         PrevBars=iTime(1);
         return;
        }
      //--- open BUY 
      if(MACD_MAIN_2>MACD_SIGNAL_2 && MACD_MAIN_4<MACD_SIGNAL_4) // Сигнал на покупку
        {
         double sl=(InpStopLoss!=0)?m_symbol.Ask()-ExtStopLoss:0.0;
         double tp=(InpTakeProfit!=0)?m_symbol.Ask()+ExtTakeProfit:0.0;
         OpenBuy(sl,tp); // Отправка маркет-ордера на покупку
         return;
        }
      //--- open SELL
      if(MACD_MAIN_2<MACD_SIGNAL_2 && MACD_MAIN_4>MACD_SIGNAL_4) // Сигнал на продажу
        {
         double sl=(InpStopLoss!=0)?m_symbol.Bid()+ExtStopLoss:0.0;
         double tp=(InpTakeProfit!=0)?m_symbol.Bid()-ExtTakeProfit:0.0;
         OpenSell(sl,tp); // Отправка маркет-ордера на продажу
        }
     }
   return;
  }

前述と同じ状況です。

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

mql5言語の特殊性、ヒントとコツ

fxsaber さん 2018.02.16 19:52

最初のOrderSendの後、成行注文が表示され、その実行前に新しいティックが来たら、まだポジションはなく、2回目のOrderSendが行われます。

PositionTotalの一見良いアイデアは、MT5では成行注文のOrdersTotalも分析する必要があるため、やや影が薄くなっています。

つまり、一般的なケースでは、Expert Advisorは1つのポジションではなく、2つ、3つなどのポジションを開くことになります。ティックの受信頻度や成行注文の約定時間によって異なります。


コドベースのほぼ全てのMT5用EAは、MT5用テンプレートと 同じロジックで書かれているため、含まれているバグも同じです。これは、残念ながらKBのほぼすべてのMT5 EAに当てはまります。

MACD EA
MACD EA
  • 投票: 4
  • 2018.02.15
  • Vladimir Karputov
  • www.mql5.com
При поступлении сигнала противоположная позиция закрывается. Также советник может закрывать половину позиции (параметр Profit for closing half of the position), может переводить позицию в безубыток (параметр Breakeven). Размер открываемой позиции может задавать вручную (параметр Lots) или в процентах риска от свободной маржи (параметр Risk in...
 

ネッティングでは、同じシンボルに対して、同時にオープンポジションと、どちらかの方向の複数の成行注文が存在することがあります。例えば、買いのポジションと買いの注文。確かに、非同期のルールがあちこちにあったので、そういうデモ口座は見つけられませんでした。

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

バグ、バグ、質問

fxsaber さん 2018.02.14 08:58

OnTradeTransaction イベント全体のシーケンスは、OrderSend が完了した後に発生します。

電子ブック

void OnTradeTransaction ( const MqlTradeTransaction &Trans, const MqlTradeRequest&, const MqlTradeResult& )
{ 
  static bool FirstRun = true;  
  static ulong StartTime;
  
  if (FirstRun)
  {
    StartTime = GetMicrosecondCount();
    
    FirstRun = false;
  }

  Print(EnumToString(Trans.type));
  Print((GetMicrosecondCount() - StartTime) / 1000);    
}

取引注文を手動で送信する。

ログ

2018.02.14 09:41:46.671 '8854170': instant sell 1.00 EURUSD at 1.23673
2018.02.14 09:41:46.853 '8854170': accepted instant sell 1.00 EURUSD at 1.23673
2018.02.14 09:41:46.853 '8854170': deal #192088422 sell 1.00 EURUSD at 1.23673 done (based on order #208541700)
2018.02.14 09:41:46.853 '8854170': order #208541700 sell 1.00 / 1.00 EURUSD at 1.23673 done in 190.608 ms


Expert Advisorの結果

2018.02.14 09:41:46.853 TRADE_TRANSACTION_ORDER_ADD
2018.02.14 09:41:46.853 0
2018.02.14 09:41:46.853 TRADE_TRANSACTION_DEAL_ADD
2018.02.14 09:41:46.853 1
2018.02.14 09:41:46.853 TRADE_TRANSACTION_ORDER_DELETE
2018.02.14 09:41:46.853 1
2018.02.14 09:41:46.853 TRADE_TRANSACTION_HISTORY_ADD
2018.02.14 09:41:46.853 2
2018.02.14 09:41:46.853 TRADE_TRANSACTION_REQUEST
2018.02.14 09:41:46.853 2


時間列とEAの数値データから、取引注文の実行時間がOnTradeTransactionイベントのシーケンスに影響を与えない ことが完全にわかります。非同期は地獄に落ちる!ここまでひどいことをやってのけたんだ。1755年製造。

例えば、OrderSendAsyncの成行注文をTerminalで行った場合、成行注文は一瞬たりとも表示されない。おそらく開発者は、少しでもスピードアップを図るために、このような方法をとったのでしょう。

 

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

記事「MetaTrader 5におけるトレード戦略の最適化の可視化」についての考察"

fxsaber さん 2018.02.22 08:39

フレームモードでは、OnInit、OnDeinit、OnTick、OnTrade、OnTradeTransaction、OnTimerは無視されます。OnChartEventのみ動作します。

もちろん、OnChartEvent例外のため、frame-modeフラグのチェックは必須です。

理由: