흥미로운 지표네요. 차트에서 실제로 투영 모델을 사용하는 수학적 측면이 마음에 듭니다. 아직 코드에 대한 경험이 많지 않기 때문에 모델을 "뒤로"하여 특정 틱 수 (예 : 100) 전에 만들었을 예측 곡선을 수행하도록 설정하는 방법이 궁금합니다. 이렇게 하면 다양한 차트에 적용하여 현실이 모델과 얼마나 다른지 알 수 있고, 모델이 잘 작동하는 시장의 특성을 파악하는 데 사용할 수도 있습니다.
나는 그것을 역사를 통해 실행했습니다-지표가 추세를 전혀 고려하지 않고 수천 개의 5 자리 포인트에 대한 추세에 대해 예측했으며, 제 생각에는 외삽기가 신호를 확인하는 MA / CCI / 볼린저 밴드와 같은 지표와 함께 사용해야하며 그렇지 않으면 배수구로 판명 될 수 있습니다.
더 높은 시간대에 가장 잘 사용해야하며 D1에서는 한 달 동안 놀라운 정확도로 예측했지만 추세가 시작되었을 때 매우 실망했습니다 (마지막 단락 참조).
또한 TS에서 외삽기를 사용하는 사람이 있다면 정확히 어떻게 사용하는지 매우 궁금합니다. 그리고 성배를 찾는이 방향은 얼마나 유망합니까?
순전히 직관적으로 이것이 필요한 것 같지만 어떻게 든이 외삽기의 테스트와 예측은 현실과 매우 잘 맞지 않는 것으로 나타났습니다. 적어도 저에게는 그렇게 밝혀졌습니다.
외삽기의 선택은 무엇이며 그중 가장 정확한 것은 무엇인지 말씀해 주시겠습니까? 푸리에 급수 만 분해 할 수있는 것이 아니라 방법은 무한합니다. 예를 들어, 가장 간단한 방법에서 이동하여 MA 또는 MACD의 교차점에서 시작하여 곡선을 예측하고 게으르지 않으면 다른 경험적 분해, 평균화 및 다시 코포닝.... 이론적으로는 어떻게하는지 상상할 수 있지만 코딩을 시작하면 1 년 안에 할 수 없을 것입니다((((
처음에는 잘 예측하는 것처럼 보였지만 최근에는 직선을 제공하기 시작했지만 오랫동안 사용하지 않은 오래된 단말기에서는 빨간색 선이 거의 가격 옆에있는 것이 더 좋았습니다. 왜 이런 일이 발생합니까? 아마도 업데이트 때문이거나 코딩이 너무 오래되어 시간이 지남에 따라 오래 되었기 때문일 것입니다.
예측의 품질을 확인하기 위해 코드에 시작 매개변수(0 막대 대신 어느 막대에서 시작할지)를 하나 더 추가했습니다.
또한 마우스 움직임에 대한 이벤트 핸들러도 추가했습니다.
시작하려면 Ctrl 키를 누르고 마우스를 움직이기만 하면 됩니다(십자선을 활성화하는 것이 좋습니다) - 차트에서 해당 위치는 시작이 됩니다.
역동적으로 보는 것은 매우 재미 있습니다.
끄려면 Ctrl을 제외한 아무 키나 누르기만 하면 됩니다.
//+--------------------------------------------------------------------------------------+ //| 푸리에_추정치_of_가격.mq5 | //| 저작권 2010, gpwr | //+--------------------------------------------------------------------------------------+ // 시작 이동 가능성 추가 (CTRL 누르기) #재산 저작권 "gpwr" #재산 버전 "1.00" #property description "삼각(멀티톤) 모델에 의한 시가 추정" #property indicator_chart_window #property indicator_buffers 2 #property indicator_plots 2 //--- 미래 모델 출력 #property indicator_label1 "모델링된 미래" #property indicator_type1 DRAW_LINE #property indicator_color1 Red #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- 과거 모델 출력 #property indicator_label2 "모델링된 과거" #property indicator_type2 DRAW_LINE #property indicator_color2 Blue #property indicator_style2 STYLE_SOLID #property indicator_width2 1 //--- 글로벌 상수 #define pi 3.141592653589793238462643383279502884197169399375105820974944592 //--- 인디케이터 입력값 입력값 Npast =300; // 삼각급수가 적용된 과거 막대 입력값 Nfut =50; // 예측된 미래 막대 입력값 Nharm =20; // 모델의 나르모닉스 입력값 double FreqTOL =0.00001; // 주파수 계산의 허용 오차 input int Start =0; // 어느 막대에서 시작할지 //--- 전역 변수 int N; int key=0; int start=0; //--- 인디케이터 버퍼 double ym[],xm[]; //+------------------------------------------------------------------+ //| 커스텀 인디케이터 초기화 함수 | //+------------------------------------------------------------------+ void OnInit() { //--- 글로벌 변수 초기화 N=MathMax(Npast,Nfut+1);
//--- 인디케이터 버퍼 매핑 ArraySetAsSeries(xm,true); ArraySetAsSeries(ym,true); SetIndexBuffer(0,ym,INDICATOR_DATA); SetIndexBuffer(1,xm,INDICATOR_DATA); IndicatorSetInteger(INDICATOR_DIGITS,_Digits); IndicatorSetString(INDICATOR_SHORTNAME, "Fourier("+string(Npast)+")"); PlotIndexSetInteger(0,PLOT_SHIFT,Nfut); ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true); start=Start; } //+------------------------------------------------------------------+ //| 커스텀 인디케이터 반복 함수 | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime&. Time[], const double& Open[], const double& High[], const double& Low[], const double& Close[], const long& tick_volume[], const long& volume[], const int& spread[]) { { // 데이터 부족 여부 확인
if(rates_total<Npast) { Print("Error: 기록에 막대가 충분하지 않습니다!"); return(0); }
//--- 모든 가격을 사용할 수 있게 MqlRates rates[]; ArraySetAsSeries(rates,true); if(CopyRates(NULL,0,start,Npast,rates)<=0) return(0);
//--- 메인 사이클 //--- 입력 데이터 준비 double x[]; ArrayResize(x,Npast); double av=0; for(int i=0;i<Npast;i++) { x[i]=rates[i].open; av+=x[i]; } av/=Npast;
//--- 초기화 모델 출력 for(int i=0;i<N<N;i++) { { xm[i+start]=av; if(i<=Nfut) ym[i+start]=av; }
//--- 삼각법 모델 적합 및 예측값 계산 for(int harm=1;harm<=Nharm;harm++) { double w,m,a,b; Freq(x,Npast,w,m,a,b); for(int i=0;i<N;i++) { xm[i+start]+=m+a*MathCos(w*i)+b*MathSin(w*i); if(i<=Nfut) ym[Nfut-i+start]+=m+a*MathCos(w*i)-b*MathSin(w*i); } }
return(rates_total); } //--- Ctrl 누름과 마우스 움직임을 위한 이벤트 핸들러 void OnChartEvent(const int id, // 이벤트 식별자 const long& lparam, // long 타입의 이벤트 파라미터 const double& dparam, // double 타입의 이벤트 파라미터 const string& sparam, // string 타입의 이벤트 파라미터 )
int iBarShift(string symbol,int timeframe,datetime time,bool exact=false) { if(time<0) return(-1); ENUM_TIMEFRAMES tf=TFMigrate(timeframe); datetime Arr[],time1; CopyTime(symbol,tf,0,1,Arr); time1=Arr[0]; if(CopyTime(symbol,tf,time,time1,Arr)>0) { if(ArraySize(Arr)>2) return(ArraySize(Arr)-1); if(time<time1) return(1); else return(0); } else return(-1); } ENUM_TIMEFRAMES TFMigrate(int tf) { switch(tf) { case 0: return(PERIOD_CURRENT); case 1: return(PERIOD_M1); case 5: return(PERIOD_M5); case 15: return(PERIOD_M15); case 30: return(PERIOD_M30); case 60: return(PEROD_H1); case 240: return(PEROD_H4); case 1440: return(PEROD_D1); case 10080: return(PEROD_W1); case 43200: return(PEROD_MN1);
case 2: return(PEROD_M2); case 3: return(PEROD_M3); case 4: return(PEROD_M4); case 6: return(PERID_M6); case 10: return(PERID_M10); case 12: return(PERID_M12); case 16385: return(PERID_H1); case 16386: return(PERID_H2); case 16387: return(PERID_H3); case 16388: return(PERID_H4); case 16390: return(PERIOD_H6); case 16392: return(PERIOD_H8); case 16396: return(PERIOD_H12); case 16408: return(PERIOD_D1); case 32769: return(PERIOD_W1); case 49153: return(PERIOD_MN1); default: return(PERIOD_CURRENT); } }
흥미로운 지표네요. 차트에서 실제로 투영 모델을 사용하는 수학적 측면이 마음에 듭니다. 아직 코드에 대한 경험이 많지 않기 때문에 모델을 "뒤로"하여 특정 틱 수 (예 : 100) 전에 만들었을 예측 곡선을 수행하도록 설정하는 방법이 궁금합니다. 이렇게 하면 다양한 차트에 적용하여 현실이 모델과 얼마나 다른지 알 수 있고, 모델이 잘 작동하는 시장의 특성을 파악하는 데 사용할 수도 있습니다.
예, Windows 7을 사용하고 있습니다.
휴대용 모드에서 MT5를 실행하는 것이 좋습니다:
terminal.exe /portable
현재 mt5 디렉터리에서 표시기가 작동합니다 - 펜드라이브 설치에 유용합니다.
를 수정하여 예측 기능을 테스트하기 위한 시간에 맞춰 백 시프트되도록 합니다:
32줄에 삽입합니다:
입력 int TimeShift = 10; // 얼마나 많은 막대가 뒤로 이동하는지, 지표의 예측 가능성을 평가하는 데 유용합니다.
54줄에서 대체합니다:
PlotIndexSetInteger(0, PLOT_SHIFT, Nfut);
with:
PlotIndexSetInteger(0, PLOT_SHIFT, Nfut - TimeShift);
55번째 줄에 삽입합니다:
PlotIndexSetInteger(1, PLOT_SHIFT, -TimeShift);
87번째 줄에서 대체
if(CopyRates(NULL, 0, 0, Npast, rates) <= 0) return(0);
with:
if(CopyRates(NULL, 0, TimeShift, Npast, rates) <= 0) return(0);
살펴볼 가치가 있습니다.
누가 거래에 사용합니까?
나는 그것을 역사를 통해 실행했습니다-지표가 추세를 전혀 고려하지 않고 수천 개의 5 자리 포인트에 대한 추세에 대해 예측했으며, 제 생각에는 외삽기가 신호를 확인하는 MA / CCI / 볼린저 밴드와 같은 지표와 함께 사용해야하며 그렇지 않으면 배수구로 판명 될 수 있습니다.
더 높은 시간대에 가장 잘 사용해야하며 D1에서는 한 달 동안 놀라운 정확도로 예측했지만 추세가 시작되었을 때 매우 실망했습니다 (마지막 단락 참조).
감사합니다
살펴볼 가치가 있습니다.
거래에서 누가 사용하나요?
또한 TS에서 외삽기를 사용하는 사람이 있다면 정확히 어떻게 사용하는지 매우 궁금합니다. 그리고 성배를 찾는이 방향은 얼마나 유망합니까?
순전히 직관적으로 이것이 필요한 것 같지만 어떻게 든이 외삽기의 테스트와 예측은 현실과 매우 잘 맞지 않는 것으로 나타났습니다. 적어도 저에게는 그렇게 밝혀졌습니다.
외삽기의 선택은 무엇이며 그중 가장 정확한 것은 무엇인지 말씀해 주시겠습니까? 푸리에 급수 만 분해 할 수있는 것이 아니라 방법은 무한합니다. 예를 들어, 가장 간단한 방법에서 이동하여 MA 또는 MACD의 교차점에서 시작하여 곡선을 예측하고 게으르지 않으면 다른 경험적 분해, 평균화 및 다시 코포닝.... 이론적으로는 어떻게하는지 상상할 수 있지만 코딩을 시작하면 1 년 안에 할 수 없을 것입니다((((
외삽기가 선을 그리는 대신 가까운 미래에 대한 확률 분포를 설정하면 멋질 것입니다.
외삽기가 선을 그리는 대신 가까운 미래에 대한 확률 분포를 설정하면 멋질 것입니다.
포토샵에서 연습하면 그렇게 할 수 있을 것 같아요))))
흥미로운 지표입니다! 만든 분께 감사드립니다.
예측의 품질을 확인하기 위해 코드에 시작 매개변수(0 막대 대신 어느 막대에서 시작할지)를 하나 더 추가했습니다.
또한 마우스 움직임에 대한 이벤트 핸들러도 추가했습니다.
시작하려면 Ctrl 키를 누르고 마우스를 움직이기만 하면 됩니다(십자선을 활성화하는 것이 좋습니다) - 차트에서 해당 위치는 시작이 됩니다.
역동적으로 보는 것은 매우 재미 있습니다.
끄려면 Ctrl을 제외한 아무 키나 누르기만 하면 됩니다.
//+--------------------------------------------------------------------------------------+
//| 푸리에_추정치_of_가격.mq5 |
//| 저작권 2010, gpwr |
//+--------------------------------------------------------------------------------------+
// 시작 이동 가능성 추가 (CTRL 누르기)
#재산 저작권 "gpwr"
#재산 버전 "1.00"
#property description "삼각(멀티톤) 모델에 의한 시가 추정"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 2
//--- 미래 모델 출력
#property indicator_label1 "모델링된 미래"
#property indicator_type1 DRAW_LINE
#property indicator_color1 Red
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- 과거 모델 출력
#property indicator_label2 "모델링된 과거"
#property indicator_type2 DRAW_LINE
#property indicator_color2 Blue
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- 글로벌 상수
#define pi 3.141592653589793238462643383279502884197169399375105820974944592
//--- 인디케이터 입력값
입력값 Npast =300; // 삼각급수가 적용된 과거 막대
입력값 Nfut =50; // 예측된 미래 막대
입력값 Nharm =20; // 모델의 나르모닉스
입력값 double FreqTOL =0.00001; // 주파수 계산의 허용 오차
input int Start =0; // 어느 막대에서 시작할지
//--- 전역 변수
int N;
int key=0;
int start=0;
//--- 인디케이터 버퍼
double ym[],xm[];
//+------------------------------------------------------------------+
//| 커스텀 인디케이터 초기화 함수 |
//+------------------------------------------------------------------+
void OnInit()
{
//--- 글로벌 변수 초기화
N=MathMax(Npast,Nfut+1);
//--- 인디케이터 버퍼 매핑
ArraySetAsSeries(xm,true);
ArraySetAsSeries(ym,true);
SetIndexBuffer(0,ym,INDICATOR_DATA);
SetIndexBuffer(1,xm,INDICATOR_DATA);
IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
IndicatorSetString(INDICATOR_SHORTNAME, "Fourier("+string(Npast)+")");
PlotIndexSetInteger(0,PLOT_SHIFT,Nfut);
ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true);
start=Start;
}
//+------------------------------------------------------------------+
//| 커스텀 인디케이터 반복 함수 |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime&. Time[],
const double& Open[],
const double& High[],
const double& Low[],
const double& Close[],
const long& tick_volume[],
const long& volume[],
const int& spread[])
{
{ // 데이터 부족 여부 확인
if(rates_total<Npast)
{
Print("Error: 기록에 막대가 충분하지 않습니다!");
return(0);
}
//--- 인디케이터 버퍼를 EMPTY_VALUE로 초기화
ArrayInitialize(xm,EMPTY_VALUE);
ArrayInitialize(ym,EMPTY_VALUE);
//--- 모든 가격을 사용할 수 있게
MqlRates rates[];
ArraySetAsSeries(rates,true);
if(CopyRates(NULL,0,start,Npast,rates)<=0) return(0);
//--- 메인 사이클
//--- 입력 데이터 준비
double x[];
ArrayResize(x,Npast);
double av=0;
for(int i=0;i<Npast;i++)
{
x[i]=rates[i].open;
av+=x[i];
}
av/=Npast;
//--- 초기화 모델 출력
for(int i=0;i<N<N;i++)
{
{ xm[i+start]=av;
if(i<=Nfut) ym[i+start]=av;
}
//--- 삼각법 모델 적합 및 예측값 계산
for(int harm=1;harm<=Nharm;harm++)
{
double w,m,a,b;
Freq(x,Npast,w,m,a,b);
for(int i=0;i<N;i++)
{
xm[i+start]+=m+a*MathCos(w*i)+b*MathSin(w*i);
if(i<=Nfut) ym[Nfut-i+start]+=m+a*MathCos(w*i)-b*MathSin(w*i);
}
}
return(rates_total);
}
//--- Ctrl 누름과 마우스 움직임을 위한 이벤트 핸들러
void OnChartEvent(const int id, // 이벤트 식별자
const long& lparam, // long 타입의 이벤트 파라미터
const double& dparam, // double 타입의 이벤트 파라미터
const string& sparam, // string 타입의 이벤트 파라미터
)
{
double y;
int window=0;
datetime ttt;
if(id==CHARTEVENT_KEYDOWN) key=(int)lparam;
if(id==CHARTEVENT_MOUSE_MOVE && key==17)
{
ChartXYToTimePrice(0,(int)lparam,(int)dparam,window,ttt,y);
if(ttt!=0) start=iBarShift(NULL,0,ttt,false);
Comment("x = ",lparam,", y = ",dparam,", Price = ",y,", Price = ",y,", start = ",start);
ArrayInitialize(xm,EMPTY_VALUE);
ArrayInitialize(ym,EMPTY_VALUE);
//--- 모든 가격을 사용할 수 있게 합니다
MqlRates rates[];
ArraySetAsSeries(rates,true);
if(CopyRates(NULL,0,start,Npast,rates)<=0) return;
//--- 메인 사이클
//--- 입력 데이터 준비
double x[];
ArrayResize(x,Npast);
double av=0;
for(int i=0;i<Npast;i++)
{
x[i]=rates[i].open;
av+=x[i];
}
av/=Npast;
//--- 모델 출력 초기화
for(int i=0;i<N;i++)
{
xm[i+start]=av;
if(i<=Nfut) ym[i+start]=av;
}
//--- 삼각법 모델 적합 및 예측 계산
for(int harm=1;harm<=Nharm;harm++)
{
double w,m,a,b;
Freq(x,Npast,w,m,a,b);
for(int i=0;i<N;i++)
{
xm[i+start]+=m+a*MathCos(w*i)+b*MathSin(w*i);
if(i<=Nfut) ym[Nfut-i+start]+=m+a*MathCos(w*i)-b*MathSin(w*i);
} }
}
}
}
//+------------------------------------------------------------------+
//| Quinn and Fernandes 알고리즘으로 주파수 찾기 |
//+------------------------------------------------------------------+
void Freq(double& x[],int n,double& w,double& m,double& a,double& b)
{
double z[];
ArrayResize(z,n);
double alpha=0.0;
double beta=2.0;
z[0]=x[0]-xm[0+start];
while(MathAbs(alpha-beta)>FreqTOL)
{
alpha=beta;
z[1]=x[1]-xm[1+start]+alpha*z[0];
double num=z[0]*z[1];
double den=z[0]*z[0];
for(int i=2;i<n;i++)
{
z[i]=x[i]-xm[i+start]+alpha*z[i-1]-z[i-2];
num+=z[i-1]*(z[i]+z[i-2]);
den+=z[i-1]*z[i-1];
}
beta=num/den;
}
w=MathArccos(beta/2.0);
TrigFit(x,n,w,m,a,b);
}
//+------------------------------------------------------------------+
//| 삼각급수의 최소제곱 피팅 |
//+------------------------------------------------------------------+
void TrigFit(double& x[],int n,double& w,double& m,double& a,double& b)
{
double Sc =0.0;
double Ss=0.0;
double Scc=0.0;
double Sss=0.0;
double Scs=0.0;
double Sx=0.0;
double Sxc=0.0;
double Sxs=0.0;
for(int i=0;i<n;i++)
{
double c=MathCos(w*i);
double s=MathSin(w*i);
double dx=x[i]-xm[i+start];
Sc +=c;
Ss +=s;
Scc+=c*c;
Sss+=s*s;
Scs+=c*s;
Sx +=dx;
Sxc+=dx*c;
Sxs+=dx*s;
}
Sc /=n;
Ss /=n;
Scc/=n;
Sss/=n;
Scs/=n;
Sx /=n;
Sxc/=n;
Sxs/=n;
if(w==0.0)
{
m=Sx;
a=0.0;
b=0.0;
}
else
{
// a, b, m 계산
double den=MathPow(Scs-Sc*Ss,2)-(Scc-Sc*Sc)*(Sss-Ss*Ss);
a=((Sxs-Sx*Ss)*(Scs-Sc*Ss)-(Sxc-Sx*Sc)*(Sss-Ss*Ss))/den;
b=((Sxc-Sx*Sc)*(Scs-Sc*Sc*Ss)-(Sxs-Sx*Ss)*(Scc-Sc*Sc*Sc))/den;
m=Sx-a*Sc-b*Ss;
}
}
int iBarShift(string symbol,int timeframe,datetime time,bool exact=false)
{
if(time<0) return(-1);
ENUM_TIMEFRAMES tf=TFMigrate(timeframe);
datetime Arr[],time1;
CopyTime(symbol,tf,0,1,Arr);
time1=Arr[0];
if(CopyTime(symbol,tf,time,time1,Arr)>0)
{
if(ArraySize(Arr)>2) return(ArraySize(Arr)-1);
if(time<time1) return(1);
else return(0);
}
else return(-1);
}
ENUM_TIMEFRAMES TFMigrate(int tf)
{
switch(tf)
{
case 0: return(PERIOD_CURRENT);
case 1: return(PERIOD_M1);
case 5: return(PERIOD_M5);
case 15: return(PERIOD_M15);
case 30: return(PERIOD_M30);
case 60: return(PEROD_H1);
case 240: return(PEROD_H4);
case 1440: return(PEROD_D1);
case 10080: return(PEROD_W1);
case 43200: return(PEROD_MN1);
case 2: return(PEROD_M2);
case 3: return(PEROD_M3);
case 4: return(PEROD_M4);
case 6: return(PERID_M6);
case 10: return(PERID_M10);
case 12: return(PERID_M12);
case 16385: return(PERID_H1);
case 16386: return(PERID_H2);
case 16387: return(PERID_H3);
case 16388: return(PERID_H4);
case 16390: return(PERIOD_H6);
case 16392: return(PERIOD_H8);
case 16396: return(PERIOD_H12);
case 16408: return(PERIOD_D1);
case 32769: return(PERIOD_W1);
case 49153: return(PERIOD_MN1);
default: return(PERIOD_CURRENT);
}
}
...