Schau, wie man Roboter kostenlos herunterladen kann
Finden Sie uns auf Telegram!
und werden Sie Mitglied unserer Fangruppe
Interessantes Skript?
Veröffentliche einen Link auf das Skript, damit die anderen ihn auch nutzen können
Hat Ihnen das Skript gefallen?
Bewerten Sie es im Terminal MetaTrader 5
Expert Advisors

Die Erzeugung von Fraktalen in MQL5 unter Verwendung der Iterated Function Systems (IFS) (Iterationsfunktionen) - Experte für den MetaTrader 5

Ansichten:
2164
Rating:
(39)
Veröffentlicht:
2016.03.21 11:08
Aktualisiert:
2016.11.22 07:34
\MQL5\Experts\IFS\
ifs_fern.mq5 (2.67 KB) ansehen
\MQL5\Include\
cintbmp.mqh (78.58 KB) ansehen
Benötigen Sie einen Roboter oder Indikator, der auf diesem Code basiert? Bestellen Sie ihn im Freelance-Bereich Zum Freelance

Einleitung

Es gibt viele Programme, die auf Basis der Iterated Function System (IFS) die Erzeugung von selbstähnlichen Fraktal-Sets erlauben . Beispiele hierfür sind Fractint, Fractal Designer oder IFS Matlab Generator. Dank der hohen Geschwindigkeit der MQL5 Sprache und der Möglichkeit mit grafischen Objekten zu arbeiten, können diese schönen Sets im MetaTrader 5 Client Terminal studiert werden.

Die cIntBMP Bibliothek, wurde von Dmitry (Integer) entwickelt und bietet viele neue grafische Möglichkeiten und vereinfacht sehr stark die Erzeugung von grafischen Bildern. Die Bibliothek wurde mit einem speziellen Preis von MetaQuotes Software Corp ausgezeichnet.

In dieser Publikation betrachten wir Beispiele, wie mit dieser Bibliothek cIntBMP gearbeitet werden kann. Darüber hinaus werden wir die Algorithmen für die Erzeugung von Fraktalen Sets mit dem "Iterated Function System" in Verbindung bringen.


1. Affine Transformation einer Fläche

Die affine Transformation einer Fläche ist eine Abbildung . Ganz allgemein kann eine affine 2-D Transformation als Matrix und  Vektoren definiert werden. Der Punkt mit den Koordinaten (x,y) wird mit Hilfe der linearen Transformation zu einem anderen Punkt transformiert:

Die Transformation muss nicht singular sein, die .  Die affine Transformation wechselt die Größe mal.

Die affine Transformation verändert nicht die Struktur von geometrischen Objekten (Linien werden zu Linien transformiert), die AT erlaubt es, einfache Deformationen von Objekten, wie zum Beispiel Rotation Skalierung und Translation zu beschreiben.

Ein Beispiel einer affinen flächentransformation:

1) Rotation of plane on angle:

2) "Skalierung" einer Fläche mit und Koeffizienten (X und Y Achse):

3) Translation Einer Fläche durch  Vektor:

Die Kontraktionszuordnungen sind die Schlüssel (vergleichen Sie mit den Hutchinson Ergebnissen).

Wenn und die Koordinaten haben und und metrisch ist (zum Beispiel, Euclid metrik: ). Die affine Transformation wird Kontraktion genannt. falls , wobei .

Hier ist ein Beispiel einer affinen Transformation:

Das Ergebnis ist:


2. Ähnlichkeits-Transformationen

Die Fraktale werden wie folgt konstruiert: einige (simple) geometrische Objekte (Sektion, Dreieck, Quadrat) Werden in N Stücke geteilt und M von denen werden für die weitere Konstruktion von dem Set verwendet. (Falls N=M ist, bekommen wir die ganzzahligen Dimension aus dem resultierenden Set). Ferner werden für jedes dieser Stücke die Prozesse immer wieder wiederholt.

Klassische Fraktale:

Sektionen:

  • Triadic Koch Curve, N=3, M=4;
  • Cantor Dust, N=3, M=2;

Dreieck:

  • Sierpinski Gasket, N=4, M=3;

Quadrate:

  • Sierpinski Carpet, N=9, M=8;
  • Vichek fractal, N=9, M=5.

Und so weiter.

Die fraktale haben eine selbstähnliche Struktur, einige von ihnen können durch Ähnlichkeitstransformationen definiert werden. Die Struktur der affinen Transformationen hängt von der Konstruktion der Fraktale ab.

Wie Sie nachfolgend sehen können, ist es sehr einfach, und das Einzige Problem, was wir lösen müssen, ist die erste Iteration der fraktalen Konstruktion zu beschreiben und das zugehörige Set von affinen Transformationen zu finden

