Diskussion zum Artikel "Statistische Verteilungen in MQL5 - Nur das Beste aus R" - Seite 7

 
ivanivan_11:

Ich spreche über R, aber mein Wissen ist veri klein)) kann jemand überprüfen, ob der Code korrekt ist?

Wenn der Code korrekt ist, können Sie den Benchmark überprüfen?

Der Code ist falsch.

Sie haben die Kompilierungszeit der Funktion gemessen, nicht ihre Ausführung:

Die Funktion cmpfun kompiliert den Rumpf einer Closure und gibt eine neue Closure mit denselben Formeln zurück, wobei der Rumpf durch den kompilierten Rumpfausdruck ersetzt wird.


Der Beweis für den Fehler:

> library(microbenchmark)
> library(compiler)
> n <- 2000
> k <- seq(0,n,by=20)
> qqq<- function(xx) { a <- dbinom(k, n, pi/10, log = TRUE) }
> res <- microbenchmark(cmpfun(qqq))
> a
Ошибка: объект 'a' не найден

Wenn die Funktion qqq während des Benchmarks ausgeführt worden wäre, hätte das Objekt a die berechneten Daten erhalten. Stattdessen stellte sich aber heraus, dass das Objekt gar nicht erstellt wurde.

Folglich zählte der Benchmark die Kompilierungszeit statt der Ausführungszeit. In meinem Code ist alles korrekt - der Benchmark zählt die tatsächliche Ausführungszeit und Objekt a wird mit den richtigen Daten erstellt.


Und ja, die Kompilierung ist ein ziemlich aufwendiger Prozess: Sie wird in Millisekunden statt in Mikrosekunden angegeben.

> print(res)
Unit: milliseconds
        expr      min       lq     mean   median       uq      max neval
 cmpfun(qqq) 1.741577 1.783867 1.856366 1.812613 1.853096 2.697548   100
 

Und ein weiterer Witz ist, dass Sie in Ihrem Beispiel die Systemfunktion q() - quit - außer Kraft gesetzt haben.

Es gab keine Möglichkeit, R zu beenden :)

 
Dr.Trader:

Ich meine, dass der mql-Compiler alle Eingabeparameter bereits zur Kompilierungszeit kennt. Es reicht aus, wenn er alles während der Kompilierung berechnet, und wenn er das Skript aufruft, gibt er einfach das vorberechnete Ergebnis zurück. Ich habe einige Artikel im Hub gesehen, in denen C++-Compiler verglichen wurden, und nach der Analyse des Assembler-Codes zu urteilen, passiert dort genau das.

Ja, er könnte es aktiv nutzen. Hier sind einige Beispiele: https://www.mql5.com/ru/forum/58241.

Aber in diesem Fall wird es nicht funktionieren - Sie müssen wegen der Komplexität, der Schleifen- und Array-Füllung vollständig zählen.

 
ivanivan_11:

wenn der Code korrekt ist, können Sie den Benchmark überprüfen?

Sie müssen res <- microbenchmark(cmpfun ( q)) mit res <- microbenchmark(q())) ersetzen . Aber zuvor kompilierte Bibliotheken werden nicht in Bytecode umkompiliert, ich habe die gleichen Ergebnisse erhalten.

Renat Fatkhullin:
qqq<- function(xx) { a <- dbinom(k, n, pi/10, log = TRUE) }

"a" wird in diesem Fall eine lokale Variable sein, auf die außerhalb der Funktion selbst sowieso nicht zugegriffen werden kann. Aber man kann es auch so machen -
a <<- dbinom(k, n, pi/10, log = TRUE)
dann wird es eine globale Variable sein.

Renat Fatkhullin:

Aber in diesem Fall wird es nicht funktionieren - man muss wegen der Komplexität, der Schleife und dem Füllen des Arrays vollständig zählen.

Verstehe, die Ausführungsgeschwindigkeit ist also ausgezeichnet

 

Übrigens kostet es praktisch nichts, den primitiven Aufruf a <- dbinom(k, n, pi/10, log = TRUE) mit einem direkten Fall in den R-Kernel mit nativer Ausführung zu interpretieren(dbinom ist in r.dll).

Der Versuch, diesen Aufruf zu kompilieren, ist also offensichtlich sinnlos.

 

Da ich schon oft über die Schnelligkeit von R geschrieben habe, möchte ich meine fünf Cent dazugeben.

Lieber Renat!

Dein Beispiel ist überhaupt nichtssagend!

