Diskussion zum Artikel "Anwendung von OLAP im Handel (Teil 4): Quantitative und visuelle Analyse der Testberichte"

 

Neuer Artikel Anwendung von OLAP im Handel (Teil 4): Quantitative und visuelle Analyse der Testberichte :

Der Artikel bietet grundlegende Werkzeuge für die OLAP-Analyse von Testberichten in Bezug auf einzelne Durchläufe und Optimierungsergebnisse. Das Werkzeug kann mit Dateien im Standardformat (tst und opt) arbeiten und bietet auch eine grafische Schnittstelle. MQL-Quellcodes sind unten angefügt.

Um die allgemeine Verteilung der Gewinne nach Ebenen in Schritten von 100 anzuzeigen, wählen Sie das Feld 'profit' aus der Statistik entlang der X-Achse und den Aggregator 'count'.

Verteilung der Gewinne nach Bereichen in Schritten von 100 Einheiten

Verteilung aller Gewinne nach Bereichen in Schritten von 100 Einheiten

Mit Hilfe des Aggregators 'identity' können wir den Einfluss der Anzahl der gewinnbringenden Geschäfte bewerten. Im Allgemeinen ermöglicht dieser Aggregator die visuelle Bewertung vieler anderer Abhängigkeiten.

Profit vs. number of trades

Profit vs. number of trades

Autor: Stanislav Korotky

 
Das sieht cool aus! Ich werde es ausprobieren. Ich danke dir.
 

Als ich den Code aus dem Artikel analysierte, hatte ich ständig das Gefühl, dass ich nicht in der Lage sein würde, auch nur annähernd ein so hohes Niveau an Fähigkeiten zu erreichen. Leider konnte ich es aufgrund meiner Inkompetenz nicht verstehen.


Ich bitte den Autor, als Beispiel zu zeigen (fertiger Code), wie man diese Funktionalität zu dem vorgestellten Toolkit hinzufügen kann?

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien.

Bibliotheken: SingleTesterCache

