거래 로봇을 무료로 다운로드 하는 법을 시청해보세요
당사를 Twitter에서 찾아주십시오!
당사 팬 페이지에 가입하십시오
스크립트가 흥미로우신가요?
그렇다면 링크 to it -
하셔서 다른 이들이 평가할 수 있도록 해보세요
스크립트가 마음에 드시나요? MetaTrader 5 터미널에서 시도해보십시오
Experts

IFS(반복 함수 시스템)를 사용하여 MQL5에서 프랙탈 생성 - MetaTrader 5용 expert

조회수:
406
평가:
(39)
게시됨:
2022.01.10 12:46
\MQL5\Experts\IFS\
ifs_fern.mq5 (2.67 KB) 조회
\MQL5\Include\
cintbmp.mqh (78.58 KB) 조회
이 코드를 기반으로 한 로봇이나 지표가 필요하신가요? 프리랜스로 주문하세요 프리랜스로 이동

소개

다음과 같이 정의된 self-similar set을 생성할 수 있는 많은 프로그램이 있습니다. 반복 함수 시스템(Iterated Function System) (IFS). Fractint, Fractal Designer or IFS Matlab Generator과 같은 예를 살펴보세요. MQL5 언어의 빠른 속도와 그래픽 객체 작업에 의해 이 아름다운 세트를 메타 트레이더 5 클라이언트 터미널에서 살펴볼 수 있습니다.

드미트리 (정수)로 개발된 cIntBMP 라이브러리는 그래픽을 활용하는데 도움을 주고 그래픽 이미지를 생성 하는 것을 크게 단순화합니다. 이 라이브러리는 MetaQuotes Software Corp의 특별상을 수여 받았습니다.

이글에서 우리는 cIntBMP 라이브러리를 사용한 작업의 예를 살펴 볼 것입니다. 또한 반복 함수 시스템(Iterated Function System)을 사용하여 프랙탈 집합을 생성하는 알고리즘을 다룰 것입니다.


1. Affine Transformation of Plane

The affine transformation of plane is a mapping . 일반적으로 affine 2차원 변환은 매트릭스와 벡터로 정의할 수 있습니다. 좌표(x,y)가 있는 점은 선형 변환을 사용해서 다른 점으로 변환됩니다:

변환은 non-singular이어야 합니다. affine transforms는 size times 크기를 변경합니다.

affine 변환은 기하학적 객체(선으로 변환된 선)의 구조를 변경하지 않으며 AT를 사용하면 회전, 크기 조정 및 이동과 같은 객체의 간단한 "변형"을 설명할 수 있습니다.

affine plane transforms 예:

1) 앵글에서 평면 로테이션:

2) 계수(X 및 Y축)와 "평면 스케일링":

3) 벡터를 통한 평면 해석:

contraction mappings이 키입니다(Hutchinson 결과를 확인하세요).

이 메트릭이면(일례, Euclid metric: ) 이 좌표를 가지고 있습니다. affine 변형은 contraction을 부릅니다. 에서 만약 이면.

다음은 affine 변형의 예입니다:

결과는 다음과 같습니다:


2. 유사 변형(Similarity Transforms)

프랙탈은 다음과 같은 방식으로 구성됩니다. 일부 (단순한) 기하학적 개체(단면, 삼각형, 정사각형)를 N 조각으로 나누고 그 중 M을 집합의 추가 "construction"에 사용합니다(N=M인 경우 정수 차원을 얻습니다. 결과 집합). 또한 이 과정은 각 조각에 대해 계속해서 반복되었습니다.

전통적인 fractals:

섹션:

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

Triangle:

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

Squares:

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

기타 등등.

프랙탈은 self-similar structure를 가지며 그 중 일부는 여러가지 similarity transformations으로 정의할 수 있습니다. 아핀 변환 구조는 프랙탈의 구성 방식에 따라 다릅니다.

앞으로 보게 되겠지만 매우 간단하며 우리가 해결해야 하는 유일한 문제는 fractal construction의 첫 번째 iteration만 설명하고 해당하는 아핀 변환 집합을 찾는 것입니다.

