English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
퍼지 로직 (Fuzzy Logic)을 이용한 인디케이터 생성의 간단한 예

퍼지 로직 (Fuzzy Logic)을 이용한 인디케이터 생성의 간단한 예

MetaTrader 5트레이딩 | 5 7월 2021, 16:59
88 0
Максим Востров
Максим Востров

소개

금융 시장 분석을 위한 다양한 방법의 사용은 최근 몇 년 동안 트레이더들 사이에서 점점 더 인기를 얻고 있습니다. 나는 몇 개의 코드 라인을 작성하여 좋은 인디케이터를 만드는 방법을 보여주고 싶습니다. 또한 fuzzy logic의 기본 사항을 간략하게 설명하겠습니다.

이 문제에 관심이 있고 더 깊이 탐구하고 싶은 사람은 누구나 다음 글들을 읽어볼 수 있습니다.

1.  Leonenkov А. "MATLAB 및 fuzzyTECH의 퍼지 시뮬레이션"(러시아어).
2. Bocharnikov V. "퍼지 기술 (Fuzzy Technology): 수학적 배경. 경제학 시뮬레이션 실습"(in Russian).
3.  S.N. Sivanandam, S. Sumathi, S.N. Deepa. MATLAB을 사용한 퍼지 로직 (Fuzzy Logic) 소개.
4.  C. Kahraman. 응용 프로그램이있는 퍼지 엔지니어링 경제학 (퍼지 및 소프트 컴퓨팅 연구).


1. 퍼지 로직 (Fuzzy Logic) 기초

"... 조금만 더 ...", "... 너무 빠르다 ...", "... 거의 아무것도 ..."와 같은 단순한 표현의 의미를 어떻게 컴퓨터에 설명할 수 있습니까? 사실, 퍼지 세트 이론 요소를 사용하거나 소위 "멤버십 기능"을 사용하면 가능합니다. 다음은 А의 예입니다. Leonenkov의 책:

"뜨거운 커피" 라는 문구의 멤버십 기능을 설명해 봅시다. 커피 온도는 0도 이하의 온도에서는 얼음으로 바뀌고 그 이상의 온도에서는 얼음으로 변하기 때문에 섭씨 0도에서 100도 사이의 범위로 간주되어야 합니다. 100도 이상의 온도에서는 증발하니까요. 온도가 20도인 커피 한 잔은 뜨겁다고 할 수 없습니다. 즉, "뜨거운" 카테고리의 멤버십 기능은 0과 같고 온도가 70 도인 커피 한 잔은 확실히 "뜨거운" 범주이므로 이 경우 함수 값은 1과 같습니다.

이 두 극단 값 사이에 있는 온도 값은 상황이 그렇게 명확하지 않습니다. 어떤 사람들은 온도가 55 도인 커피 한 잔을 "뜨겁다"고 생각하는 반면, 다른 사람들은 "그다지 뜨겁지 않다"고 생각할 수 있습니다. 이것이 "모호함 (fuzziness)"입니다.

그럼에도 불구하고 우리는 멤버십 함수의 대략적인 모습을 상상할 수 있습니다. 이는 "단조롭게 증가"합니다.


위 그림은 "piecewise linear" 멤버십 기능을 보여줍니다.

따라서 함수는 다음 분석 표현식으로 정의 할 수 있습니다.


이러한 기능을 인디케이터에 사용할 것입니다.


2. 멤버십 기능

어떤 식으로든 기술 인디케이터의 임무는 현재 시장 상태 (평탄한, 상승 추세, 하락 추세)를 결정하고 시장 진입/출구 신호를 생성하는 것입니다. 멤버십 기능의 도움으로 어떻게 할 수 있습니까? 충분히 쉽습니다.

먼저 경계 조건을 정의해야 합니다. 다음과 같은 경계 조건이 있습니다.«100 % 상승 추세»의 경우 매개 변수가 8, 0.08, SMA, Close, Envelopes 상단 경계와 함께 일반적인 가격 (H+L+C)/3을 기준으로 기간 2를 갖는 EMA의 교차점이 됩니다. 반면, «100% 하향 추세»의 경우 Envelopes 하단 경계가 있는 동일한 EMA의 교차점이 됩니다. 이러한 조건 사이에 있는 모든 것은 평평한 것으로 간주됩니다. 매개 변수가 32, 0.15, SMA, Close 인 봉투를 하나 더 추가해 보겠습니다. 