Angenommen wir haben ein paar Sets. Gemäß der Algorithmen für die Erzeugung von Fraktalen müssen wir sie reduzieren, rotieren und an eine "bestimmte Stelle" setzen. Das Problem ist, mit Hilfe der affinen Transformationen diesen Prozess zu beschreiben. Zum Beispiel müssen wir die Matrix und den Vektor herausfinden.

Es ist leicht zu beweisen, dass es ausreicht, drei Punkte des ursprünglichen Satzes zu nehmen (nontrivial) Und sie im 3 zugehörige Punkte des reduzierten Sets zu transformieren. Diese Transformation führt zu 6 linearen Gleichungen, welche es uns erlauben eine Lösung für a,b,c,d,e,f zu finden.

Lasst es uns ansehen. Angenommen Dreieck wird transformiert zu Dreieck.

Nach dem das Lösen der linearen Gleichungen Sind wir in der Lage die a,b,c,d,e und f Koeffizienten zu ermitteln:

Beispiel:Sierpinski Gasket:

The coordinates of the points are:

  • A (0,0)
  • B (0,1)
  • C (1,1)
  • D(0,1/2)
  • E (1/2,1)
  • F(1/2,1/2)

Wir haben drei Transformationen:

  1. ABC -> ADF
  2. ABC -> DBE
  3. ABC -> FEC

The system of linear equations looks as follows:




Die Lösungen sind: , ,

Wir haben die Koeffizienten der drei affinen Transformationen gefunden. Nachfolgend werden wir diese für die Erzeugung von selbstähnlichen Sets benutzen.


3. Die Erzeugung von Fraktalen unter Verwendung der Iterated Function Systems (IFS) (Iterationsfunktionen)

Das Iterated Function System (IFS) ist ein Set von affinen Kontraktionen wobei - die Gewichtung ist. Jede der IFS-Funktionen wird durch 7 Zahlen definiert: , wobeiGewichtung gebraucht wird wenn der Iterationsprozess die Wahrscheinlichkeit von n-th Transformationen besitzt. Es ist am besten, die Werte proportional zu deren Kontraktion zu definieren: .

Schauen wir uns die Algorithmen für die fraktale Konstruktion unter Verwendung der Iterated Function System an. (sehen Sie auch hier Chaos Game).

Zunächst brauchen wir ein paar Ausgangspunkte mit deren Koordinaten . Als nächstes wählen wir per Zufall einige der Kontraktionen aus und zeichnen den Punkt. . Lassen Sie uns noch mal eine zufällige Kontraktion auswählen Und den Punkt zeichnen . Am Ende haben wir eine Serie von Punkten.

Die Auswahl der Kontraktion hängt von ihrer Wahrscheinlichkeit ab. Wenn wir diesen Prozess wiederholen (zum Beispiel, bis ~30000 Punkte) und die resultierende Serie zeichnen, können wir trotz des zufälligen Prozesses eine Struktur erkennen.

Hier ist ein Beispiel von Sierpinski Gasket:

Figure  1. The Sierpinski Gasket, generiert durch IFS Koeffizienten, die im Kapitel 2 berechnet werden

Figure 1. The Sierpinski Gasket, generiert durch IFS Koeffizienten, die im Kapitel 2 berechnet werden

The code:

//+------------------------------------------------------------------+
//|                                        IFS_Sierpinski_Gasket.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

//-- include file with cIntBMP class
#include <cIntBMP.mqh>

//-- Sierpinski Gasket IFS coefficients
//-- (a,b,c,d) matricies
double IFS_a[3] = {0.50,  0.50,  0.50};
double IFS_b[3] = {0.00,  0.00,  0.00};
double IFS_c[3] = {0.00,  0.00,  0.00};
double IFS_d[3] = {0.50,  0.50,  0.50};
//-- (e,f) vectors
double IFS_e[3] = {0.00,  0.00,  0.50};
double IFS_f[3] = {0.00,  0.50,  0.50};
//-- "probabilities" of transforms, multiplied by 1000
double IFS_p[3]={333,333,333};

double Probs[3]; // Probs array - Wird für die EFS Transformation benötigt
cIntBMP bmp;     // cIntBMP class instance
int scale=350;  // scale coefficient
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//-- Das Probs-Array vorbereiten
   double m=0;
   for(int i=0; i<ArraySize(IFS_p); i++)
     {
      Probs[i]=IFS_p[i]+m;
      m=m+IFS_p[i];
     }
//-- size of BMP image
   int XSize=500;
   int YSize=400;
//-- Erzeugung eines bmp Bildes mit XSizexYSize und clrSeashell Hintergrundfarbe
   bmp.Create(XSize,YSize,clrSeashell);
//-- Ein Rechteck
   bmp.DrawRectangle(0,0,XSize-1,YSize-1,clrBlack);

//-- Koordinaten (Diese werden für die Konstruktion des Sets benötigt)
   double x0=0;
   double y0=0;
   double x,y;