어떤 세트가 있다고 가정해 봅시다. 프랙탈 생성 알고리즘에 따르면 이를 줄이고 회전하고 "특정 위치에 놓을" 필요가 있습니다. 문제는 아핀 변환을 사용하여 이 프로세스를 설명하는 것입니다. 즉, 행렬과 벡터를 찾아야 합니다.

초기 세트(사소하지 않은)의 3개 포인트를 취하여 "축소된" 세트의 3개 해당 포인트로 변환하는 것으로 충분하다는 것을 증명하는 것은 쉽습니다. 이 변환은 6개의 선형 방정식으로 이어져 a,b,c,d,e,f를 솔루션으로 찾을 수 있습니다.

여기서 살펴보겠습니다. 삼각형이 삼각형으로 변환 되었다고 가정합니다.

선형 방정식 시스템을 풀면 a, b, c, d, f 계수를 얻을 수 있습니다.

예:Sierpinski Gasket:

포인트의 좌표는 다음과 같습니다.

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

3가지 변형이 있습니다.

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

선형 방정식 시스템은 다음과 같습니다.




솔루션은 다음과 같습니다: , ,

세 가지 아핀 변환의 계수를 찾았습니다. 더 나아가 우리는 그것들을 self-similar sets의 생성에 사용할 것입니다.


3. 반복 함수 시스템을 사용하여 프랙탈 만들기

Iterated Function System (IFS)where -이 "weights"인 affine contractions의 세트입니다 각각의 IFS 함수는 7개의 숫자로 정의됩니다: 가중치는 n번째 변환의 확률로 반복 처리할 때 사용됩니다. 컨트렉션에 비례하여 그 값들을 정의하는 것이 좋습니다: .

반복 함수 시스템을 사용하여 프랙탈 구성 알고리즘을 살펴보겠습니다.(Chaos Game도 살펴 보시기 바랍니다).

첫 번째로 필요한 것은 좌표가 있는 초기점을 취하는 것입니다. . 다음으로 constraction 중 일부를 무작위로 선택하고 점을 플로팅 합니다. . 그리고 다시, contraction 중 하나를 무작위로 선택합니다. 그리고 플랏 합니다 . 마지막으로 우리는 점의 집합으로 을 갖게 됩니다 .

contraction의 선택은 "확률"에 따라 다릅니다. 만약 프로세스를 반복하고(예: ~30000포인트) 결과 세트를 플롯 하면 무작위 프로세스에도 불구하고 구조를 볼 수 있습니다.

다음은 Sierpinski Gasket의 예입니다.

그림  1. 챕터 2에서 계산된 IFS 계수로 생성된 Sierpinski Gasket

그림 1. 챕터 2에서 계산된 IFS 계수로 생성된 Sierpinski Gasket

코드:

//+------------------------------------------------------------------+
//|                                        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 파일과 cIntBMP 클래스
#include <cIntBMP.mqh>

//-- Sierpinski Gasket IFS 계수
//-- (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};
//-- 1000이 곱해진 변형의 "확률" 
double IFS_p[3]={333,333,333};

double Probs[3]; // Probs array -  IFS 변형을 선택하기 위해 사용됨
cIntBMP bmp;     // cIntBMP class instance
int scale=350;  // 스케일 계수
//+------------------------------------------------------------------+
//| Expert 초기화 함수                                                 |
//+------------------------------------------------------------------+
int OnInit()
  {
//--  Probs 행 준비
   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;
//-- clrSeashell 백그라운드 컬러로 bmp image XSizexYSize를 생성
   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=1500000;
//-- 세트를 계산
   for(int i=0; i<points; i++)
     {
      // 정의된 확률과 비례에 따른 IFS 변형
      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];
            // 이전 좌표 업데이트
            x0 = x;
            y0 = y;
            // BMP 이미지 좌표로 변환
            // (cIntBMP의 Y 축 주의 )
            int scX = int (MathRound(XSize/2 + (x-0.5)*scale));
            int scY = int (MathRound(YSize/2 + (y-0.5)*scale));
            // 포인트 계수가 이밎 안에 있으면 점을 그림
            if(scX>=0 && scX<XSize && scY>=0 && scY<YSize) { bmp.DrawDot(scX,scY,clrDarkBlue); }
            break;
           }
        }
     }
