Olá, indicador interessante. Estou gostando do aspecto matemático de realmente usar um modelo de projeção nos gráficos. Como ainda não tenho muita experiência com código, gostaria de saber como você configuraria o modelo para "voltar" e fazer a curva de previsão que ele teria feito há um determinado número de ticks (digamos, 100). Dessa forma, ele poderia ser aplicado a vários gráficos e dar uma ideia de quanto a realidade varia em relação ao modelo, talvez usar isso para identificar algumas características de um mercado em que o modelo funciona bem etc.
Eu o analisei no histórico e descobri que o indicador não leva em conta a tendência, ele previu contra a tendência por vários milhares de pontos de cinco dígitos. Na minha opinião, ele deve ser usado com um indicador como MA/CCI/Bollinger Bands, em que o extrapolador confirmará o sinal, caso contrário, ele pode se tornar um ralo
Supõe-se que ele seja mais bem utilizado em períodos de tempo mais altos. No D1, ele previu com incrível precisão durante um mês, mas quando a tendência começou, fiquei muito desapontado (veja o último parágrafo).
Também estou muito curioso, se alguém usa extrapoladores em seu TS, como exatamente? E quão promissora é essa direção de busca do Graal?
De forma puramente intuitiva, parece que isso é o que é necessário, mas, de alguma forma, os testes e as previsões desse extrapolador não se correlacionam muito bem com a realidade, pelo menos para mim foi o que aconteceu...
Você poderia me dizer qual é a escolha dos extrapoladores e qual deles é o mais preciso? Quero dizer, provavelmente não apenas as séries de Fourier podem ser decompostas, as formas são infinitas. Por exemplo, você pode ir das formas mais simples e começar a partir do cruzamento de MA ou MACD e, assim, prever a curva, e se você não for preguiçoso, então diferentes decomposições empíricas, em seguida, a média e, em seguida, novamente copponing.... Teoricamente, posso imaginar como fazer isso, mas se eu começar a tentar codificá-lo, não conseguirei fazê-lo em um ano((((
Seria legal se o extrapolador definisse a distribuição de probabilidade para o futuro próximo em vez de desenhar uma linha.
No início, ele parecia prever bem, mas recentemente começou a apresentar uma linha reta, embora nos terminais antigos, que não uso há muito tempo, fosse ainda melhor - a linha vermelha fica quase ao lado do preço. Por que isso acontece? Provavelmente por causa das atualizações ou porque está tão codificado que fica velho com o tempo.
Para ver a qualidade de sua previsão, adicionei mais um parâmetro Start ao código - a partir de qual barra começar em vez da barra zero.
Também adicionei um manipulador de eventos para o movimento do mouse.
Para iniciá-lo, basta pressionar Ctrl e mover o mouse (aconselho a ativar a mira) - sua posição no gráfico será Start.
É muito engraçado observá-lo em dinâmica.
Para desativá-lo, basta pressionar qualquer tecla, exceto Ctrl
//+--------------------------------------------------------------------------------------+ //| Fourier_Extrapolator_of_Price.mq5 | //| Copyright 2010, gpwr | //+--------------------------------------------------------------------------------------+ // adicionada a possibilidade de deslocar o Start (pressione CTRL) #property copyright "gpwr" #property version "1.00" #property description "Extrapolação de preços abertos por modelo trigonométrico (multitone)" #property indicator_chart_window #property indicator_buffers 2 #property indicator_plots 2 //--- outputs do modelo futuro #property indicator_label1 "Modeled future" #property indicator_type1 DRAW_LINE #property indicator_color1 Red #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- saídas de modelos passados #property indicator_label2 "Modeled past" #property indicator_type2 DRAW_LINE #property indicator_color2 Blue #property indicator_style2 STYLE_SOLID #property indicator_width2 1 //--- constantes globais #define pi 3.141592653589793238462643383279502884197169399375105820974944592 //--- entradas do indicador input int Npast =300; // Barras passadas, às quais a série trigonométrica é ajustada input int Nfut =50; // Barras futuras previstas input int Nharm =20; // Narmônicos no modelo input double FreqTOL =0.00001; // Tolerância dos cálculos de frequência input int Start =0; // A partir de qual barra começamos //--- variáveis globais int N; int key=0; int start=0; //--- buffers de indicadores double ym[],xm[]; //+------------------------------------------------------------------+ //| Função de inicialização personalizada do indicador | //+------------------------------------------------------------------+ void OnInit() { //--- inicializar variáveis globais N=MathMax(Npast,Nfut+1);
//--- mapeamento de buffers de indicadores 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; } //+------------------------------------------------------------------+ //| Função de iteração de indicador personalizado | //+------------------------------------------------------------------+ 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[]) { { // Verificar se há dados insuficientes
if(rates_total<Npast) { Print("Error: não há barras suficientes no histórico!"); return(0); }
//--- inicializar os buffers do indicador para EMPTY_VALUE ArrayInitialize(xm,EMPTY_VALUE); ArrayInitialize(ym,EMPTY_VALUE);
//--- disponibilizar todos os preços MqlRates rates[]; ArraySetAsSeries(rates,true); if(CopyRates(NULL,0,start,Npast,rates)<=0) return(0);
//--- ciclo principal //--- preparar dados de entrada 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;
//--- inicializar as saídas do modelo for(int i=0;i<N<N;i++) { { xm[i+start]=av; if(i<=Nfut) ym[i+start]=av; }
//--- ajustar o modelo trigonométrico e calcular as previsões 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); } //--- manipulador de eventos para pressionar Ctrl e mover o mouse void OnChartEvent(const int id, // identificador de evento const long& lparam, // parâmetro de evento do tipo long const double& dparam, // parâmetro de evento do tipo double const string& sparam // parâmetro de evento do tipo string )
//--- make all prices available MqlRates rates[]; ArraySetAsSeries(rates,true); if(CopyRates(NULL,0,start,Npast,rates)<=0) return;
//--- main cycle //--- prepare input data 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;
//--- inicialize as saídas do modelo for(int i=0;i<N;i++) { xm[i+start]=av; if(i<=Nfut) ym[i+start]=av; }
//--- ajuste o modelo trigonométrico e calcule as previsões 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); } } } }
//+------------------------------------------------------------------+ //| Algoritmo de Quinn e Fernandes para encontrar a frequência | //+------------------------------------------------------------------+ 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); } //+------------------------------------------------------------------+ //| Ajuste de mínimos quadrados de séries trigonométricas | //+------------------------------------------------------------------+ 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 { // calculando a, b e 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(PERIOD_H1); case 240: return(PERIOD_H4); case 1440: return(PERIOD_D1); case 10080: return(PERIOD_W1); case 43200: return(PERIOD_MN1);
case 2: return(PERIOD_M2); case 3: return(PERIOD_M3); case 4: return(PERIOD_M4); case 6: return(PERIOD_M6); case 10: return(PERIOD_M10); case 12: return(PERIOD_M12); case 16385: return(PERIOD_H1); case 16386: return(PERIOD_H2); case 16387: return(PERIOD_H3); case 16388: return(PERIOD_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); } }
Para login e uso do site MQL5.com, você deve ativar o uso de cookies.
Ative esta opção no seu navegador, caso contrário você não poderá fazer login.
Você entrou na conta. A autenticação de dois fatores foi desativada. Configure-a novamente e escaneie um novo código QR ou continue com a autenticação de dois fatores desativada.
Olá, indicador interessante. Estou gostando do aspecto matemático de realmente usar um modelo de projeção nos gráficos. Como ainda não tenho muita experiência com código, gostaria de saber como você configuraria o modelo para "voltar" e fazer a curva de previsão que ele teria feito há um determinado número de ticks (digamos, 100). Dessa forma, ele poderia ser aplicado a vários gráficos e dar uma ideia de quanto a realidade varia em relação ao modelo, talvez usar isso para identificar algumas características de um mercado em que o modelo funciona bem etc.
Sim, eu uso o Windows 7, vou dar uma olhada
talvez você queira executar o mt5 no modo portátil:
terminal.exe /portable
você obterá o indicador funcionando no diretório atual do mt5 - útil para a instalação do pendrive
modificação para fazer com que ele se desloque para trás no tempo para testar sua capacidade de previsão:
na linha 32, insira:
input int TimeShift = 10; // quantas barras são deslocadas para trás, útil para avaliar a previsibilidade do indicador
na linha 54 substitua:
PlotIndexSetInteger(0, PLOT_SHIFT, Nfut);
por:
PlotIndexSetInteger(0, PLOT_SHIFT, Nfut - TimeShift);
na linha 55 insira:
PlotIndexSetInteger(1, PLOT_SHIFT, -TimeShift);
na linha 87 replace:
if(CopyRates(NULL, 0, 0, Npast, rates) <= 0) return(0);
with:
if(CopyRates(NULL, 0, TimeShift, Npast, rates) <= 0) return(0);
Vale a pena dar uma olhada.
Quem o utiliza nas negociações?
Eu o analisei no histórico e descobri que o indicador não leva em conta a tendência, ele previu contra a tendência por vários milhares de pontos de cinco dígitos. Na minha opinião, ele deve ser usado com um indicador como MA/CCI/Bollinger Bands, em que o extrapolador confirmará o sinal, caso contrário, ele pode se tornar um ralo
Supõe-se que ele seja mais bem utilizado em períodos de tempo mais altos. No D1, ele previu com incrível precisão durante um mês, mas quando a tendência começou, fiquei muito desapontado (veja o último parágrafo).
Obrigado
Vale a pena dar uma olhada.
Quem o utiliza no comércio?
Também estou muito curioso, se alguém usa extrapoladores em seu TS, como exatamente? E quão promissora é essa direção de busca do Graal?
De forma puramente intuitiva, parece que isso é o que é necessário, mas, de alguma forma, os testes e as previsões desse extrapolador não se correlacionam muito bem com a realidade, pelo menos para mim foi o que aconteceu...
Você poderia me dizer qual é a escolha dos extrapoladores e qual deles é o mais preciso? Quero dizer, provavelmente não apenas as séries de Fourier podem ser decompostas, as formas são infinitas. Por exemplo, você pode ir das formas mais simples e começar a partir do cruzamento de MA ou MACD e, assim, prever a curva, e se você não for preguiçoso, então diferentes decomposições empíricas, em seguida, a média e, em seguida, novamente copponing.... Teoricamente, posso imaginar como fazer isso, mas se eu começar a tentar codificá-lo, não conseguirei fazê-lo em um ano((((
Seria legal se o extrapolador definisse a distribuição de probabilidade para o futuro próximo em vez de desenhar uma linha.
Seria legal se o extrapolador definisse a distribuição de probabilidade para o futuro próximo, em vez de desenhar uma linha.
Acho que poderia ser assim, se você praticar no photoshop)))))
Indicador interessante! Agradeço ao seu criador.
Para ver a qualidade de sua previsão, adicionei mais um parâmetro Start ao código - a partir de qual barra começar em vez da barra zero.
Também adicionei um manipulador de eventos para o movimento do mouse.
Para iniciá-lo, basta pressionar Ctrl e mover o mouse (aconselho a ativar a mira) - sua posição no gráfico será Start.
É muito engraçado observá-lo em dinâmica.
Para desativá-lo, basta pressionar qualquer tecla, exceto Ctrl
//+--------------------------------------------------------------------------------------+
//| Fourier_Extrapolator_of_Price.mq5 |
//| Copyright 2010, gpwr |
//+--------------------------------------------------------------------------------------+
// adicionada a possibilidade de deslocar o Start (pressione CTRL)
#property copyright "gpwr"
#property version "1.00"
#property description "Extrapolação de preços abertos por modelo trigonométrico (multitone)"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 2
//--- outputs do modelo futuro
#property indicator_label1 "Modeled future"
#property indicator_type1 DRAW_LINE
#property indicator_color1 Red
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- saídas de modelos passados
#property indicator_label2 "Modeled past"
#property indicator_type2 DRAW_LINE
#property indicator_color2 Blue
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- constantes globais
#define pi 3.141592653589793238462643383279502884197169399375105820974944592
//--- entradas do indicador
input int Npast =300; // Barras passadas, às quais a série trigonométrica é ajustada
input int Nfut =50; // Barras futuras previstas
input int Nharm =20; // Narmônicos no modelo
input double FreqTOL =0.00001; // Tolerância dos cálculos de frequência
input int Start =0; // A partir de qual barra começamos
//--- variáveis globais
int N;
int key=0;
int start=0;
//--- buffers de indicadores
double ym[],xm[];
//+------------------------------------------------------------------+
//| Função de inicialização personalizada do indicador |
//+------------------------------------------------------------------+
void OnInit()
{
//--- inicializar variáveis globais
N=MathMax(Npast,Nfut+1);
//--- mapeamento de buffers de indicadores
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;
}
//+------------------------------------------------------------------+
//| Função de iteração de indicador personalizado |
//+------------------------------------------------------------------+
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[])
{
{ // Verificar se há dados insuficientes
if(rates_total<Npast)
{
Print("Error: não há barras suficientes no histórico!");
return(0);
}
//--- inicializar os buffers do indicador para EMPTY_VALUE
ArrayInitialize(xm,EMPTY_VALUE);
ArrayInitialize(ym,EMPTY_VALUE);
//--- disponibilizar todos os preços
MqlRates rates[];
ArraySetAsSeries(rates,true);
if(CopyRates(NULL,0,start,Npast,rates)<=0) return(0);
//--- ciclo principal
//--- preparar dados de entrada
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;
//--- inicializar as saídas do modelo
for(int i=0;i<N<N;i++)
{
{ xm[i+start]=av;
if(i<=Nfut) ym[i+start]=av;
}
//--- ajustar o modelo trigonométrico e calcular as previsões
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);
}
//--- manipulador de eventos para pressionar Ctrl e mover o mouse
void OnChartEvent(const int id, // identificador de evento
const long& lparam, // parâmetro de evento do tipo long
const double& dparam, // parâmetro de evento do tipo double
const string& sparam // parâmetro de evento do tipo 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);
//--- make all prices available
MqlRates rates[];
ArraySetAsSeries(rates,true);
if(CopyRates(NULL,0,start,Npast,rates)<=0) return;
//--- main cycle
//--- prepare input data
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;
//--- inicialize as saídas do modelo
for(int i=0;i<N;i++)
{
xm[i+start]=av;
if(i<=Nfut) ym[i+start]=av;
}
//--- ajuste o modelo trigonométrico e calcule as previsões
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);
}
}
}
}
//+------------------------------------------------------------------+
//| Algoritmo de Quinn e Fernandes para encontrar a frequência |
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
//| Ajuste de mínimos quadrados de séries trigonométricas |
//+------------------------------------------------------------------+
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
{
// calculando a, b e 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(PERIOD_H1);
case 240: return(PERIOD_H4);
case 1440: return(PERIOD_D1);
case 10080: return(PERIOD_W1);
case 43200: return(PERIOD_MN1);
case 2: return(PERIOD_M2);
case 3: return(PERIOD_M3);
case 4: return(PERIOD_M4);
case 6: return(PERIOD_M6);
case 10: return(PERIOD_M10);
case 12: return(PERIOD_M12);
case 16385: return(PERIOD_H1);
case 16386: return(PERIOD_H2);
case 16387: return(PERIOD_H3);
case 16388: return(PERIOD_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);
}
}
...