//-- number of points to calculate (more points - detailed image)
   int points=1500000;
//-- Set berechnen
   for(int i=0; i<points; i++)
     {
      // Auswahl der IFS Transformation mit der Wahrscheinlichkeit, proportional zu dem definierten
      double prb=1000*(rand()/32767.0);
      for(int k=0; k<ArraySize(IFS_p); k++)
        {
         if(prb<=Probs[k])
           {
            // Affine Transformation
            x = IFS_a[k] * x0 + IFS_b[k] * y0 + IFS_e[k];
            y = IFS_c[k] * x0 + IFS_d[k] * y0 + IFS_f[k];
            // Die vorherigen Koordinaten aktualisieren
            x0 = x;
            y0 = y;
            // In Bildkoordinaten umwandeln
            // (Beachten Sie die Y-Achse in cIntBMP)
            int scX = int (MathRound(XSize/2 + (x-0.5)*scale));
            int scY = int (MathRound(YSize/2 + (y-0.5)*scale));
            // Wenn die Koordinaten innerhalb des Bildes liegen dann zeichne den Punkt
            if(scX>=0 && scX<XSize && scY>=0 && scY<YSize) { bmp.DrawDot(scX,scY,clrDarkBlue); }
            break;
           }
        }
     }
//-- Bild als Datei speichern
   bmp.Save("bmpimg",true);
//-- Bild im Chart darstellen
   bmp.Show(0,0,"bmpimg","IFS");
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Bild vom Chart entfernen
   ObjectDelete(0,"IFS");
//--- Datei löschen
   bmp.Delete("bmpimg",true);
  }
//+------------------------------------------------------------------+

Wenn wir die Maßstab(scale) auf 1350 setzen, die Anzahl der Iterationen auf 15000000 erhöhen, und die Verschiebung des initialen Punktes ändern:

int scX = MathRound(XSize/2 + (x-0.75)*scale);
int scY = MathRound(YSize/2 + (y-0.75)*scale);

Dann sehen wir eine vergrößerte Region des Sets. Man kann in (Fig. 2) sehen, Das ist eine selbstähnliche Struktur hat:

Figure 2. Vergrößerte Region von Sierpinski Gasket

Figure 2. Vergrößerte Region von Sierpinski Gasket

Betrachten wir den beliebten Barnsley's Farn, vorgestellt von Michael Barnsley. Dieser ist ein wenig komplizierter.

Figure 3. Barnsley's Fern

Figure 3. Barnsley's Farn

Der Programmcode sieht ähnlich aus, aber in diesem Fall haben wir vier Kontraktionen mit verschiedenen Gewichtungen.

//+------------------------------------------------------------------+
//|                                                     IFS_fern.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include <cIntBMP.mqh>
//-- Barnsley Farn IFS Koeffizienten
//-- (a,b,c,d) matricies
double IFS_a[4] = {0.00,  0.85,  0.20,  -0.15};
double IFS_b[4] = {0.00,  0.04, -0.26,   0.28};
double IFS_c[4] = {0.00, -0.04,  0.23,   0.26};
double IFS_d[4] = {0.16,  0.85,  0.22,   0.24};
//-- (e,f) vectors
double IFS_e[4] = {0.00,  0.00,  0.00,   0.00};
double IFS_f[4] = {0.00,  1.60,  1.60,   0.00};
//-- "probabilities" of transforms, multiplied by 1000
double IFS_p[4] = {10,     850,    70,     70};

double Probs[4];
cIntBMP bmp;
int scale=50;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   double m=0;
   for(int i=0; i<ArraySize(IFS_p); i++)
     {
      Probs[i]=IFS_p[i]+m;
      m=m+IFS_p[i];
     }

   int XSize=600;
   int YSize=600;

   bmp.Create(XSize,YSize,clrSeashell);

   bmp.DrawRectangle(0,0,XSize-1,YSize-1,clrBlack);

   double x0=0;
   double y0=0;
   double x,y;

   int points=250000;

   for(int i=0; i<points; i++)
     {
      double prb=1000*(rand()/32767.0);
      for(int k=0; k<ArraySize(IFS_p); k++)
        {
         if(prb<=Probs[k])
           {
            x = IFS_a[k] * x0 + IFS_b[k] * y0 + IFS_e[k];
            y = IFS_c[k] * x0 + IFS_d[k] * y0 + IFS_f[k];
            x0 = x;
            y0 = y;
            int scX = int (MathRound(XSize/2 + (x)*scale));
            int scY = int (MathRound(YSize/2 + (y-5)*scale));
            if(scX>=0 && scX<XSize && scY>=0 && scY<YSize) { bmp.DrawDot(scX,scY,clrForestGreen); }
            break;
           }
        }
     }
   bmp.Save("bmpimg",true);
   bmp.Show(0,0,"bmpimg","IFS");
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectDelete(0,"IFS");
   bmp.Delete("bmpimg",true);
  }