//-- 이미지를 파일로 저장
   bmp.Save("bmpimg",true);
//-- 이미즈를 차트에 놓음
   bmp.Show(0,0,"bmpimg","IFS");
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert 초기화 해제 함수                                             |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- 이미지를 차트에서 삭제
   ObjectDelete(0,"IFS");
//--- 파일 삭제
   bmp.Delete("bmpimg",true);
  }
//+------------------------------------------------------------------+

scale을 1350으로 설정하려면 반복 횟수를 15000000으로 늘리고 shift 초기점을 변경합니다.

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

세트의 확대된 영역을 볼 수 있습니다. self-similar structure를 가지고 있는 (그림 2)을 볼 수 있습니다.

그림 2. Sierpinski Gasket의 확대 영역

그림 2. Sierpinski Gasket의 확대 영역

마이클 반즐리가 제안한 유명한 반즐리의 고사리를 살펴봅니다. 좀더 복잡합니다.

그림 3. 반즐리의 고사리

그림 3. 반즐리의 고사리

코드는 비슷하지만 이 경우 가중치가 서로 다른 4개의 IFS 수축이 있습니다.

//+------------------------------------------------------------------+
//|                                                     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>
//-- 반즐리 고사리 IFS 계수
//-- (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};
//-- 1000이 곱해진 변형의 "확률"
double IFS_p[4] = {10,     850,    70,     70};

double Probs[4];
cIntBMP bmp;
int scale=50;
//+------------------------------------------------------------------+
//| Expert 초기화 함수                                                 |
//+------------------------------------------------------------------+
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 초기화 해제 함수                                             |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectDelete(0,"IFS");
   bmp.Delete("bmpimg",true);
  }
//+------------------------------------------------------------------+ 

이렇게 복잡한 구조를 28개의 숫자로 정의할 수 있다는 것이 놀랍습니다.

스케일을 150으로 늘리고 반복을 1250000으로 설정하면 확대된 조각이 표시됩니다.

그림 4. 반즐리의 고사리 조각

그림 4. 반즐리의 고사리 조각

보다시피 알고리즘은 보편적이므로 다양한 프랙탈 세트를 생성할 수 있습니다.

다음 예는 다음 IFS 계수로 정의되는 Sierpinski Carpet입니다.

//-- Sierpinski Gasket IFS 계수
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};
//-- 1000이 곱해진 "확률"
double IFS_p[8]={125,125,125,125,125,125,125,125};

그림 5. Sierpinski Carpet

그림 5. Sierpinski Carpet

2장에서 우리는 IFS 수축 계수 계산 알고리즘을 살려 보았습니다.

"프랙탈 단어"를 만드는 방법을 살펴 보겠습니다. 러시아어에서 "프랙탈"이란 단어는 다음과 같이 생겼습니다.

그림 6. 러시아어로 "프랙탈"이란 단어

그림 6. 러시아어로 "프랙탈"이란 단어

IFS 계수를 찾으려면 해당 선형 시스템을 풀어야 합니다. 해법은 다음과 같습니다:

//-- 러시아어로 "Fractals"이란 단어의 IFS 계수
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
  };

//-- 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
  };

결과로 다음과 같은 이미지를 얻을 수 있습니다.

그림 7. 자기 유사 단어

그림 7. 자기 유사 단어

전체 소스 코드는 ifs_fractals.mq5에서 찾을 수 있습니다.

세트를 확대하면 자기 유사 구조가 보입니다.

그림 8. 세트의 확대된 영역

그림 8. 세트의 확대된 영역

IFS를 기반으로 하는 자기 유사 집합은 프랙탈 디자이너을 사용하여 구성할 수 있습니다.

우리는 반복 함수 시스템을 사용하여 프랙탈 집합을 만드는 방법에 대해 다뤘습니다. cIntBMP 라이브러리 덕분에 프로세스는 매우 간단합니다. 이제 클래스를 만들고 이미지를 개선하기 위한 몇 가지 기능을 추가할 시간입니다.