결과적으로 두 개의 동일한 멤버십 기능을 얻게 됩니다. 두 기능이 모두 1이면 매수 신호가 활성화되고 두 기능이 각각 -1이면 매도 신호가 활성화됩니다. -1에서 1까지의 범위로 차트를 작성하는 것이 편리하므로 결과 차트는 두 함수 F(x)= (f1(x)+f2(x))/2의 산술 평균으로 얻어집니다.

이것이 차트에서 보이는 방식입니다.


이 경우 멤버십 기능은 다음과 같은 그래픽 표현을 갖습니다.


분석적으로 다음과 같이 작성할 수 있습니다.

,

여기서 a와 b는 각각 위쪽과 아래쪽 envelope 선이고 х는 EMA (2)의 값입니다.

함수가 정의되었으므로 이제 인디케이터 코드 작성으로 이동할 수 있습니다.


3. 프로그램 코드 생성

우선 무엇을 그리고 어떻게 그릴 것인지 정의해야 합니다.

멤버십 함수 계산 결과는 각각 빨간색과 파란색의 선으로 표시됩니다.

산술 평균은 제로 라인에서 히스토그램으로 표시되고 결과 함수 값에 따라 5 가지 색상 중 하나로 그려집니다.

DRAW_COLOR_HISTOGRAM 그리기 스타일을 사용합니다.

값이 1 또는 -1 인 히스토그램 바 위에 구매/종료 신호로 파란색 및 빨간색 직사각형을 그립니다.

이제 MetaEditor를 실행하고 시작할 시간입니다. 새로 만들기->사용자 지정 인디케이터->다음 ... "매개 변수" 필드를 채웁니다.


 버퍼를 만듭니다.


"마침" 버튼을 클릭하면 소스 코드를 받고 개선을 시작합니다.

먼저 버퍼수를 정의해보겠습니다. 그중 7 개는 이미 마법사에 의해 생성되었습니다 (데이터 5 개, 색상 2 개). 5 개 더 필요합니다.

#property indicator_minimum -1.4 // Setting fractional values
#property indicator_maximum 1.4  // Expert Advisors wizard ignores fractional parts for some reason
#property indicator_buffers 12   // Changing the value from 7 to 12 (5 more buffers have been added)
입력 매개 변수를 편집해보겠습니다.
input string txt1="----------";
input int                  Period_Fast=8;
input ENUM_MA_METHOD        Method_Fast = MODE_SMA; /*Smoothing method*/ //moving average smoothing method 
input ENUM_APPLIED_PRICE    Price_Fast  = PRICE_CLOSE;
input double               Dev_Fast=0.08;
input string txt2="----------";
input int                  Period_Slow=32;
input ENUM_MA_METHOD        Method_Slow = MODE_SMA;
input ENUM_APPLIED_PRICE    Price_Slow  = PRICE_CLOSE;
input double               Dev_Slow=0.15;  /*Deviation parameter*/
input string txt3="----------";
input int                  Period_Signal=2;
input ENUM_MA_METHOD        Method_Signal = MODE_EMA;
input ENUM_APPLIED_PRICE    Price_Signal  = PRICE_TYPICAL;
input string txt4="----------";

선언된 변수 뒤에 오는 주석은 매우 편리합니다. 주석 텍스트가 인디케이터 매개 변수 창에 삽입됩니다.

목록을 만들 수 있는 가능성도 매우 유용합니다.


인디케이터 핸들 및 버퍼에 대한 변수 예약:

int Envelopes_Fast;     // Fast envelope
int Envelopes_Slow;     // Slow envelope
int MA_Signal;          // Signal line

double Env_Fast_Up[];   // Fast envelope upper border
double Env_Fast_Dn[];   // Fast envelope lower border

double Env_Slow_Up[];   // Slow envelope upper border
double Env_Slow_Dn[];   // Slow envelope lower border

double Mov_Sign[];      // Signal line

이제 OnInit() 함수로 이동합니다.

몇 가지 아름다움을 추가해 보겠습니다. 인디케이터 이름을 지정하고 추가 소수점 0을 제거합니다.

IndicatorSetInteger(INDICATOR_DIGITS,1); // setting display accuracy, we do not need some outstanding accuracy values 
string name;                           // indicator name 
StringConcatenate(name, "FLE ( ", Period_Fast, " , ", Dev_Fast, " | ", Period_Slow, " , ", Dev_Slow, " | ", Period_Signal, " )"); 
IndicatorSetString(INDICATOR_SHORTNAME,name);

누락된 버퍼를 추가합니다.

