ライブラリ: TesterBenchmark - ページ 2

 

アイデアは良いのですが、実装が正しくありません。プライベートメッセージで回答

fxsaber

こんにちは!

トレーディング・ロジックをあなたのトレーディング・ライブラリに適応させて、そのパフォーマンスを測定することは可能でしょうか?

取引、自動取引システム、取引戦略のテストに関するフォーラム。

ライブラリ: TesterBenchmark

fxsaber, 2017.08.15 19:31

順位は以下のように分布しました。

  1. Pure MQL5 - 100% のパフォーマンス。
  2. MT4Orders.mqh - ~95%のパフォーマンス。
  3. SB TradeTrade.mqh - ~84%のパフォーマンス。
SBの遅れが少なくなってきた。


ZЫ 他の取引ライブラリはどれくらいなんだろう...。

ありがとう!

何のパフォーマンスか理解できない。ライブラリ?ストラテジーがないと動かない。ストラテジーが必要です。そして、ライブラリーの助けを借りて書かれた戦略のパフォーマンスを測定する必要がある。測定して結果が出たとしよう。何と比較すればいいのだろう?純粋なMQLで書かれた同じストラテジーと比較する必要がある。2つのストラテジーをどこで手に入れるか?そのような2つのストラテジーがあるとしよう。しかし、その2つのストラテジーが互いにエントリー/エグジットが同じであるという保証はどこにあるのだろうか?互いに同一であることが保証された2つのストラテジーがあると仮定して、その速度を測定してみよう。速度はわずかな差しかない。これはエンジンが効率的であることを意味するのだろうか?ストラテジーはエンジン/MQLの能力をすべて使っているわけではない。突然、別のストラテジーで相場の長い履歴をリクエストすると、エンジンは何倍も遅く動き始めることがわかった。これは、エンジンの動作が純粋なMQLの何倍も遅いことを意味するのでしょうか?いいえ、この特定の操作が遅いという意味ではありません。しかし、データを提供するクラスを最適化すれば、新しいバージョンでは、同じ操作でエンジンがシステムCopyXXXよりも速く動作することが判明するでしょう。だから、この話全体では、主なことがはっきりしないのだ: 私たちが何であり、何と比較しているのか.

 
Vasiliy Sokolov:

アイデアは良いのですが、実装が正しくありません。プライベートメッセージで回答しました:

これがテストEAのコード です。

同じシンプルな取引ロジックが含まれていますが、純粋なMQL5、Trade.mqh、MT4Orders.mqhの3つの方法があります。

このため、まったく同じ取引結果で各バリアントのパフォーマンスを測定することが可能です。

これまでのところ、Trade.mqhは15%遅れていることが判明しています。しかし、パフォーマンス測定アプローチは普遍的で、どの取引APIでも取引ロジックを繰り返すことができます。ここでは、クロスプラットフォームのバイブルに書いて、純粋なMQL5と比較して速度を測定することをお勧めする。

このような計測のおかげで、私は自分のバイブルのボトルネックを見つけ、それを根絶することができた。また、最適化することで、時間短縮につながることもある。一般的に、これは有用だと思います。


あなたのアドバイザーは
#include <TesterBenchmark.mqh>

それ以外は必要ない。そして最適化を選択して実行する。ログにパフォーマンスが表示されます。

 

テスト用Expert Advisorのコードでは、各ティックで、履歴上の取引の完全な検索が行われ、それらの合計ロットと利益が考慮され、現在の取引のボリュームが計算されます:

if (HistorySelect(0, TimeCurrent()))
    {
      const int Total = HistoryDealsTotal() - 1;
      double SumProfit = 0;
      double SumLots = 0;
      for (int i = Total, Count = 0; (i >= 0) && (Count < AmountLastDeals); i--)
      {
        const ulong Ticket = HistoryDealGetTicket(i);

        if ((ENUM_DEAL_ENTRY)HistoryDealGetInteger(Ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT)
        {
          SumProfit += HistoryDealGetDouble(Ticket, DEAL_PROFIT) * (AmountLastDeals - Count);
          SumLots += HistoryDealGetDouble(Ticket, DEAL_VOLUME) * (AmountLastDeals - Count);

          Count++;
        }
      }
      SumLots /= (AmountLastDeals * (1 + AmountLastDeals)) >> 1;
      ...
   }

あなたのExpert Advisorは、HistorySelectにロードするだけです。したがって、HistorySelect 自身以外のパフォーマンスを測定するベンチマークにはなりえません。したがって、私が引用したあなたの発言は「MT5はMT4より4.4倍速い!」 少なくとも、MT5のHistorySelectはMT4の同様の内部手順より4.4倍速いと訂正すべきです。

私のエンジンであるCStrategyに関しては、現在、トレードを扱うことはまったくできず、ポジションを扱うことしかできないので、現在書かれている例はCStrategyでは使用できません。

追伸:あなたの例では、作業速度はO(n)に等しいことに注意してください。そして、この場合のMT4とMT5の違いは、HistorySelect/HistoryOrderSelectの速度だけです。当然ながら、複雑さO(n)のタスクにおけるCStrategyは基本的な呼び出し、この場合はHistorySelectを使用し、当然ながらHistorySelectを直接呼び出すよりも少し遅くなります。しかし、例えばHistoryOrderSelect(ticket)を呼び出す必要がある場合、ここではすべてがもっと面白くなり、CStrategyは、辞書によるアクセスやプログラムのメモリへのデータ格納のために、環境に対する標準的なアクセスを壊してしまうタスクもあります。

 
Vasiliy Sokolov:

テスト用Expert Advisorのコードでは、各ティックで、履歴上の取引の完全な検索が行われ、それらの合計ロットと利益が考慮され、現在の取引のボリュームが計算されます:

あなたのExpert Advisorは、HistorySelectにロードするだけです。したがって、HistorySelect 自身以外のパフォーマンスを測定するベンチマークにはなりえません。したがって、私が引用したあなたの発言は「MT5はMT4より4.4倍速い!」 少なくとも、MT5のHistorySelectはMT4の同様の内部手順より4.4倍速いと訂正すべきです。

結論を急ぎすぎです。指定されたピースは、インターバル秒ごとに1回、ポジションをオープンするときにのみ実行されます。つまり、非常にまれです。

私のCStrategyエンジンに関しては、現在のところ、トレードを操作することはできませんが、ポジションを操作することはできます。

以下はOnTickテストEAのMQL4コードですが、これもポジションでのみ動作します。

if (!OrderSelect(0, SELECT_BY_POS))
{
  const int Total = OrdersHistoryTotal() - 1;

  double SumProfit = 0;
  double SumLots = 0;

  for (int i = Total, Count = 0; (i >= 0) && (Count < AmountLastDeals); i--)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && (OrderType() <= OP_SELL))
    {
      SumProfit += OrderProfit() * (AmountLastDeals - Count);
      SumLots += OrderLots() * (AmountLastDeals - Count);

      Count++;
    }

  SumLots /= (AmountLastDeals * (1 + AmountLastDeals)) >> 1;

  const int Type = (Total >= 0) && OrderSelect(Total, SELECT_BY_POS, MODE_HISTORY) && (OrderType() == OP_BUY) ? OP_SELL : OP_BUY;

  OrderSend(_Symbol, Type, (SumProfit >= 0) ? Lots : CorrectLot(SumLots),
            SymbolInfoDouble(_Symbol, (Type == OP_BUY) ? SYMBOL_ASK : SYMBOL_BID), 0, 0, 0); // , null, 0, 0, 0, int_min);
}
else if (TimeCurrent() - OrderOpenTime() >= Interval)
  OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0);

もちろん、このような単純なロジックをAPI上で書き換えることは難しくありません。しかし、もし取引APIのパフォーマンスを分析するためのより良いEAの提案があれば(時系列などではなく、取引だけです)、あなたのバージョンの取引ロジックを喜んで拝見します。私はすぐに純粋なMQL5、MQL4、Trade.mqh用に書き直すことができます。


ZY テスト・アドバイザーを開始する際、バランス = 1e7 を選択します。常にポジションを建てるのに十分な資金を持つためです。

 
fxsaber:

あなたは結論を急ぎすぎた。指定された曲は、インターバル秒に一度だけ、ポジション・オープニングで実行される。つまり、非常に稀です。

これはテスト用Expert AdvisorのOnTickのMQL4コードです。

もちろん、このような単純なロジックをAPI上で書き換えることは難しくありません。しかし、もし取引APIのパフォーマンスを分析するためのより良いEAの提案があれば(時系列などではなく、取引のみ)、あなたのバージョンの取引ロジックを喜んで拝見します。純粋なMQL5、MQL4、Trade.mqh用にすぐに書き換えることができます。

あなたのコードをよく見て、何を測定しているのか教えてください。

if (!OrderSelect(0, SELECT_BY_POS))
{
  const int Total = OrdersHistoryTotal() - 1;

  double SumProfit = 0;
  double SumLots = 0;

  for (int i = Total, Count = 0; (i >= 0) && (Count < AmountLastDeals); i--)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && (OrderType() <= OP_SELL))
    {
      SumProfit += OrderProfit() * (AmountLastDeals - Count);
      SumLots += OrderLots() * (AmountLastDeals - Count);

      Count++;
    }

  SumLots /= (AmountLastDeals * (1 + AmountLastDeals)) >> 1;

  const int Type = (Total >= 0) && OrderSelect(Total, SELECT_BY_POS, MODE_HISTORY) && (OrderType() == OP_BUY) ? OP_SELL : OP_BUY;

  OrderSend(_Symbol, Type, (SumProfit >= 0) ? Lots : CorrectLot(SumLots),
            SymbolInfoDouble(_Symbol, (Type == OP_BUY) ? SYMBOL_ASK : SYMBOL_BID), 0, 0, 0); // , null, 0, 0, 0, int_min);
}
else if (TimeCurrent() - OrderOpenTime() >= Interval)
  OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0);