확률에 의해 구동되는 세트의 올바른 구성을 알 수 있습니다. 확률의 차이는 집합이 불규칙한 구조를 갖는다는 것을 의미합니다(반즐리 고사리 IFS의 가중치 참조). 이 사실은 아름다운 이미지를 만드는 데 사용할 수 있습니다. 어떤 이웃에 있는 점의 빈도에 비례하여 색상을 설정해야 합니다.

픽셀 색상이 이전 값에 따라 달라지는 경우 가상 화면(배열)을 사용하여 수행할 수 있습니다. 마지막으로 가상 화면은 팔레트를 사용하여 bmp로 렌더링됩니다. bmp 이미지 자체를 차트의 배경 그림으로 그릴 수 있습니다.

다음은 CIFS 클래스를 기반으로 하는 Expert Advisor의 코드입니다.

//+------------------------------------------------------------------+
//|                                               IFS_Fern_color.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#include <cIntBMP.mqh>
//-- 반즐리 고사리 IFS 계수
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};
//-- 팔레트
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 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();
  };
//+------------------------------------------------------------------+
//| 생성 메서드                                                        |
//+------------------------------------------------------------------+
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();
  }
//+------------------------------------------------------------------+
//| 가상 화면 준비                                                     |
//+------------------------------------------------------------------+
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);
  }
//+------------------------------------------------------------------+
//| 특정 색으로 가상 화면을 채움                                          |
//+------------------------------------------------------------------+
void CIFS::VS_Fill(uchar col)
  {
   for(int i=0; i<m_xsize*m_ysize; i++) {m_virtual_screen[i]=col;}
  }
//+------------------------------------------------------------------+
//| 팔레트에서 색상 반환                                                |
//+------------------------------------------------------------------+
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));
  }
//+------------------------------------------------------------------+
//| 가상 화면에 픽셀을 그림                                              |
//+------------------------------------------------------------------+
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;
  }
//+------------------------------------------------------------------+
//| 픽셀 '색상'을 가상 화면에서 가져옴                                    |
//+------------------------------------------------------------------+
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]);
  }
//+------------------------------------------------------------------+
//|  점진적 확률 배열을 준비                                             |
//+------------------------------------------------------------------+
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];
     }
  }
//+------------------------------------------------------------------+
//|  IFS 세트를 가상 화면에 보임                                         |
//+------------------------------------------------------------------+
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;
        }
     }
  }
//+------------------------------------------------------------------+
//| 가상 화면을 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);
        }
     }
  }
//+------------------------------------------------------------------+
//| BMP 이미지를 차트에 나타냄                                           |
//+------------------------------------------------------------------+
void CIFS::ShowBMP(bool back)
  {
   m_bmp.Save("bmpimg",true);
   m_bmp.Show(0,0,"bmpimg","Fern");
   ObjectSetInteger(0,"Fern",OBJPROP_BACK,back);
  }
//+------------------------------------------------------------------+
//| Render 메서드                                                     |     
//+------------------------------------------------------------------+
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 초기화 함수                                                 |
//+------------------------------------------------------------------+
void OnInit()
  {
//-- 그리드 모드 
   gridmode= int (ChartGetInteger(0,CHART_SHOW_GRID,0));
//-- 그리드 모드 해제
   ChartSetInteger(0,CHART_SHOW_GRID,0);
//-- bmp 생성
   fern.Create(800,800,0x00);
//-- 백그라운드 이미지로 
   fern.Render(currentscale,true);
  }
//+------------------------------------------------------------------+
//| Expert 초기화 해제 함수                                             |
//+------------------------------------------------------------------+
void OnDeinit(const int r)
  {
//-- 그리드 모드 복원
   ChartSetInteger(0,CHART_SHOW_GRID,gridmode); 
//-- 고사리 객체 삭제
   ObjectDelete(0,"Fern");
 }