//+------------------------------------------------------------------+ 

Es ist erstaunlich dass eine so komplexe Struktur mit lediglich 28 Zahlen definiert werden kann.

Wenn wir den Maßstab (scale) auf 150 erhöhen, und die Anzahl der Iterationen auf 1250000 setzen, dann erhalten wir ein vergrößertes Fragment:

Figure 4. Ein Fragment von Barnsley's Fern

Figure 4. Ein Fragment von Barnsley's Fern

Wie Sie sehen können, ist der Algorithmus universell einsetzbar und er erlaubt Ihnen verschiedene Fraktal-Sets zu generieren.

Das nächste Beispiel ist der Sierpinski Carpet, definiert durch die folgenden IFS Koeffizienten:

//-- Sierpinski Gasket IFS coefficients
double IFS_a[8] = {0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333};
double IFS_b[8] = {0.00,  0.00,  0.00,   0.00, 0.00,  0.00,  0.00,   0.00};
double IFS_c[8] = {0.00,  0.00,  0.00,   0.00, 0.00,  0.00,  0.00,   0.00};
double IFS_d[8] = {0.333, 0.333,  0.333,  0.333, 0.333,  0.333,  0.333, 0.333};
double IFS_e[8] = {-0.125, -3.375, -3.375,  3.125, 3.125, -3.375, -0.125, 3.125};
double IFS_f[8] = {6.75, 0.25, 6.75,  0.25, 6.75, 3.5, 0.25, 3.50};
//-- "Wahrscheinlichkeit", multipliziert mit 1000
double IFS_p[8]={125,125,125,125,125,125,125,125};

Figure 5. Sierpinski Carpet

Figure 5. Sierpinski Carpet

In Kapitel zwei haben wir uns die Algorithmen für die Berechnung der Koeffizienten der IFS Kontraktionen angeschaut.

Lassen Sie uns anschauen wie wir "fractal words" erzeugen können. In russischer Sprache sieht das Wort "Fractals" wie folgt aus:

Figure 6. Das Wort "Fractals" auf Russisch.

Figure 6. Das Wort "Fractals" auf Russisch.

Um die ISS Koeffizienten herausfinden zu können, müssen wir die zugehörigen linearen Gleichungen lösen. Die Lösungen sind:

//-- IFS Koeffizienten des Wortes "Fractals" in Russisch
double IFS_a[28]=
  {
   0.00, 0.03,  0.00, 0.09, 0.00, 0.03, -0.00, 0.07, 0.00, 0.07, 0.03,  0.03,  0.03,  0.00,
   0.04, 0.04, -0.00, 0.09, 0.03, 0.03,  0.03, 0.03, 0.03, 0.00, 0.05, -0.00,  0.05,  0.00
  };

double IFS_b[28]=
  {
   -0.11, 0.00, 0.07, 0.00, -0.07, 0.00, -0.11,  0.00, -0.07,  0.00, -0.11,  0.11, 0.00, -0.14,
   -0.12, 0.12,-0.11, 0.00, -0.11, 0.11,  0.00, -0.11,  0.11, -0.11,  0.00, -0.07, 0.00, -0.07
  };

double IFS_c[28]=
  {
   0.12,  0.00,  0.08,  -0.00,  0.08,  0.00,  0.12,  0.00,  0.04,  0.00,  0.12,  -0.12, 0.00,  0.12,
   0.06,  -0.06,  0.10,  0.00,  0.12,  -0.12,  0.00,  0.12,  -0.12,  0.12, 0.00,  0.04,  0.00,  0.12
  };

double IFS_d[28]=
  {
   0.00,  0.05,  0.00,  0.07,  0.00,  0.05,  0.00,  0.07,  0.00,  0.07,  0.00,  0.00,  0.07,  0.00,
   0.00,  0.00,  0.00,  0.07,  0.00,  0.00,  0.07,  0.00,  0.00,  0.00,  0.07,  0.00,  0.07,  0.00
  };

double IFS_e[28]=
  {
   -4.58,  -5.06, -5.16, -4.70, -4.09, -4.35, -3.73, -3.26, -2.76,  -3.26, -2.22, -1.86, -2.04, -0.98,
   -0.46,  -0.76,  0.76,  0.63,  1.78,  2.14,  1.96,  3.11,  3.47,  4.27,  4.60,  4.98,   4.60, 5.24
  };

double IFS_f[28]=
  {
   1.26,  0.89,  1.52,  2.00,  1.52,  0.89,  1.43,  1.96,  1.69,  1.24,  1.43,  1.41,  1.11,  1.43,
   1.79,  1.05,  1.32,  1.96,  1.43,  1.41,  1.11,  1.43,  1.41,  1.43,  1.42,  1.16,  0.71,  1.43
  };