Du hast zwei ähnliche Funktionen genommen und daraus einen Rückschluss auf die Leistungsfähigkeit von R gezogen.

Die Funktionen, die du genannt hast, repräsentieren überhaupt nicht die Leistungsfähigkeit und Vielfalt von R.

Sie sollten rechenintensive Operationen vergleichen.

Zum Beispiel die Matrixmultiplikation...

Lassen Sie uns den Ausdruck in R messen

c <- a*b,

wobei a und b Matrizen mit einer Größe von mindestens 100*100 sind. Stellen Sie in Ihrem Code sicher, dass R die MKL von Intel verwendet. Dazu müssen Sie lediglich die entsprechende Version von R installieren.

Wenn wir uns R ansehen, gibt es Berge von Code, der rechenintensive Operationen enthält. Um diese auszuführen, werden Bibliotheken verwendet, die im Moment die effizientesten sind.

Und der Nutzen von R für den Handel liegt nicht in den Funktionen, die Sie umgeschrieben haben (obwohl sie auch notwendig sind), sondern in den Modellen. In einer meiner Antworten an Sie habe ich das Caret-Paket erwähnt. Sehen Sie, was es ist.... Die Implementierung jedes praktisch nützlichen Handelsmodells im Rahmen dieses Pakets und auf µl wird Ihnen die Antwort geben

Außerdem sollten Sie nicht vergessen, dass das Laden aller Kerne eines Comps eine Routine für R ist. Darüber hinaus können Sie benachbarte Comps im lokalen Netzwerk laden.

PS.

Die Idee, die Leistung von MKL und R zu vergleichen, halte ich für fragwürdig: Diese beiden Systeme haben völlig unterschiedliche Themenbereiche

 

SanSanych, wir werden alles testen und einen Benchmark veröffentlichen. Aber zuerst werden wir die Funktionalität vervollständigen.

Der Test war gerechtfertigt und hat das Problem sofort aufgedeckt. Ich habe die theoretische Begründung dargelegt und bin sicher, dass der System-Overhead von R bei der überwältigenden Menge an Funktionalität erhalten bleibt.

Wir können die Matrizen so multiplizieren, dass Intel verlieren wird. Das ist längst keine Raketenwissenschaft mehr, und Intel (oder besser gesagt, solche Drittprogrammierer innerhalb der Firmenzugehörigkeit) ist kein Meister im mythischen Wissen über seine Prozessoren.

[Gelöscht]  
СанСаныч Фоменко:

Da ich schon oft über die Schnelligkeit von R geschrieben habe, möchte ich meine fünf Cent dazugeben.

.................

An San-Sanych und die anderen Jungs.

San-Sanych, du weißt, wie sehr ich dich respektiere ... ((S) Kataev und Feinzilberg, bekannt als "Ilf und Petrov"), trotz einiger Ihrer post-sowjetischen Witze hier.

Lassen Sie mich etwas Wichtiges für Sie klarstellen:

1). Die Hauptaufgabe eines Programmierers ist nicht das Schreiben von Programmen, sondern das LESEN von Programmen, insbesondere von seinen eigenen. Jeder Programmierer 95...99% seiner Zeit sitzt er da und starrt auf den Monitor. Schreibt er ein Programm? Nein, er liest es meistens. Je näher das, was er auf dem Bildschirm liest, an der natürlichen Sprache ist, d.h. an dem, was ihm von seiner Mutter, seinem Vater, seiner Großmutter, seinem Lehrer beigebracht wurde, desto effizienter wird er diese sprachlichen Krakozebras auf dem Bildschirm entschlüsseln und die Entsprechung zwischen dem Algorithmus und seinem Programm finden.

2). Für die Zwecke von Punkt (1) gibt es im Durchschnitt nichts Besseres als die Sprache C. Deshalb habe ich persönlich (sowie 2-3 verantwortliche und weniger verantwortliche Leute) es zum Beispiel geschafft, ein Projekt mit 700+ Unterprogrammen in C, MQL4, CUDA..... zu schreiben. Und alles funktioniert.

3). Aus der Sicht von Punkt (1) ist die objektorientierte Variante von C, d.h. C++, viel schlechter. (Aber dazu ein andermal mehr).

4). Die volle Kompatibilität von klassischem C und MQL4 ist einfach unbezahlbar. Die Übertragung einer Prozedur hin und her dauert eine halbe Minute.

5). Der Hauptvorteil von C+MQL4 ist die KLARHEIT. Das heißt, die Verständlichkeit und Transparenz von allem, was sich auf dem Bildschirm des Programmierers befindet.