//+------------------------------------------------------------------+
//| Expert OnChart 이벤트 핸들러                                       |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,           // 이벤트 식별자  
                const long& lparam,   // long 타입의 이벤트 패러미터
                const double& dparam, //  double 타입의 이벤트 패러미터
                const string& sparam  // string 타입의 이벤트 패러미터
                )
  {
//--- 그래픽 객체 클릭
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      Print("그래픽 객체 이름과 함께 이벤트 클릭 '"+sparam+"'");
      if(sparam=="Fern")
        {
         // 스케일 계수(줌) 증가
         currentscale=int (currentscale*1.1);
         fern.Render(currentscale,true);
        }
     }
  }
//+------------------------------------------------------------------+

결과는 다음과 같습니다:

그림 9. CIFS 클래스로 만든 Barnsley의 고사리 이미지

그림 9. CIFS 클래스로 만든 Barnsley의 고사리 이미지


그림 10. Barnsley 고사리의 확대 영역

그림 10. Barnsley 고사리의 확대 영역


Figure 11. Barnsley 고사리의 확대 영역

Figure 11. Barnsley 고사리의 확대 영역


Figure 12. Barnsley 고사리의 확대 영역

Figure 12. Barnsley 고사리의 확대 영역

스스로 해 보세요

1. Fractint에는 IFS 프랙탈이 많이 있습니다. 예를 들어 다음과 같습니다:

// 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};

이 집합을 그려보세요. IFS 계수를 사용하여 유사성 변환 시작부분을 찾는 방법은 무엇입니까?

2. 자신만의 프랙탈 세트를 만들고 계수를 계산합니다(2장).

3. 팔레트 색상(uchar Palette 배열)으로 시도하고 팔레트를 확장하고 그라디언트 색상을 추가하십시오.

4. Barnsley의 고사리의 프랙탈(Hausdorf-Bezikovitch) 차원은 어떻습니까? IFS 계수*를 사용하여 프랙탈 차원을 계산하는 공식이 있습니까?

5. OnChartEven의 마우스 클릭 좌표 정보를 이용하여 특정 영역의 확대/축소 추가:

void OnChartEvent(const int id,         // 이벤트 식별자  
                const long& lparam,   // long 타입의 이벤트 패러미터
                const double& dparam, // double 타입의 이벤트 패러미터
                const string& sparam  // string 타입의 이벤트 패러미터 
                )
  {
//--- 좌 클릭 
   if(id==CHARTEVENT_CLICK)
     {
      Print("Coordinates: x=",lparam,"  y=",dparam);
     }
  }

결론

반복 함수 시스템을 사용하여 자기 유사 집합을 생성하는 알고리즘을 살펴 봤습니다.

cIntBMP 라이브러리를 사용하면 그래픽 이미지 작업을 크게 단순화할 수 있습니다. 우리가 사용한 DrawDot(x,y,color) 메서드 외에도 cIntBMP 클래스에는 다른 유용한 메서드가 많이 포함되어 있습니다. 하지만 또다른 영역이기도 합니다.


MetaQuotes Ltd에서 러시아어로 번역함.
원본 코드: https://www.mql5.com/ru/code/328

MQL5 마법사 - 캔들 스틱 패턴에 기반한 거래 신호 + 스토캐스틱 MQL5 마법사 - 캔들 스틱 패턴에 기반한 거래 신호 + 스토캐스틱

스토캐스틱 지표에 의한 확인과 캔들스틱 패턴을 통한 거래 신호

Demo_BitmapOffset (OBJPROP_XOFFSET and OBJPROP_YOFFSET) Demo_BitmapOffset (OBJPROP_XOFFSET and OBJPROP_YOFFSET)

만약 현재 이미지의 일부만 표시하고 나머지는 숨길 필요가 있는 경우 이미지가 보이는 부분을 지정하여 이동하는 창을 사용할 수 있습니다.

DRAW_NONE DRAW_NONE

DRAW_NONE 그리기 스타일은 "데이터 창"에서 지표의 값을 계산하고 표시해야 하지만 플로팅이 필요하지 않은 경우에 사용됩니다.

DRAW_LINE DRAW_LINE

DRAW_LINE 스타일은 지표의 버퍼 값을 선으로 표시하는 데 사용됩니다.