//-- "Wahrscheinlichkeit", multipliziert mit 1000
double IFS_p[28]=
  {
   35,  35,  35,  35,  35,  35,  35,  35,  35,  35,  35,  35,  35,  35,  
   35,  35,  35,  35,  35,  35,  35,  35,  35,  35,  35,  35,  35,  35
  };

Als Ergebnis erhalten wir das folgende Bild:

Figure 7. Selbstähnliches Wort

Figure 7. Selbstähnliches Wort

Den vollständigen Programmcode finden Sie in ifs_fractals.mq5.

Wenn wir in das Bild hineinzoomen, sehen wir die selbstähnliche Struktur:

Figure 8. Vergrößerte Region des Sets

Figure 8. Vergrößerte Region des Sets

Die selbst ähnlichen Sets, die auf IFS basieren, können mit Hilfe des Fractal Designer konstruiert werden.

Wir haben nun das Thema, wie Fraktale mit Hilfe des Iterated Function Systems (IFS) erzeugt werden können, abgedeckt. Dank der cIntBMP Bibliothek, ist dieser Prozess sehr einfach. Jetzt ist es an der Zeit eine Klasse zu erstellen und einige Eigenschaften hinzuzufügen die die Qualität der Bilder verbessert.


Sie haben wahrscheinlich bemerkt dass die korrekte Konstruktion von Wahrscheinlichkeiten gesteuert wird. Der Unterschied in den Wahrscheinlichkeiten bedeutet das dass Set irreguläre Strukturen hat (Sehen Sie hierzu die Gewichtungen von Barnsley Farn IFS). Diese Tatsache kann dazu benutzt werden, schöne Bilder zu erzeugen. Wir setzen dazu die Farbe proportional zu der Häufigkeit der Punkte in der Umgebung.

Dieses kann mit einem virtuellen Bildschirm erreicht werden (Lediglich ein array), Wendy. Farbe von vorherigen Werten abhängt. Zum Schluss wird der virtuelle Bildschirm mit Hilfe der Palette zu einem BMP gerendert. Das BMP Bild kann als Hintergrund im Charts gezeichnet werden

Hier ist der Programmcode des Expert Advisors, basierend auf der CIFS Klasse:

//+------------------------------------------------------------------+
//|                                               IFS_Fern_color.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#include <cIntBMP.mqh>
//-- Barnsley Farn IFS Koeffizienten
double IFS_a[4] = {0.00,  0.85,  0.20,  -0.15};
double IFS_b[4] = {0.00,  0.04, -0.26,   0.28};
double IFS_c[4] = {0.00, -0.04,  0.23,   0.26};
double IFS_d[4] = {0.16,  0.85,  0.22,   0.24};
double IFS_e[4] = {0.00,  0.00,  0.00,   0.00};
double IFS_f[4] = {0.00,  1.60,  1.60,   0.00};
double IFS_p[4] = {10,     850,    70,     70};
//-- Palette
uchar Palette[23*3]=
  {
   0x00,0x00,0x00,0x02,0x0A,0x06,0x03,0x11,0x0A,0x0B,0x1E,0x0F,0x0C,0x4C,0x2C,0x1C,0x50,0x28,
   0x2C,0x54,0x24,0x3C,0x58,0x20,0x4C,0x5C,0x1C,0x70,0x98,0x6C,0x38,0xBC,0xB0,0x28,0xCC,0xC8,
   0x4C,0xB0,0x98,0x5C,0xA4,0x84,0xBC,0x68,0x14,0xA8,0x74,0x28,0x84,0x8C,0x54,0x94,0x80,0x40,
   0x87,0x87,0x87,0x9F,0x9F,0x9F,0xC7,0xC7,0xC7,0xDF,0xDF,0xDF,0xFC,0xFC,0xFC
  };
//+------------------------------------------------------------------+
//| CIFS class                                                       |
//+------------------------------------------------------------------+
class CIFS
  {
protected:
   cIntBMP           m_bmp;
   int               m_xsize;
   int               m_ysize;
   uchar             m_virtual_screen[];
   double            m_scale;
   double            m_probs[8];

public:
                    ~CIFS()                          { m_bmp.Delete("bmpimg",true); };
   void              Create(int x_size,int y_size,uchar col);
   void              Render(double scale,bool back);
   void              ShowBMP(bool back);
protected:
   void              VS_Prepare(int x_size,int y_size,uchar col);
   void              VS_Fill(uchar col);
   void              VS_PutPixel(int px,int py,uchar col);
   uchar             VS_GetPixel(int px,int py);
   int               GetPalColor(uchar index);
   int               RGB256(int r,int g,int b) const {return(r+256*g+65536*b);      }
   void              PrepareProbabilities();
   void              RenderIFSToVirtualScreen();
   void              VirtualScreenToBMP();
  };