Wenn wir C-MQL4 mit Ihrem R vergleichen, sollten wir nicht auf die Geschwindigkeit und den Umfang des geschriebenen Codes achten, sondern auf die KLARHEIT des Textes. Das heißt, seine Verständlichkeit. Andernfalls wird der Programmierer 24 Stunden lang auf den Bildschirm starren und vergeblich versuchen zu verstehen, was das Programm tut, welche Parameter es hat, warum der Autor sie so benannt hat und ganz allgemein, warum der Programmierer es so und nicht anders gemacht hat. Es ist nicht die Geschwindigkeit des Programms, die hier wichtig ist, sondern die Korrektheit seiner Arbeit und die Geschwindigkeit seiner ANWENDBARKEIT für den Endprogrammierer.

Unter diesem Gesichtspunkt ist das, was Metaquotes getan hat, natürlich eine großartige Unterstützung für diejenigen, die Statistiken in ihre EAs einfügen wollen. Es gibt nichts Vergleichbares in Bezug auf die Einfachheit und Verständlichkeit der Funktionen. Und das ist wichtig. Vor allem, wenn Sie heikle Berechnungen haben (und Forex und der Handel im Allgemeinen erfordern heikle Berechnungen).

Lassen Sie uns vergleichen.

Hier sehen Sie, wie die Integrationsfunktion in C - MQL4 aussieht:

//__________________________________________________________________
//|
// Integral_Simpson_3_Punkte_Lite ()|
//_______________________________________________________|
#define  FACTOR_1_3      (1.0 / 3.0)

double Integral_Simpson_3_Points_Lite
(
   double       & Price_Array[],
   int          Period_Param,
   int          Last_Bar
)
{
        double  Sum, Sum_Full_Cycles, Sum_Tail, Sum_Total;
        int             i, j;
        int             Quant;
        int             Full_Cycles;
        int             Tail_Limit;
        int             Tail_Start;

        //..................................................................
        if (Last_Bar < 0)
        {
                Last_Bar = 0;
        }
        //.........................................
        if (Period_Param <= 1)
        {
                return (0.0);
        }
        //.................................................................
        if (Period_Param == 2)
        {
                return (0.5 * (Price_Array[Last_Bar] + Price_Array[Last_Bar + 1]));
        }
        //=============================================================================================
        //=============================================================================================
        Quant = 3;
        Full_Cycles = (Period_Param - 1) / (Quant - 1);
        Tail_Start = Full_Cycles * (Quant - 1);
        Tail_Limit = Period_Param - Tail_Start;
        //...........................................................
        j = Last_Bar;

        Sum = 0.0;
        for (i = 0; i < Full_Cycles; i ++)
        {
                //.........................................................................
                Sum += Price_Array[j];
                Sum += 4.0 * Price_Array[j + 1];
                Sum += Price_Array[j + 2];
                j = j + (Quant - 1);
        }
        //...........................................................
        Sum_Full_Cycles = Sum * FACTOR_1_3;
        Sum_Tail = Integral_Trapezoid_Lite (Price_Array,
                                            Tail_Limit,
                                            Last_Bar + Tail_Start);
        //.........................................................................
        Sum_Total = Sum_Full_Cycles + Sum_Tail;
        //...............................................................
        return (Sum_Total) ;

}
[Gelöscht]  

Ich schreibe in Teilen, so ist es einfacher zu schreiben.

Es ist eine trapezförmige Integrationsfunktion enthalten:

//__________________________________________________________________
//|
// Integral_Trapezoid_Lite ()|
//_______________________________________________________|
double Integral_Trapezoid_Lite
(
   double       & Price_Array[],
   int          Period_Param,
   int          Last_Bar
)
{
        double  Sum;
        int             i;
        int             Price_Index ;
        //.........................................
        if (Last_Bar < 0)
        {
                Last_Bar = 0;
        }
        //.........................................
        if (Period_Param <= 1)
        {
                return (0.0);
        }
        //.................................................................
        if (Period_Param == 2)
        {
                return (0.5 * (Price_Array[Last_Bar] + Price_Array[Last_Bar + 1]));
        }
        //..................................................................
        //..................................................................
        Sum = 0.0;
        for (i = 0; i < Period_Param; i++)
        {
                Price_Index = Last_Bar + i;
                if (Price_Index < 0)
                {
                        break;
                }
                //........................................
                if ((i == 0) || (i == (Period_Param - 1)))
                {
                        Sum = Sum + Price_Array[i] * 0.5;
                }
                else
                {
                        Sum = Sum + Price_Array[i];
                }
        }
        //...............................................................
        return (Sum) ;
}
[Gelöscht]  