ここには2つのボトルネックがあります:forループと注文送信 そのものです。forループのどちらが速く動作するかを比較したいですか?CTradeか純粋なMQLか?注文送信はどこが速いですか?CTradeかOrderSendか?CTradeでは注文を送信する前に多くのチェックが行われるため、もちろん純粋なOrderSendの方が高速です。しかし、ここからどのような結論が導かれるでしょうか?

 
Vasiliy Sokolov:

あなたのコードをよく見て、何を測定しているか教えてください。

ここには2つのボトルネックがあります:forループと実際の注文送信です。forループのどこが速く動作するかを比較したいですか?

なぜかあなたはそれを見ていない

fxsaber:

指定されたピースは、インターバル秒に一度、ポジションをオープンするときにのみ実行されます。つまり、非常にまれです。


Vasiliy Sokolov:

注文はどこで送信するのが速いですか?CTradeですか、それともOrderSendですか?もちろん、純粋なOrderSendの方が速いです。なぜなら、CTradeでは注文が送信される前に多くのチェックが行われるからです。しかし、これにはどのような意味があるのでしょうか?

CTradeでは、同じMT4Ordersよりもはるかに少ないチェックしか行われません。SBは純粋なMQL5より16%遅れており、絶対的に正確に加速することができます。そして、CTradeを使用する 人は、最適化中にクラウドで余分な資金を失い、最適化そのものに時間を費やすことになります。

 

あなたはまだ自分のコードが何をしているのか理解していない。私はわざとプロファイラを実行し、1時間以内に1秒間隔で1800回の取引を行いました。 99,66% OnTickの実行時間の99,66%が2つのOrderSend関数で占められて います

何を最適化するつもりですか?残りの0.34%は無意味です。OrderSendを最適化することはできません。

なるほど。最も興味深い部分だ。include<TradeTrade.mqh>を入れて、CTradeライブラリを使ったときに何が変わったか見てみよう:


Trade.Buy/SellとTrade.PositionCloseを呼び出すのに100%の時間がかかるようになりました。Trade.PositionCloseに行くと、ジャジャジャーン:

すなわち、Trade.PositionCloseは99.97%の時間、同じOrderSendを取ります。Trade.BuyとTrade.Sellも同様です。

では、SBで何を最適化するのか?テスト対象はどこですか?一般的に何をテストしているのか?

(プログラムの実行時間の99.97%はOrderSendによる直接の注文送信にかかり、残りの0.03%は注文送信前に必要なチェックを行うCTradeバインディングにかかります。つまり、有能なOOPを使用することで、無視できるほどごくわずかな遅延が生じます。なぜなら、この0.03%の時間のほとんどは、手続きコードであろうと他のどこかであろうと、適切な方法で実装されるべき必須のチェックに費やされるからです。)

 
Vasiliy Sokolov:

具体的にプロファイラーを動かしてみると、1時間以内に1秒間隔で1,800回の取引がありました。

オンラインと何か関係があるのですか?テスターについてです。

 
Andrey Khatimlianskii:

オンラインと何の関係が?それはテスターについてです。

MT5とそのストラテジーテスターについて話して いるのであれば、同じ99%の時間(まあ、もう少し少ないかもしれませんが)が取引環境の再現に費やされています(それゆえ、MT4に比べて動作が遅いのです)。そして、実生活でOrderSendに99.9%の時間がかかるのであれば、ストラテジーテスターでは突然2桁速く動作すると考える理由はない。
 
Vasiliy Sokolov:
MT5とそのストラテジーテスターについて話して いるのであれば、同じ99%の時間(まあ、もう少し少ないかもしれませんが)が取引環境の再現に費やされています(それゆえ、MT4に比べて動作が遅いのです)。そして、実生活でOrderSendに99.9%の時間がかかっても、ストラテジーテスターで突然2桁速く動くと考える理由はない。

Vasily、あなたはテスターとリアルタイムのOrderSendの実行速度の比較可能性について真剣に話しているのですか?

オンラインではサーバーに情報を送信して応答を待つので最も遅いですが、テスターでは(遅延を含めなければですが、問題外でした)即座に送信して待ちます。

このライブラリーの課題は、テスターの(取引機能面での)速度を測定することである。