//+------------------------------------------------------------------+
//| Methode für das Erzeugen                                                     |
//+------------------------------------------------------------------+
void CIFS::Create(int x_size,int y_size,uchar col)
  {
   m_bmp.Create(x_size,y_size,col);
   VS_Prepare(x_size,y_size,col);
   PrepareProbabilities();
  }
//+------------------------------------------------------------------+
//| Vorbereiten des virtuellen Bildschirms                                          |
//+------------------------------------------------------------------+
void CIFS::VS_Prepare(int x_size,int y_size,uchar col)
  {
   m_xsize=x_size;
   m_ysize=y_size;
   ArrayResize(m_virtual_screen,m_xsize*m_ysize);
   VS_Fill(col);
  }
//+------------------------------------------------------------------+
//| Füllte den virtuellen Bildschirm mit Farbe                    |
//+------------------------------------------------------------------+
void CIFS::VS_Fill(uchar col)
  {
   for(int i=0; i<m_xsize*m_ysize; i++) {m_virtual_screen[i]=col;}
  }
//+------------------------------------------------------------------+
//| Gibt die Farbe aus der palette zurück                                   |
//+------------------------------------------------------------------+
int CIFS::GetPalColor(uchar index)
  {
   int ind=index;
   if(ind<=0) {ind=0;}
   if(ind>22) {ind=22;}
   uchar r=Palette[3*(ind)];
   uchar g=Palette[3*(ind)+1];
   uchar b=Palette[3*(ind)+2];
   return(RGB256(r,g,b));
  }
//+------------------------------------------------------------------+
//| Malt einen Pixel auf den virtuellen Bildschirm                              |
//+------------------------------------------------------------------+
void CIFS::VS_PutPixel(int px,int py,uchar col)
  {
   if (px<0) return;
   if (py<0) return;
   if (px>m_xsize) return;
   if (py>m_ysize) return;
    int pos=m_xsize*py+px;
   if(pos>=ArraySize(m_virtual_screen)) return;
   m_virtual_screen[pos]=col;
  }
//+------------------------------------------------------------------+
//| Ruft einen Pixel "color" vom virtuellen Bildschirm ab                   |
//+------------------------------------------------------------------+
uchar CIFS::VS_GetPixel(int px,int py)
  {
   if (px<0) return(0);
   if (py<0) return(0);
   if (px>m_xsize) return(0);
   if (py>m_ysize) return(0);
    int pos=m_xsize*py+px;
   if(pos>=ArraySize(m_virtual_screen)) return(0);
   return(m_virtual_screen[pos]);
  }
//+------------------------------------------------------------------+
//| Vorbereiten des aufsummierenden wahrscheinlichkeits-Arrays                       |
//+------------------------------------------------------------------+
void CIFS::PrepareProbabilities()
  {
   double m=0;
   for(int i=0; i<ArraySize(IFS_p); i++)
     {
      m_probs[i]=IFS_p[i]+m;
      m=m+IFS_p[i];
     }
  }
//+------------------------------------------------------------------+
//| Rendert das IFS Set auf den virtuellen Bildschirm                        |
//+------------------------------------------------------------------+
void CIFS::RenderIFSToVirtualScreen()
  {
   double x=0,y=0;
   double x0=0;
   double y0=0;
   uint iterations= uint (MathRound(100000+100*MathPow(m_scale,2)));

   for(uint i=0; i<iterations; i++)
     {
      double prb=1000*(rand()/32767.0);

      for(int k=0; k<ArraySize(IFS_p); k++)
        {
         if(prb<=m_probs[k])
           {
            x = IFS_a[k] * x0 + IFS_b[k] * y0 + IFS_e[k];
            y = IFS_c[k] * x0 + IFS_d[k] * y0 + IFS_f[k];

            int scX = int (MathRound(m_xsize/2 + (x-0)*m_scale));
            int scY = int (MathRound(m_ysize/2 + (y-5)*m_scale));

            if(scX>=0 && scX<m_xsize && scY>=0 && scY<m_ysize)
              {
               uchar c=VS_GetPixel(scX,scY);
               if(c<255) c=c+1;
               VS_PutPixel(scX,scY,c);
              }
            break;
           }
         x0 = x;
         y0 = y;
        }
     }
  }
//+------------------------------------------------------------------+
//| Kopiert den virtuellen Bildschirm in ein BMP                                    |
//+------------------------------------------------------------------+
void CIFS::VirtualScreenToBMP()
  {
   for(int i=0; i<m_xsize; i++)
     {
      for(int j=0; j<m_ysize; j++)
        {
         uchar colind=VS_GetPixel(i,j);
         int xcol=GetPalColor(colind);
         if(colind==0) xcol=0x00;
         //if(colind==0) xcol=0xFFFFFF;
         m_bmp.DrawDot(i,j,xcol);
        }
     }
  }