Alles ist absolut klar und verständlich. Und was wichtig ist, es funktioniert immer und funktioniert gut, d.h. mit geringen Fehlern auch in MT4-MQL4, was eine Menge Zeit spart.

Aber wenn Sie herausfinden wollen, warum Sie unverständliche Fehler haben, wenn Sie in R arbeiten, oder wenn Sie einfach nur verstehen wollen, welche Parameter es in der Integrationsprozedur gibt oder welche Integrationsmethode sie dort programmiert haben, dann sehen Sie folgendes (Gott verzeihe mir, dass ich das für unreife Programmierkinder poste):

http://www.netlib.org/quadpack/

Dies ist nur der Titel der ursprünglich in Fortran geschriebenen Funktion. Der eigentliche Text wird später folgen. Dies ist das Originalprogramm, das im R-Paket für die Integration verwendet wird.

Was gibt es hier zu verstehen, sagen Sie es mir?

      subroutine qagse(f,a,b,epsabs,epsrel,limit,result,abserr,neval,
     *   ier,alist,blist,rlist,elist,iord,last)
c***begin prologue  qagse
c***date written   800101   (yymmdd)
c***revision date  830518   (yymmdd)
c***category no.  h2a1a1
c***keywords  automatic integrator, general-purpose,
c             (end point) singularities, extrapolation,
c             globally adaptive
c***author  piessens,robert,appl. math. & progr. div. - k.u.leuven
c           de doncker,elise,appl. math. & progr. div. - k.u.leuven
c***purpose  the routine calculates an approximation result to a given
c            definite integral i = integral of f over (a,b),
c            hopefully satisfying following claim for accuracy
c            abs(i-result).le.max(epsabs,epsrel*abs(i)).
c***description
c
c        computation of a definite integral
c        standard fortran subroutine
c        real version
c
c        parameters
c         on entry
c            f      - real
c                     function subprogram defining the integrand
c                     function f(x). the actual name for f needs to be
c                     declared e x t e r n a l in the driver program.
c
c            a      - real
c                     lower limit of integration
c
c            b      - real
c                     upper limit of integration
c
c            epsabs - real
c                     absolute accuracy requested
c            epsrel - real
c                     relative accuracy requested
c                     if  epsabs.le.0
c                     and epsrel.lt.max(50*rel.mach.acc.,0.5 d-28),
c                     the routine will end with ier = 6.
c
c            limit  - integer
c                     gives an upperbound on the number of subintervals
c                     in the partition of (a,b)
c
c         on return
c            result - real
c                     approximation to the integral
c
c            abserr - real
c                     estimate of the modulus of the absolute error,
c                     which should equal or exceed abs(i-result)
c
c            neval  - integer
c                     number of integrand evaluations
c
c            ier    - integer
c                     ier = 0 normal and reliable termination of the
c                             routine. it is assumed that the requested
c                             accuracy has been achieved.
c                     ier.gt.0 abnormal termination of the routine
c                             the estimates for integral and error are
c                             less reliable. it is assumed that the
c                             requested accuracy has not been achieved.
c            error messages
c                         = 1 maximum number of subdivisions allowed
c                             has been achieved. one can allow more sub-
c                             divisions by increasing the value of limit
c                             (and taking the according dimension
c                             adjustments into account). however, if
c                             this yields no improvement it is advised
c                             to analyze the integrand in order to
c                             determine the integration difficulties. if
c                             the position of a local difficulty can be
c                             determined (e.g. singularity,
c                             discontinuity within the interval) one
c                             will probably gain from splitting up the
c                             interval at this point and calling the
c                             integrator on the subranges. if possible,
c                             an appropriate special-purpose integrator
c                             should be used, which is designed for
c                             handling the type of difficulty involved.
c                         = 2 the occurrence of roundoff error is detec-
c                             ted, which prevents the requested
c                             tolerance from being achieved.
c                             the error may be under-estimated.
c                         = 3 extremely bad integrand behaviour
c                             occurs at some points of the integration
c                             interval.
c                         = 4 the algorithm does not converge.
c                             roundoff error is detected in the
c                             extrapolation table.
c                             it is presumed that the requested
c                             tolerance cannot be achieved, and that the
c                             returned result is the best which can be
c                             obtained.
c                         = 5 the integral is probably divergent, or
c                             slowly convergent. it must be noted that
c                             divergence can occur with any other value
c                             of ier.
c                         = 6 the input is invalid, because
c                             epsabs.le.0 and
c                             epsrel.lt.max(50*rel.mach.acc.,0.5 d-28).
c                             result, abserr, neval, last, rlist(1),
c                             iord(1) and elist(1) are set to zero.
c                             alist(1) and blist(1) are set to a and b
c                             respectively.
c
c            alist  - real
c                     vector of dimension at least limit, the first
c                      last  elements of which are the left end points
c                     of the subintervals in the partition of the
c                     given integration range (a,b)
c
c            blist  - real
c                     vector of dimension at least limit, the first
c                      last  elements of which are the right end points
c                     of the subintervals in the partition of the given
c                     integration range (a,b)
c
c            rlist  - real
c                     vector of dimension at least limit, the first
c                      last  elements of which are the integral
c                     approximations on the subintervals
c
c            elist  - real
c                     vector of dimension at least limit, the first
c                      last  elements of which are the moduli of the
c                     absolute error estimates on the subintervals
c
c            iord   - integer
c                     vector of dimension at least limit, the first k
c                     elements of which are pointers to the
c                     error estimates over the subintervals,
c                     such that elist(iord(1)), ..., elist(iord(k))
c                     form a decreasing sequence, with k = last
c                     if last.le.(limit/2+2), and k = limit+1-last
c                     otherwise
c
c            last   - integer
c                     number of subintervals actually produced in the
c                     subdivision process
c
c***references  (none)
c***routines called  qelg,qk21,qpsrt,r1mach
c***end prologue  qagse
c
      real a,abseps,abserr,alist,area,area1,area12,area2,a1,
     *  a2,b,blist,b1,b2,correc,defabs,defab1,defab2,r1mach,
     *  dres,elist,epmach,epsabs,epsrel,erlarg,erlast,errbnd,
     *  errmax,error1,error2,erro12,errsum,ertest,f,oflow,resabs,
     *  reseps,result,res3la,rlist,rlist2,small,uflow
      integer id,ier,ierro,iord,iroff1,iroff2,iroff3,jupbnd,k,ksgn,
     *  ktmin,last,limit,maxerr,neval,nres,nrmax,numrl2
      logical extrap,noext