SetIndexBuffer(7,Env_Fast_Up,INDICATOR_CALCULATIONS);
SetIndexBuffer(8,Env_Fast_Dn,INDICATOR_CALCULATIONS);
SetIndexBuffer(9,Env_Slow_Up,INDICATOR_CALCULATIONS);
SetIndexBuffer(10,Env_Slow_Dn,INDICATOR_CALCULATIONS);
SetIndexBuffer(11,Mov_Sign,INDICATOR_CALCULATIONS); 

INDICATOR_CALCULATIONS 매개 변수는 버퍼 데이터가 중간 계산에만 필요함을 의미합니다. 차트에 표시되지 않습니다.

색상 버퍼가 있는 인디케이터가 선언되는 방법에 유의하십시오.

SetIndexBuffer(4,SignalBuffer1,INDICATOR_DATA);      // All indicator buffers at first 
SetIndexBuffer(5,SignalBuffer2,INDICATOR_DATA);      // as this is Color Histogram2, then it has 2 data buffers
SetIndexBuffer(6,SignalColors,INDICATOR_COLOR_INDEX);// the color buffer comes next.

핸들 채우기:

Envelopes_Fast = iEnvelopes(NULL,0,Period_Fast,0,Method_Fast,Price_Fast,Dev_Fast);
Envelopes_Slow = iEnvelopes(NULL,0,Period_Slow,0,Method_Slow,Price_Slow,Dev_Slow);
MA_Signal      = iMA(NULL,0,Period_Signal,0,Method_Signal,Price_Signal);

OnInit() 함수의 모든 작업이 끝났습니다.

이제 멤버십 함수 값을 계산할 함수를 만들어 보겠습니다.

double Fuzzy(double x,double a, double c)
{
double F;
     if (a<x)          F=1;                 // 100% uptrend
else if (x<=a && x>=c)  F=(1-2*(a-x)/(a-c));// Flat
else if (x<c)           F=-1;               // 100% downtrend
return (F);
}

준비가 끝났습니다. 변수와 버퍼가 선언되고 핸들이 할당됩니다.

이제 OnCalculate() 기본 함수를 진행할 차례입니다.

먼저 필요한 인디케이터의 값을 중간 버퍼에 적어 보겠습니다. CopyBuffer() 함수 사용:

CopyBuffer(Envelopes_Fast,  // Indicator handle
           UPPER_LINE,      // Indicator buffer
           0,              // The point to start 0 - from the very beginning
           rates_total,    // How many to be copied - All 
           Env_Fast_Up);   // The buffer the values are written in
// - the rest are done in a similar way
CopyBuffer(Envelopes_Fast,LOWER_LINE,0,rates_total,Env_Fast_Dn);
CopyBuffer(Envelopes_Slow,UPPER_LINE,0,rates_total,Env_Slow_Up);
CopyBuffer(Envelopes_Slow,LOWER_LINE,0,rates_total,Env_Slow_Dn);
CopyBuffer(MA_Signal,0,0,rates_total,Mov_Sign);

 여기에 계산 최적화를 위한 코드를 추가해야 합니다 (마지막 바의 재계산만 수행됨).

// declaring start variable for storing the index of the bar, recalculation of the indicator buffers will be
// carried out from.