//+------------------------------------------------------------------+
//| Zeigt das BMP auf dem Chart                                     |
//+------------------------------------------------------------------+
void CIFS::ShowBMP(bool back)
  {
   m_bmp.Save("bmpimg",true);
   m_bmp.Show(0,0,"bmpimg","Fern");
   ObjectSetInteger(0,"Fern",OBJPROP_BACK,back);
  }
//+------------------------------------------------------------------+
//| Render method                                                    |     
//+------------------------------------------------------------------+
void CIFS::Render(double scale,bool back)
  {
   m_scale=scale;
   VS_Fill(0);
   RenderIFSToVirtualScreen();
   VirtualScreenToBMP();
   ShowBMP(back);
  }

static int gridmode;
CIFS fern;
int currentscale=50;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
void OnInit()
  {
//-- get grid mode
   gridmode= int (ChartGetInteger(0,CHART_SHOW_GRID,0));
//-- disable grid
   ChartSetInteger(0,CHART_SHOW_GRID,0);
//-- create bmp
   fern.Create(800,800,0x00);
//-- zeige es als Hintergrundbild an
   fern.Render(currentscale,true);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int r)
  {
//-- restore grid mode
   ChartSetInteger(0,CHART_SHOW_GRID,gridmode); 
//-- delete Fern object
   ObjectDelete(0,"Fern");
 }
//+------------------------------------------------------------------+
//| Expert OnChart event handler                                     |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,           // Event identifier  
                const long& lparam,   // Event parameter of long type
                const double& dparam, // Event parameter of double type
                const string& sparam  // Event parameter of string type
                )
  {
//--- Ein Click auf das grafische Objekt
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      Print("Click event on graphic object with name '"+sparam+"'");
      if(sparam=="Fern")
        {
         // Erhöhung des Maßstabs-Koeffizienten (scale) (zoom)
         currentscale=int (currentscale*1.1);
         fern.Render(currentscale,true);
        }
     }
  }
//+------------------------------------------------------------------+

Das Ergebnis ist:

Figure 9. Barnsley's fern image, erzeugt mit der CIFS Klasse

Abb. 9. Barnsley's Farn, erzeugt mit der CIFS Klasse


Figure 10. Die vergrößerte Region von Barnsley's Fern

Abb. 10. Die vergrößerte Region von Barnsley's Farn


Figure 11. Die vergrößerte Region von Barnsley's Fern

Abb. 11. Die vergrößerte Region von Barnsley's Farn


Figure 12. Die vergrößerte Region von Barnsley's Fern

Abb. 12. Die vergrößerte Region von Barnsley's Farn

Machen sie es selbst

1. Es gibt eine Menge von IFS Fraktale in Fractint, Zum Beispiel:

// Binary
double IFS_a[3] = { 0.5,  0.5,  0.0};
double IFS_b[3] = { 0.0,  0.0, -0.5};
double IFS_c[4] = { 0.0,  0.0,  0.5};
double IFS_d[4] = { 0.5,  0.5,  0.5};
double IFS_e[4] = {-2.563477,  2.436544, 4.873085};
double IFS_f[4] = {-0.000000, -0.000003, 7.563492};
double IFS_p[4] = {333, 333, 333};

// Coral
double IFS_a[3] = { 0.307692,  0.307692,  0.000000};
double IFS_b[3] = {-0.531469, -0.076923,  0.54545};
double IFS_c[3] = {-0.461538,  0.153846,  0.692308};
double IFS_d[3] = {-0.293706, -0.447552, -0.195804};
double IFS_e[3] = {5.4019537, -1.295248, -4.893637};
double IFS_f[3] = { 8.6551754.152990,  7.269794};
double IFS_p[3] = {400, 150, 450};

// Crystal
double IFS_a[2] = { 0.696970,  0.090909};
double IFS_b[2] = {-0.481061, -0.443182};
double IFS_c[2] = {-0.393939,  0.515152};
double IFS_d[2] = {-0.662879, -0.094697};
double IFS_e[2] = { 2.147003,  4.286558};
double IFS_f[2] = {10.310288,  2.925762};
double IFS_p[2] = {750, 250};

// Dragon
double IFS_a[2] = { 0.824074,  0.088272};
double IFS_b[2] = { 0.281482,  0.520988};
double IFS_c[2] = {-0.212346, -0.463889};
double IFS_d[2] = { 0.864198, -0.377778};
double IFS_e[2] = {-1.882290,  0.785360};
double IFS_f[2] = {-0.110607,  8.095795};
double IFS_p[2] = {780, 220};

// Floor
double IFS_a[3] = { 0,  0.52,  0};
double IFS_b[3] = {-0.5,   0,  0.5};
double IFS_c[3] = { 0.5,   0, -0.5};
double IFS_d[3] = { 0,   0.5,  0};
double IFS_e[3] = {-1.732366, -0.027891,  1.620804};
double IFS_f[3] = { 3.366182,  5.014877,  3.310401};
double IFS_p[3] = {333, 333, 333};