c
      dimension alist(limit),blist(limit),elist(limit),iord(limit),
     * res3la(3),rlist(limit),rlist2(52)
c
      external f
c
c            the dimension of rlist2 is determined by the value of
c            limexp in subroutine qelg (rlist2 should be of dimension
c            (limexp+2) at least).
c
c            list of major variables
c            -----------------------
c
c           alist     - list of left end points of all subintervals
c                       considered up to now
c           blist     - list of right end points of all subintervals
c                       considered up to now
c           rlist(i)  - approximation to the integral over
c                       (alist(i),blist(i))
c           rlist2    - array of dimension at least limexp+2
c                       containing the part of the epsilon table
c                       which is still needed for further computations
c           elist(i)  - error estimate applying to rlist(i)
c           maxerr    - pointer to the interval with largest error
c                       estimate
c           errmax    - elist(maxerr)
c           erlast    - error on the interval currently subdivided
c                       (before that subdivision has taken place)
c           area      - sum of the integrals over the subintervals
c           errsum    - sum of the errors over the subintervals
c           errbnd    - requested accuracy max(epsabs,epsrel*
c                       abs(result))
c           *****1    - variable for the left interval
c           *****2    - variable for the right interval
c           last      - index for subdivision
c           nres      - number of calls to the extrapolation routine
c           numrl2    - number of elements currently in rlist2. if an
c                       appropriate approximation to the compounded
c                       integral has been obtained it is put in
c                       rlist2(numrl2) after numrl2 has been increased
c                       by one.
c           small     - length of the smallest interval considered
c                       up to now, multiplied by 1.5
c           erlarg    - sum of the errors over the intervals larger
c                       than the smallest interval considered up to now
c           extrap    - logical variable denoting that the routine
c                       is attempting to perform extrapolation
c                       i.e. before subdividing the smallest interval
c                       we try to decrease the value of erlarg.
c           noext     - logical variable denoting that extrapolation
c                       is no longer allowed (true value)
c
c            machine dependent constants
c            ---------------------------
c
c           epmach is the largest relative spacing.
c           uflow is the smallest positive magnitude.
c           oflow is the largest positive magnitude.
c
c***first executable statement  qagse
      epmach = r1mach(4)
c
c            test on validity of parameters
c            ------------------------------