int start;              
if (prev_calculated==0// in case no bars have been calculated
    {
    start = Period_Slow; // not all indicators have been calculated up to this value, therefore, there is no point in executing the code
    }
else start=prev_calculated-1;

for (int i=start;i<rates_total;i++)
      {
      // All remaining code will be written here
      }

코드가 많이 남지 않았습니다.

x, a, b 매개 변수 설정, 멤버십 함수 값 계산 수행 및 적절한 버퍼에 쓰기:
double x = Mov_Sign[i]; // Signal
// Setting the first membership function parameters:
double a1 = Env_Fast_Up[i]; // Upper border
double b1 = Env_Fast_Dn[i];
// setting the first membership function value and writing it to the buffer
Rule1Buffer[i] = Fuzzy(x,a1,b1);
// Setting the second membership function parameters:
double a2 = Env_Slow_Up[i]; // Upper border
double b2 = Env_Slow_Dn[i];
// setting the second membership function value and writing it to the buffer
Rule2Buffer[i] = Fuzzy(x,a2,b2);

두 개의 표시선이 만들어집니다.

이제 결과값을 계산해 봅시다.

ResultBuffer[i] = (Rule1Buffer[i]+Rule2Buffer[i])/2;

그런 다음 히스토그램 바를 적절한 색상으로 칠해야 합니다. 5 가지 색상이 있으므로 ResultColors [i]는 0에서 4까지의 값을 가질 수 있습니다.

일반적으로 가능한 색상 수는 64 개입니다. 따라서 창의력을 발휘할 수 있는 좋은 기회입니다.

for (int ColorIndex=0;ColorIndex<=4;ColorIndex++) 
    { 
    if (MathAbs(ResultBuffer[i])>0.2*ColorIndex && MathAbs(ResultBuffer[i])<=0.2*(ColorIndex+1)) 
        { 
        ResultColors[i] = ColorIndex; 
        break; 
        } 
    }

그런 다음 신호 직사각형을 그려야 합니다. DRAW_COLOR_HISTOGRAM2 그리기 스타일을 사용합니다.

히스토그램 바가 있는 두 개의 데이터 버퍼와 그 사이에 구축되는 하나의 색상 버퍼가 있습니다.

데이터 버퍼 값은 항상 동일합니다. 매수 신호의 경우 1.1 및 1.3, 매도 신호의 경우 -1.1 및 -1.3입니다.

EMPTY_VALUE는 신호 부재를 의미합니다.

      if (ResultBuffer[i]==1)
        {
        SignalBuffer1[i]=1.1;
        SignalBuffer2[i]=1.3;
        SignalColors[i]=1;
        }
      else if (ResultBuffer[i]==-1)
        {
        SignalBuffer1[i]=-1.1;
        SignalBuffer2[i]=-1.3;
        SignalColors[i]=0;
        }
      else
        {
        SignalBuffer1[i]=EMPTY_VALUE;
        SignalBuffer2[i]=EMPTY_VALUE;
        SignalColors[i]=EMPTY_VALUE;
        }

"컴파일"을 클릭하고 짜잔!



결론

그 밖에 무엇을 추가 할 수 있습니까? 이 기사에서는 fuzzy logic에 대한 가장 기본적인 접근 방식을 다루었습니다.

여기에는 다양한 실험을 위한 충분한 공간이 있습니다. 예를 들어 다음 함수를 사용할 수 있습니다.


그것에 대한 분석적 표현을 작성하고 적절한 조건을 찾는 것이 어렵지 않을 것이라고 생각합니다.

행운을 빕니다!

MetaQuotes 소프트웨어 사를 통해 러시아어가 번역됨.
원본 기고글: https://www.mql5.com/ru/articles/178

파일 첨부됨 |
표준 라이브러리 클래스를 사용하여 나만의 Market Watch 만들기 표준 라이브러리 클래스를 사용하여 나만의 Market Watch 만들기
새로운 MetaTrader 5 클라이언트 터미널과 MQL5 언어는 트레이더에게 시각적 정보를 제공 할 수 있는 새로운 기회를 제공합니다. 이 기사에서는 차트에 임의의 텍스트 정보를 표시하는 모든 작업을 처리하는 확장 가능한 범용 클래스 집합을 제안합니다. Market Watch 지표의 예가 표시됩니다.
MQL5 마법사: 프로그래밍 없이 Expert Advisor 만들기 MQL5 마법사: 프로그래밍 없이 Expert Advisor 만들기
프로그래밍에 시간을 낭비하지 않고 거래 전략을 시도하고 싶습니까? MQL5 마법사에서 거래 신호 유형을 선택하고 추적 포지션 및 자금 관리 모듈을 추가하면 작업이 완료됩니다! 고유한 모듈 구현을 생성하거나 작업 서비스를 통해 주문하고 새 모듈을 기존 모듈과 결합합니다.
추가 버퍼를 사용하지 않고 중간 계산을 위한 평균 가격 시리즈 추가 버퍼를 사용하지 않고 중간 계산을 위한 평균 가격 시리즈
이 문서는 가장 단순한 클래스와 단일 유형 클래스로 압축된 평균화의 전통적이고 특이한 알고리즘에 대해 설명합니다. 거의 모든 지표 개발에서 보편적으로 사용하기 위한 것입니다. 제안된 클래스가 사용자 지정 및 기술 지표의 '대량' 호출에 대한 좋은 대안이 되기를 바랍니다.
성장하는 신경 가스: MQL5 구현 성장하는 신경 가스: MQL5 구현
이 글은 성장 신경 가스 (GNG)라고하는 클러스터링의 적응 알고리즘을 구현하는 MQL5 프로그램을 개발하는 방법의 예를 보여줍니다. 이 글은 언어 문서를 공부하고 신경 정보학 분야에서 특정 프로그래밍 기술과 기본 지식을 보유한 사용자를 대상으로 합니다.