// Koch3
double IFS_a[5] = {0.307692, 0.192308,  0.192308,  0.307692,  0.384615};
double IFS_b[5] = {      0,-0.205882,  0.205882,         0,        0};
double IFS_c[5] = {      0, 0.653846, -0.653846,         0,         0};
double IFS_d[5] = {0.294118, 0.088235,  0.088235,  0.294118, -0.294118};
double IFS_e[5] = {4.119164,-0.688840,  0.688840, -4.136530, -0.007718};
double IFS_f[5] = {1.604278, 5.978916,  5.962514,  1.604278,  2.941176};
double IFS_p[5] = {151, 254, 254, 151, 190};

//Spiral
double IFS_a[3] = { 0.787879, -0.121212,  0.181818};
double IFS_b[3] = {-0.424242,  0.257576, -0.136364};
double IFS_c[3] = { 0.242424,  0.151515,  0.090909};
double IFS_d[3] = { 0.859848,  0.053030,  0.181818};
double IFS_e[3] = { 1.758647,  -6.721654,  6.086107};
double IFS_f[3] = { 1.408065,   1.377236,  1.568035};
double IFS_p[3] = {896, 52, 52};

//Swirl5
double IFS_a[2] = {  0.74545, -0.424242};
double IFS_b[2] = {-0.459091, -0.065152};
double IFS_c[2] = { 0.406061, -0.175758};
double IFS_d[2] = { 0.887121, -0.218182};
double IFS_e[2] = { 1.460279,  3.809567};
double IFS_f[2] = { 0.691072,  6.741476};
double IFS_p[2] = {920, 80};

//Zigzag2
double IFS_a[2] = {-0.632407, -0.036111};
double IFS_b[2] = {-0.614815, 0.444444};
double IFS_c[2] = {-0.545370, 0.210185};
double IFS_d[2] = { 0.659259, 0.037037};
double IFS_e[2] = { 3.840822, 2.071081};
double IFS_f[2] = { 1.282321, 8.330552};
double IFS_p[2] = {888, 112};

Drucken Sie diese Sets aus. Wie findet man die Initialen Ähnlichkeitstransformationen unter Verwendung der IFS Koeffizienten heraus?

2. Generieren Sie Ihre eigenen Fraktal-Sets und berechnen sie deren Koeffizienten (chapter 2).

3. Versuchen Sie mit den Farbpaletten zu experimentieren (uchar Palette array), Erweitern Sie die Palette und fügen Sie Farbverläufe hinzu.

4. Was ist mit der Fraktalen (Hausdorf-Bezikovitch) Dimension von Barnsley's Farn? Gibt es hierfür eine Formel für die Berechnung der fraktalen Dimension unter Verwendung der IFS Koeffizienten*.

5. Fügen Sie mit Hilfe der Information von einem Mausklick, einer bestimmten Region eine Vergrößerung hinzu. OnChartEvent:

void OnChartEvent(const int id,         // Event identifier  
                const long& lparam,   // Event parameter of long type
                const double& dparam, // Event parameter of double type
                const string& sparam  // Event parameter of string type
                )
  {
//--- Linke Maustaste
   if(id==CHARTEVENT_CLICK)
     {
      Print("Coordinates: x=",lparam,"  y=",dparam);
     }
  }

Schlussfolgerung

Wir haben uns die Algorithmen für die Erstellung von selbstähnlichen Sets mit Hilfe der Iterated Function System angeschaut.

Die Verwendung der cIntBMP Bibliothek vereinfacht auf geniale Weise die Arbeit mit grafischen Bildern. Neben der DrawDot(x,y,color) Methode, die wir verwendet haben, Beinhaltet die Klasse cIntBMP viele weitere hilfreiche Methoden. Aber das ist eine andere Geschichte.


Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalpublikation: https://www.mql5.com/ru/code/328

MQL5 Wizard - Trading Signals of Candlestick Patterns + Stochastic MQL5 Wizard - Trading Signals of Candlestick Patterns + Stochastic

Tradingsignale mit Kerzengruppen und der Bestätigung durch einen stochastischen Indikator.

iChartsSwitchSymbol iChartsSwitchSymbol

Wenn das Symbol des Charts geändert wird, dann werden auch alle anderen Symbole in allen anderen Charts geändert.

DRAW_NONE DRAW_NONE

Der DRAW_NONE Zeichnungstyp wird in den Fällen verwendet, wo sie eine Berechnung durchführen und die Ergebnisse der Berechnungen im "Data Window" anzeigen aber die Zeichnung selbst nicht benötigt wird.

DRAW_LINE DRAW_LINE

Der DRAW_LINE Zeichnungstyp Wird für die Zeichnung der Werte des Indikators Speichers (Idicator buffers) als Linie verwendet.