fxsaber, 2020.01.14 11:42 AM

  uchar Bytes2[];
  
  if (MTTESTER::GetLastTstCache(Bytes2) != -1) // Wenn es möglich wäre, den letzten Cache-Datensatz eines einzelnen Laufs zu lesen
  {
    const SINGLETESTERCACHE SingleTesterCache(Bytes2); // Fahren Sie es in das entsprechende Objekt.

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Bibliotheken: TesterCache

fxsaber, 2019.11.11 04:45 Uhr.

  uchar Bytes[];
  
  MTTESTER::GetLastOptCache(Bytes);
  
// TESTERCACHE<TestCacheSymbolRecord> Cache; // Symboloptimierung
  TESTERCACHE<ExpTradeSummary> Cache;         // Standardoptimierung

  if (Cache.Load(Bytes)) // Lesen Sie den Optimierungscache.
 
Bitte klären Sie die Frage. SingleTesterCache und TesterCache sind in dem Artikel bereits miteinander verbunden.
 
Stanislav Korotky:
Bitte klären Sie die Frage. SingleTesterCache und TesterCache sind in dem Artikel bereits miteinander verbunden.

Ich möchte EX5 ausführen und es wird automatisch die letzte opt/tst-Datei (die zuletzt ausgeführte entsprechende Aufgabe in Tester) zur Analyse auswählen.

 
fxsaber:

Ich möchte EX5 ausführen, und es soll automatisch die letzte opt/tst-Datei (den zuletzt ausgeführten entsprechenden Auftrag in Tester) zur Analyse auswählen.

Hier ist eine Variante für einen separaten Lauf.

//+------------------------------------------------------------------+
//|TSTcube.mqh |
//|Copyright (c) 2020, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
Online-Analytische Verarbeitung von Handels-Hyperwürfeln //|
//| https://www.mql5.com/de/articles/6602 |
//| https://www.mql5.com/de/articles/6603 |
//| https://www.mql5.com/de/articles/7656 |
//|rev. 5.03.2020 |
//+------------------------------------------------------------------+

#include "ReportCubeBase.mqh"
#include <fxsaber/SingleTesterCache/SingleTesterCache.mqh>
#include <fxsaber/MultiTester/MTTester.mqh>                 // +


class TesterDeal: public Deal
{
  public:
    TesterDeal(const TradeDeal &td)
    {
      time = (datetime)td.time_create + TimeShift;
      price = td.price_open;
      string t = dealType(td.action);
      type = t == "buy" ? +1 : (t == "sell" ? -1 : 0);
      t = dealDir(td.entry);
      direction = 0;
      if(StringFind(t, "in") > -1) ++direction;
      if(StringFind(t, "out") > -1) --direction;
      volume = (double)td.volume;
      profit = td.profit;
      deal = (long)td.deal;
      order = (long)td.order;
      comment = td.comment[];
      symbol = td.symbol[];
      commission = td.commission;
      swap = td.storage;
      
      // Saldo - SingleTesterCache.Deals[i].reserve
    }

    static string dealType(const ENUM_DEAL_TYPE type)
    {
      return type == DEAL_TYPE_BUY ? "buy" : (type == DEAL_TYPE_SELL ? "sell" : "balance");
    }

    static string dealDir(const ENUM_DEAL_ENTRY entry)
    {
      string result = "";
      if(entry == DEAL_ENTRY_IN) result += "in";
      else if(entry == DEAL_ENTRY_OUT || entry == DEAL_ENTRY_OUT_BY) result += "out";
      else if(entry == DEAL_ENTRY_INOUT) result += "in out";
      return result;
    }
};

template<typename T>
class TesterReportAdapter: public BaseReportAdapter<T>
{
  protected:
    SINGLETESTERCACHE *ptrSingleTesterCache;

    virtual bool fillDealsArray() override
    {
      for(int i = 0; i < ArraySize(ptrSingleTesterCache.Deals); i++)
      {
        if(TesterDeal::dealType(ptrSingleTesterCache.Deals[i].action) == "balance")
        {
          balance += ptrSingleTesterCache.Deals[i].profit;
        }
        else
        {
          array << new TesterDeal(ptrSingleTesterCache.Deals[i]);
        }
      }
      return true;
    }

  public:
    ~TesterReportAdapter()
    {
      if(CheckPointer(ptrSingleTesterCache) == POINTER_DYNAMIC) delete ptrSingleTesterCache;
    }

    virtual bool load(const string file) override
    {
      if(StringFind(file, ".tst") > 0)
      {
        BaseReportAdapter<T>::load(file);

        if(CheckPointer(ptrSingleTesterCache) == POINTER_DYNAMIC) delete ptrSingleTesterCache;

        bool loaded = true;                                                // +
        ptrSingleTesterCache = new SINGLETESTERCACHE();
        if(file == "*.tst")                                                // +
        {                                                                  // +
          uchar Bytes2[];                                                  // +
          // Warum ist MTTESTER::GetLastTstCacheFileName() privat? // +
          // Print("Loading ", MTTESTER::GetLastTstCacheFileName()); // +
          if(MTTESTER::GetLastTstCache(Bytes2) != -1)                      // +
          {                                                                // +
            loaded = ptrSingleTesterCache.Load(Bytes2);                    // +
          }                                                                // +
        }
        else
        {
          loaded = ptrSingleTesterCache.Load(file);                        // *
        }
        
        if(!loaded)                                                        // *
        {
          delete ptrSingleTesterCache;
          ptrSingleTesterCache = NULL;
          return false;
        }
        size = generate();
        
        Print("Tester cache import: ", size, " trades from ", ArraySize(ptrSingleTesterCache.Deals), " deals");
      }
      return true;
    }
};

TesterReportAdapter<RECORD_CLASS> _defaultTSTReportAdapter;

Ich wollte den Namen der letzten tst-Datei in das Protokoll ausgeben, aber die entsprechende Methode ist privat.

In den Einstellungen sollte man die Datei "*.tst" auswählen (ein leerer Name startet trotzdem die Analyse der Online-Kontohistorie).

Dateien:
TSTCube.mqh  5 kb
 

Für die Ergebnisse der Optimierung:

#include <fxsaber/MultiTester/MTTester.mqh>                 // +

...

template<typename T>
class OptCacheDataAdapter: public DataAdapter
{
  private:
    TESTERCACHE<ExpTradeSummary> Cache;
    ...
    
  public:
    OptCacheDataAdapter()
    {
      reset();
    }
    
    void load(const string optName)
    {
      bool loaded = true;                                       // +
      if(optName == "")                                         // +
      {                                                         // +
        uchar Bytes[];                                          // +
        // Warum ist GetLastOptCacheFileName() privat? // +
        // Print("Loading ", MTTESTER::GetLastOptCacheFileName()); // +
        MTTESTER::GetLastOptCache(Bytes);                       // +
        loaded = Cache.Load(Bytes);                             // +
      }
      else
      {
        loaded = Cache.Load(optName);                           // *
      }
      if(loaded)                                                // *
      {
        customize();
        reset();
      }
      else
      {
        cursor = -1;
      }
    }
...
Dateien:
OLAPOpts.mqh  11 kb
 

Der Artikel hat mir gefallen, wie auch alle Artikel über OLAP-Technologie.

Mir persönlich fehlte der Gedankenflug, - philosophische Formulierungen der Essenz, die eine Vorstellung vom gesamten Ansatz geben, - vom abgedeckten Raum der Aufgaben und Potenziale. Und das Potenzial ist riesig. Ich bin traurig über die zahlreichen und unbedeutenden Details, die die Zeit des Lesers verschwenden. Sie sagen - es gibt so eine Variable dort, und es gibt so eine Variable hier..... Mir ist klar, dass dies für Anfänger beim Kopieren von Lösungen notwendig ist, aber dennoch.... Keine Technologie ist statisch, und wenn Ihre Klassen und Methoden jetzt verwendet werden, dann wird in Zukunft jemand alles für sich selbst ändern wollen, und für ihn wird der Nutzen des Artikels im Verhältnis zur Anzahl der privaten Entitäten abnehmen. Schreiben Sie mehr über den Ansatz als Ganzes - über seine Gegenwart und Zukunft. Sie müssen bei solchen Ansätzen globaler sein.

Aber das ist meine subjektive Meinung. Ich danke Ihnen für den Artikel.

 
Stanislav Korotky:

Ich wollte den Namen der letzten tst-Datei im Protokoll ausgeben, aber die entsprechende Methode ist privat.

Mir ist nicht in den Sinn gekommen, dass das jemand brauchen könnte. Wenn Sie weitere Kommentare zu private->public haben, sagen Sie es mir. Wird gemacht.

 

Guten Tag, mein Herr,

Ich habe versucht, die Datei 'OLAPGUI_Opts.mq5' zu kompilieren, aber es gibt 17 Fehler in einigen Include-Dateien.

Mit freundlichen Grüßen,
Ben

 
Szabo Bence #:

Guten Tag, mein Herr,

Ich habe versucht, die Datei "OLAPGUI_Opts.mq5" zu kompilieren, aber es gibt 17 Fehler in einigen Include-Dateien.

Mit freundlichen Grüßen,
Ben

Sie sollten immer die genauen Fehler anzeigen.