Biblioteca2/Include/strategy.mqh

672 lines
51 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 14:43:36 +02:00
<EFBFBD><EFBFBD>#define ELEFANT_MAGIC 10
#define SHADOW_MAGIC 20
#define BUY_HOLD_MAGIC 30
#define SELL_HOLD_MAGIC 40
#define TREND_MAGIC 100
#define RETURN_MAGIC 200
#define GAP_MAGIC 50
#define PYTHON_MAGIC 60
class Signal//classe base
{
public:
string psymbol;
int patr;
ENUM_TIMEFRAMES timeframe;
int BuyMagic;
int SellMagic;
double myvol;
Signal(void){Init();}
void Reset(void){Init();}
virtual void InitFname(string fname){return;}
virtual void Init(void){return;}
virtual void Initspecific(double &params[]){return;}
virtual void Initfixed(string Psymbol,int Patr,ENUM_TIMEFRAMES Timeframe,int buymagic,int sellmagic,double thisvol)
{
psymbol=Psymbol;
patr=Patr;
timeframe=Timeframe;
BuyMagic=buymagic;
SellMagic=sellmagic;
myvol=thisvol;
}
virtual bool SignalCheck(ENUM_OP_TYPES direcao){return(false);}
virtual double Sl(void){return(0);}
virtual double Tp(void){return(0);}
virtual double Vol(void)
{
if (PositionSelect(psymbol))
{
//Print("Rebalan<00>o");
//return(MathAbs(PositionGetDouble(POSITION_VOLUME)-myvol));
return(0);
}
else return(myvol);
}
virtual string PrintString(void){return("");}
virtual bool ClosePosition(bool selected)
{
if ((!selected)&&(PositionSelect(psymbol))) return (true);
return(false);
}
};
class BuyHold : public Signal
{
public:
virtual bool SignalCheck(ENUM_OP_TYPES direcao)
{
if (PositionSelect(psymbol))//Rebalan<EFBFBD>o
{
if ((PositionGetDouble(POSITION_VOLUME)<myvol)&&direcao==Buy) {MyPrint(psymbol," Rebalan<00>o compra");return(true);}
if ((PositionGetDouble(POSITION_VOLUME)>myvol)&&direcao==Sell) {MyPrint(psymbol," Rebalan<00>o venda");return(true);}
return(false);
}
else
{
if (direcao==Buy) return(true);
if (direcao==Sell) return(false);
return(false);
}
}
virtual double Vol(void)
{
if (PositionSelect(psymbol))//Rebalance
{
//Print("Rebalan<00>o");
return(MathAbs(PositionGetDouble(POSITION_VOLUME)-myvol));
}
else return(myvol);
}
};
class SellHold : public BuyHold
{
public:
virtual bool SignalCheck(ENUM_OP_TYPES direcao)
{
if (PositionSelect(psymbol))//Rebalance
{
if ((PositionGetDouble(POSITION_VOLUME)>myvol)&&direcao==Buy) {MyPrint(psymbol," Rebalan<00>o compra");return(true);}
if ((PositionGetDouble(POSITION_VOLUME)<myvol)&&direcao==Sell) {MyPrint(psymbol," Rebalan<00>o venda");return(true);}
return(false);
}
else
{
if (direcao==Buy) return(false);
if (direcao==Sell) return(true);
return(false);
}
}
};
class BuyHoldSellNeutral : public Signal
{
public:
virtual bool SignalCheck(ENUM_OP_TYPES direcao)
{
if (psymbol!=NeutralAsset2)
{
if (PositionSelect(psymbol))//Rebalan<EFBFBD>o
{
if ((PositionGetDouble(POSITION_VOLUME)<myvol)&&direcao==Buy) {MyPrint(psymbol," Rebalan<00>o compra");return(true);}
if ((PositionGetDouble(POSITION_VOLUME)>myvol)&&direcao==Sell) {MyPrint(psymbol," Rebalan<00>o venda");return(true);}
return(false);
}
else
{
if (direcao==Buy) return(true);
if (direcao==Sell) return(false);
return(false);
}
}
else
{
if (PositionSelect(psymbol))//Rebalance
{
if ((PositionGetDouble(POSITION_VOLUME)>myvol)&&direcao==Buy) {MyPrint(psymbol," Rebalan<00>o compra");return(true);}
if ((PositionGetDouble(POSITION_VOLUME)<myvol)&&direcao==Sell) {MyPrint(psymbol," Rebalan<00>o venda");return(true);}
return(false);
}
else
{
if (direcao==Buy) return(false);
if (direcao==Sell) return(true);
return(false);
}
}
}
virtual double Vol(void)
{
if (PositionSelect(psymbol))//Rebalance
{
//Print("Rebalan<00>o");
return(MathAbs(PositionGetDouble(POSITION_VOLUME)-myvol));
}
else return(myvol);
}
};
class Shadow : public Signal
{
public:
bool AtrVar;//=false;//Usar janela vari<EFBFBD>vel com ATR
bool SignalOrig;//=true;//Sinal original - lag pre<EFBFBD>o/c<EFBFBD>digo - lag ssb
virtual void Initspecific(double &params[])
{
if (ArraySize(params)==2)
{
AtrVar=(bool)params[0];
SignalOrig=(bool)params[1];
}
}
virtual bool SignalCheck(ENUM_OP_TYPES direcao)
{
double ssb=SSB(psymbol,timeframe,0);
double ssblag=SSB(psymbol,timeframe,25);
MqlRates preco[],precolag[];
CopyRates(psymbol,timeframe,0,1,preco);//na simula<EFBFBD>ao diario <EFBFBD> zero, deve ser mudado na simula<EFBFBD><EFBFBD>o m1
CopyRates(psymbol,timeframe,25,1,precolag);
if (SignalOrig)
{
if ((preco[0].close>ssb)&&(precolag[0].close>ssb)&&(direcao==Buy)) return(true);
if ((preco[0].close<ssb)&&(precolag[0].close<ssb)&&(direcao==Sell)) return(true);
}
else
{
if ((preco[0].close>ssb)&&(preco[0].close>ssblag)&&(direcao==Buy)) return(true);
if ((preco[0].close<ssb)&&(preco[0].close<ssblag)&&(direcao==Sell)) return(true);
}
return(false);
}
};
class Gap : public Signal
{
public:
virtual bool SignalCheck(ENUM_OP_TYPES direcao)
{
MqlRates bar[];
ArraySetAsSeries(bar, true);
double ret[];
ArraySetAsSeries(ret, true);
//Usa 3 par<EFBFBD>metros da classe Signal
//usa o par<EFBFBD>metro patr (per<EFBFBD>odo do atr no menu da estrat<EFBFBD>gia) para determinar qual o tamanho da janela de c<EFBFBD>lculo do desvio padr<EFBFBD>o
//usar o par<EFBFBD>metro timeframe (timeframe do atr no menu da estrat<EFBFBD>gia) para determinar qual o timeframe do c<EFBFBD>lculo do desvio padr<EFBFBD>o e do gap
//usa o par<EFBFBD>metro psymbol para fazer o c<EFBFBD>lculo para o ativo da estrat<EFBFBD>gia, tornando-a multiativo
CopyRates(psymbol, timeframe, 0, patr+1,bar);
ArrayResize(ret,ArraySize(bar)-1);
//for (int i=0;i<ArraySize(ret);i++) ret[i] = MathLog(bar[i+1].close/bar[i].close);
for (int i=0;i<ArraySize(ret);i++) ret[i] = bar[i+1].close/bar[i].close-1;
double gap_buy = (bar[0].open-bar[1].low)/bar[1].low;//-1;//abertura de hoje<m<EFBFBD>nimo de ontem=>gap_buy <EFBFBD> negativo
double gap_sell = (bar[0].open-bar[1].high)/bar[1].high;//-1;//abertura de hoje>maximo de ontem=>gap_sell <EFBFBD> positivo
double vol= MathStandardDeviation(ret);
//Estrutura de sinais da estrategia
bool signal_a_buy = gap_buy<-vol;
bool signal_a_sell = gap_sell>vol;
bool signal_b_buy = bar[0].open<bar[1].low;
bool signal_b_sell = bar[0].open>bar[1].high;
if ((signal_a_buy&&signal_b_buy)&&(direcao==Buy)) return(true);
if ((signal_a_sell&&signal_a_sell)&&(direcao==Sell)) return(true);
return(false);
}
};
class ProjecaoMaxMin : public Signal
{//equivale a retorno a pre<EFBFBD>o
public:
virtual bool SignalCheck(ENUM_OP_TYPES direcao)
{
MqlRates preco[];
CopyRates(psymbol,timeframe,0,1,preco);
double volatilidade=Atr(psymbol,patr,timeframe,0);//estimativa da volatilidade, pode ser o atr por ex.
double alphamax=0.5,alphamin=0.5;
/*
//alphamax e alphamin determinados minimizando o desvio quadr<EFBFBD>tico m<EFBFBD>dio
alphamax=0.5;
alphamin=0.5;
double erromax=0;erromin=0;
for (int i=0;i<patr;i++)
{
erromax+=(preco[i].high-(preco[i].open+alphamax*volatilidade))*(preco[i].high-(preco[i].open+alphamax*volatilidade));
erromin+=(preco[i].low-(preco[i].open-alphamin*volatilidade))*(preco[i].low-(preco[i].open-alphamin*volatilidade));
}
double alphastep=0.1
bla bla bla
pensando bem, n<EFBFBD>o acho que vai ser muito melhor que a estimativa abaixo, a n<EFBFBD>o ser em tend<EFBFBD>ncias muito bem definidas
*/
double max= preco[0].open + alphamax*volatilidade;
double min= preco[0].open - alphamin*volatilidade;
double price=preco[0].close;//<EFBFBD>ltimo pre<EFBFBD>o (ou bid ou ask)
bool signal_buy = price<min;//compra se pre<EFBFBD>o menor que a proje<EFBFBD><EFBFBD>o do m<EFBFBD>nimo
bool signal_sell = price>max;//vende se pre<EFBFBD>o maior que a proje<EFBFBD><EFBFBD>o do m<EFBFBD>ximo
if (signal_buy&&(direcao==Buy)) return(true);
if (signal_sell&&(direcao==Sell)) return(true);
return(false);
}
};
class PythonScripts: public Signal
{
public:
string script_name;
bool useticker,usevolume;
virtual void InitFname(string fname){script_name=fname;}
virtual void Initspecific(double &params[])
{
if (ArraySize(params)==2)
{
useticker=(bool)params[0];
usevolume=(bool)params[1];
}
}
virtual bool SignalCheck(ENUM_OP_TYPES direcao)
{
string outputfile=script_name+".out";
if (FileIsExist(outputfile)) FileDelete(outputfile);//Se o arquivo de sa<EFBFBD>da existir, delete-o
RunPython(script_name);//Roda o script python
while (!FileIsExist(outputfile)) Sleep(1000);//espera o aquivo ser criado
int fhandle=FileOpen(outputfile,FILE_READ|FILE_CSV|FILE_TXT,";"); //Abre o arquivo para leitura
if (fhandle!=INVALID_HANDLE)
{
string fsymbol=FileReadString(fhandle);//L<EFBFBD> o ticker
ENUM_OP_TYPES fdirecao=None;
int dir=(int)FileReadNumber(fhandle);//L<EFBFBD> a dire<EFBFBD><EFBFBD>o
if (dir==1) fdirecao=Buy;//Converte a dire<EFBFBD><EFBFBD>o (n<EFBFBD>o precisava kkkkk)
if (dir==-1) fdirecao=Sell;
double fvolume=FileReadNumber(fhandle);//L<EFBFBD> o volume
if (useticker?(fsymbol==psymbol):true)//Testa se o ativo no arquivo <EFBFBD> o mesmo do objeto
{
if (usevolume) myvol=fvolume;//seta o novo volume
//testa a dire<EFBFBD><EFBFBD>o do sinal
if ((fdirecao==Buy)&&(direcao==Buy)) return(true);
if ((fdirecao==Sell)&&(direcao==Sell)) return(true);
}
}
return(false);
}
};
enum REF_TYPES
{
Ref_price_maxmin,//Rompimento/Retorno Max,Min(Pre<EFBFBD>o)
Ref_mean,//Cruzamento/Retorno M<EFBFBD>dia
Ref_ssb,//Cruzamento/Retorno Ssb
Ref_price_minmax//Rompimento/Retorno Min,Max(Pre<EFBFBD>o)
};
enum REF_PRICES_TYPES
{
Ref_pt_maxmin,//Max,Min
Ref_pt_max,//m<EFBFBD>ximo
Ref_pt_min,//m<EFBFBD>nimo
Ref_pt_open,//abertura
Ref_pt_close,//fechamento
Ref_pt_median,//(max+min)/2
Ref_pt_typical,//(max+min+close)/3
Ref_pt_weighted//(max+min+open+close)/4
};
double Calc_refs(string psymbol,int period,ENUM_TIMEFRAMES timeframe,REF_TYPES type,REF_PRICES_TYPES price_type,double &max,double &min,int shift=0)
{
MqlRates rt[];
if (CopyRates(psymbol,timeframe,shift,period,rt)==period)
{
double ret=0;
double price=0;
max=-DBL_MAX;
min=DBL_MAX;
if ((type==Ref_mean)&&(price_type==Ref_pt_maxmin))
{
max=0;
min=0;
}
for (int i=0;i<period;i++)
{
switch(price_type)
{
case Ref_pt_maxmin:price=(rt[i].high+rt[i].low)/2.0;break;
case Ref_pt_max:price=rt[i].high;break;
case Ref_pt_min:price=rt[i].low;break;
case Ref_pt_open:price=rt[i].open;break;
case Ref_pt_close:price=rt[i].close;break;
case Ref_pt_median:price=(rt[i].high+rt[i].low)/2.0;break;
case Ref_pt_typical:price=(rt[i].high+rt[i].low+rt[i].close)/3.0;break;
case Ref_pt_weighted:price=(rt[i].high+rt[i].low+rt[i].open+rt[i].close)/4.0;break;
}
if ((type==Ref_mean)&&(price_type==Ref_pt_maxmin))
{
max+=rt[i].high;
min+=rt[i].low;
}
else
{
(price_type!=Ref_pt_maxmin)?max=MathMax(max,price):max=MathMax(max,rt[i].high);
(price_type!=Ref_pt_maxmin)?min=MathMin(min,price):min=MathMin(min,rt[i].low);
}
ret+=price;
}
switch(type)
{
case Ref_price_maxmin:break;
case Ref_price_minmax:break;
case Ref_mean:
ret/=(double)period;
if (price_type==Ref_pt_maxmin)
{
max/=(double)period;
min/=(double)period;
}
break;
case Ref_ssb:ret=(max+min)/2.0;break;
}
return(ret);
}
return(0);
}
class Trend : public Signal
{
public:
REF_TYPES Type;//=Ref_price_maxmin;//Tipo de estrat<EFBFBD>gia
REF_PRICES_TYPES Price;//=Ref_pt_maxmin;//Tipo de pre<EFBFBD>o
int Periodo;//=7;//N<EFBFBD>mero de barras no sinal
double AtrFrac;//=0.0;//Fra<EFBFBD><EFBFBD>o do Atr de deslocamento
bool ConfCandle;//=false;//Usar candle de confirma<EFBFBD><EFBFBD>o do rompimento
ENUM_TIMEFRAMES RefTimeframe;//Timeframe da refer<EFBFBD>ncia
virtual void Initspecific(double &params[])
{
if (ArraySize(params)==6)
{
Type=(REF_TYPES)params[0];
Price=(REF_PRICES_TYPES)params[1];
Periodo=(int)params[2];
AtrFrac=(double)params[3];
ConfCandle=(bool)params[4];
RefTimeframe=(ENUM_TIMEFRAMES)params[5];
}
}
virtual bool SignalCheck(ENUM_OP_TYPES direcao)
{
MqlRates rt[];//candle confirmacao
CopyRates(psymbol,timeframe,0,1,rt);
double last=rt[0].close;//SymbolInfoDouble(psymbol,SYMBOL_LAST);
double ask=SymbolInfoDouble(psymbol,SYMBOL_ASK);
double bid=SymbolInfoDouble(psymbol,SYMBOL_BID);
double max,min;
double atr=Atr(psymbol,patr,timeframe,0);
CopyRates(psymbol,timeframe,1,1,rt);//na simula<EFBFBD>ao diario comeca no zero, deve ser mudado na simula<EFBFBD><EFBFBD>o m1
double ret=Calc_refs(psymbol,Periodo,RefTimeframe,Type,Price,max,min,1);
//if (PositionSelect(psymbol)){max=PositionGetDouble(POSITION_PRICE_OPEN);min=max;ret=max;}//parcelamento com sinal
switch (Type)
{
case Ref_price_maxmin:
if ((last>(max+AtrFrac*atr))&&(ConfCandle?rt[0].close>(max+AtrFrac*atr):true)&&(direcao==Buy)) return(true);
if ((last<(min-AtrFrac*atr))&&(ConfCandle?rt[0].close<(min-AtrFrac*atr):true)&&(direcao==Sell)) return(true);
break;
case Ref_price_minmax:
if ((last>(min+AtrFrac*atr))&&(ConfCandle?rt[0].close>(min+AtrFrac*atr):true)&&(direcao==Buy)) return(true);
if ((last<(max-AtrFrac*atr))&&(ConfCandle?rt[0].close<(max-AtrFrac*atr):true)&&(direcao==Sell)) return(true);
break;
case Ref_mean:
if (Price==Ref_pt_maxmin)
{
if ((last>(max+AtrFrac*atr))&&(ConfCandle?rt[0].close>(max+AtrFrac*atr):true)&&(direcao==Buy)) return(true);
if ((last<(min-AtrFrac*atr))&&(ConfCandle?rt[0].close<(min-AtrFrac*atr):true)&&(direcao==Sell)) return(true);
}
else
{
if ((last>(ret+AtrFrac*atr))&&(ConfCandle?rt[0].close>(ret+AtrFrac*atr):true)&&(direcao==Buy)) return(true);
if ((last<(ret-AtrFrac*atr))&&(ConfCandle?rt[0].close<(ret-AtrFrac*atr):true)&&(direcao==Sell)) return(true);
}
break;
case Ref_ssb:
if ((last>(ret+AtrFrac*atr))&&(ConfCandle?rt[0].close>(ret+AtrFrac*atr):true)&&(direcao==Buy)) return(true);
if ((last<(ret-AtrFrac*atr))&&(ConfCandle?rt[0].close<(ret-AtrFrac*atr):true)&&(direcao==Sell)) return(true);
break;
}
return(false);
}
};
class Return : public Trend
{
public:
virtual bool SignalCheck(ENUM_OP_TYPES direcao)
{
MqlRates rt[];//candle confirmacao
CopyRates(psymbol,timeframe,0,1,rt);//na simula<EFBFBD>ao diario comeca no zero, deve ser mudado na simula<EFBFBD><EFBFBD>o m1
double last=rt[0].close;//SymbolInfoDouble(psymbol,SYMBOL_LAST);
double ask=SymbolInfoDouble(psymbol,SYMBOL_ASK);
double bid=SymbolInfoDouble(psymbol,SYMBOL_BID);
double max,min;
double atr=Atr(psymbol,patr,timeframe,0);
CopyRates(psymbol,timeframe,1,1,rt);//na simula<EFBFBD>ao diario comeca no zero, deve ser mudado na simula<EFBFBD><EFBFBD>o m1
double ret=Calc_refs(psymbol,Periodo,RefTimeframe,Type,Price,max,min,1);
//if (PositionSelect(psymbol)){max=PositionGetDouble(POSITION_PRICE_OPEN);min=max;ret=max;}//parcelamento com sinal
switch (Type)
{
case Ref_price_maxmin:
if ((last<(max-AtrFrac*atr))&&(ConfCandle?rt[0].close<(max-AtrFrac*atr):true)&&(direcao==Buy)) return(true);
if ((last>(min+AtrFrac*atr))&&(ConfCandle?rt[0].close>(min+AtrFrac*atr):true)&&(direcao==Sell)) return(true);
break;
case Ref_price_minmax:
//CopyRates(psymbol,timeframe,0,1,rt);
if ((last<(min-AtrFrac*atr))&&(ConfCandle?rt[0].close<(min-AtrFrac*atr):true)&&(direcao==Buy)) return(true);
if ((last>(max+AtrFrac*atr))&&(ConfCandle?rt[0].close>(max+AtrFrac*atr):true)&&(direcao==Sell)) return(true);
break;
case Ref_mean:
if (Price==Ref_pt_maxmin)
{
if ((last<(max-AtrFrac*atr))&&(ConfCandle?rt[0].close<(max-AtrFrac*atr):true)&&(direcao==Buy)) return(true);
if ((last>(min+AtrFrac*atr))&&(ConfCandle?rt[0].close>(min+AtrFrac*atr):true)&&(direcao==Sell)) return(true);
}
else
{
if ((last<(ret-AtrFrac*atr))&&(ConfCandle?rt[0].close<(ret-AtrFrac*atr):true)&&(direcao==Buy)) return(true);
if ((last>(ret+AtrFrac*atr))&&(ConfCandle?rt[0].close>(ret+AtrFrac*atr):true)&&(direcao==Sell)) return(true);
}
break;
case Ref_ssb:
if ((last<(ret-AtrFrac*atr))&&(ConfCandle?rt[0].close<(ret-AtrFrac*atr):true)&&(direcao==Buy)) return(true);
if ((last>(ret+AtrFrac*atr))&&(ConfCandle?rt[0].close>(ret+AtrFrac*atr):true)&&(direcao==Sell)) return(true);
break;
}
return(false);
}
};
class CandlesElefant
{
public:
bool enable;
datetime data;
double min,max,tamanho;
CandlesElefant(void){enable=false;data=0;min=0;max=0;tamanho=0;}
void Init(void){enable=false;data=0;min=0;max=0;tamanho=0;}
void Reset(void){Init();}
};
class Elefante : public Signal
{
public:
CandlesElefant elefante,gatilho;
ENUM_OP_TYPES mydir;
bool RRFilter;//=true;//Usar filtro de Retorno/Risco
double RRFrac;//=0.33;//Fra<EFBFBD><EFBFBD>o RR
bool SSBFilter;//=true;//Usar filtro SSB
bool ConfCandle;//=true;//Usar candle de confirma<EFBFBD><EFBFBD>o do rompimento
bool SlOrig;//=false;//SL original - extens<EFBFBD>o acima(abaixo) piv<EFBFBD>/ponto m<EFBFBD>dio do elefante
bool TpOrig;//=false;//TP original - extens<EFBFBD>o baixo(acima) piv<EFBFBD>/extens<EFBFBD>o acima(abaixo) elefante
bool PivotCandle;//=false;//Usar candle de pivot - rompimento do piv<EFBFBD>/elefante
bool BodyElefant;//=true;//Usar s<EFBFBD> o corpo do candle elefante
bool BodyPivot;//=false;//Usar s<EFBFBD> o corpo do candle piv<EFBFBD>
virtual void Initspecific(double &params[])
{
if (ArraySize(params)==10)
{
RRFilter=(bool)params[0];
RRFrac=(double)params[1];
SSBFilter=(bool)params[2];
ConfCandle=(bool)params[3];
SlOrig=(bool)params[4];
TpOrig=(bool)params[5];
PivotCandle=(bool)params[6];
BodyElefant=(bool)params[7];
BodyPivot=(bool)params[8];
mydir=(ENUM_OP_TYPES)params[9];
}
}
virtual void Init(void)
{
elefante.Init();
gatilho.Init();
mydir=None;
}
virtual bool SignalCheck(ENUM_OP_TYPES direcao)
{
MqlRates rt[];
ArraySetAsSeries(rt,true);
CopyRates(psymbol,timeframe,0,1,rt);
double preco=rt[0].close;//SymbolInfoDouble(psymbol,SYMBOL_LAST);
CopyRates(psymbol,timeframe,1,1,rt);
double ask=SymbolInfoDouble(psymbol,SYMBOL_ASK);
double bid=SymbolInfoDouble(psymbol,SYMBOL_BID);
double ssb=(SSBFilter?SSB(psymbol,timeframe,26):preco);
if ((MathAbs(rt[0].close-rt[0].open)>Atr(psymbol,patr,timeframe))&&(!elefante.enable))//verifica candle elefante
{
Reset();
if ((rt[0].close>rt[0].open)&&(preco>=ssb))
{
elefante.enable=true;
mydir=Buy;
}
else if((rt[0].close<rt[0].open)&&(preco<=ssb))
{
elefante.enable=true;
mydir=Sell;
}
elefante.data=rt[0].time;
elefante.tamanho=MathAbs(rt[0].close-rt[0].open);
elefante.min=(BodyElefant?MathMin(rt[0].open,rt[0].close):rt[0].low);
elefante.max=(BodyElefant?MathMax(rt[0].open,rt[0].close):rt[0].high);
}
if ((elefante.enable)&&(rt[0].time!=elefante.data))//verifica gatilho
{
if(PivotCandle)
{
if ((MathAbs(rt[0].close-rt[0].open)<(0.5*elefante.tamanho))&&(!gatilho.enable)//verifica tamanho
&&( ((rt[0].low>(0.5*elefante.min+0.5*elefante.max))&&(mydir==Buy)&&(preco>=ssb))
||((rt[0].high<(0.5*elefante.min+0.5*elefante.max))&&(mydir==Sell)&&(preco<=ssb)) )//verifica range
)
{
gatilho.enable=true;
gatilho.data=rt[0].time;
gatilho.tamanho=MathAbs(rt[0].close-rt[0].open);
gatilho.min=(BodyPivot?MathMin(rt[0].open,rt[0].close):rt[0].low);
gatilho.max=(BodyPivot?MathMax(rt[0].open,rt[0].close):rt[0].high);
}
else if (!gatilho.enable) Reset();//se n<EFBFBD>o teve range ou tamanho, reseta
}
else
{
gatilho.enable=true;
gatilho.data=rt[0].time;
gatilho.tamanho=MathAbs(rt[0].close-rt[0].open);
gatilho.min=(BodyPivot?MathMin(rt[0].open,rt[0].close):rt[0].low);
gatilho.max=(BodyPivot?MathMax(rt[0].open,rt[0].close):rt[0].high);
}
if ( ((rt[0].low<(0.5*elefante.min+0.5*elefante.max))&&(mydir==Buy))//tendo gatilho ou nao se ficou fora do range deve desarmar
||((rt[0].high>(0.5*elefante.min+0.5*elefante.max))&&(mydir==Sell)) )//verifica range
Reset();
if ((!gatilho.enable)&&PivotCandle) Reset();//se entrou aqui e n<EFBFBD>o setou gatilho, reseta
}
if ((elefante.enable)&&(gatilho.enable))//verifica disparo
{
if ( ((ask>=Entry())&&(mydir==Buy)&&(preco>=ssb)&&(ConfCandle?(rt[0].close>=Entry()):true)&&(direcao==Buy) )||
((bid<=Entry())&&(mydir==Sell)&&(preco<=ssb)&&(ConfCandle?(rt[0].close<=Entry()):true)&&(direcao==Sell) ) )//verifica rompimento gatilho
{
if (RRFilter)
{
double profit=MathAbs(Tp()-preco);
double loss=MathAbs(preco-Sl());
if (profit<(RRFrac*loss)) return(false);
return(true);
}
else return(true);
}
if ( (((rt[0].close<gatilho.min)&&(mydir==Buy))||((rt[0].close>gatilho.max)&&(mydir==Sell)))&&(rt[0].time!=gatilho.data) )
Reset();//desarma
}
return(false);
}
double Entry(void)
{
if(!PivotCandle)
{
if(mydir==Buy) return(NormalizePrice(psymbol,elefante.max+1.0*SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_SIZE),true));
if(mydir==Sell) return(NormalizePrice(psymbol,elefante.min-1.0*SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_SIZE),true));
}
else
{
if(mydir==Buy) return(NormalizePrice(psymbol,gatilho.max+1.0*SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_SIZE),true));
if(mydir==Sell) return(NormalizePrice(psymbol,gatilho.min-1.0*SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_SIZE),true));
}
return(0);
}
virtual double Sl(void)
{
if (SlOrig)
{
if(mydir==Buy) return(NormalizePrice(psymbol,gatilho.min-1.0*SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_SIZE),true));
if(mydir==Sell) return(NormalizePrice(psymbol,gatilho.max+1.0*SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_SIZE),true));
}
else
{
if(mydir==Buy) return(NormalizePrice(psymbol,(0.5*elefante.min+0.5*elefante.max-1.0*SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_SIZE)),true));
if(mydir==Sell) return(NormalizePrice(psymbol,(0.5*elefante.min+0.5*elefante.max+1.0*SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_SIZE)),true));
}
return(0);
}
virtual double Tp(void)
{
if (TpOrig)
{
if(mydir==Buy) return(NormalizePrice(psymbol,gatilho.max+elefante.tamanho+2.0*SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_SIZE),true));
if(mydir==Sell) return(NormalizePrice(psymbol,gatilho.min-elefante.tamanho-2.0*SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_SIZE),true));
}
else
{
if(mydir==Buy) return(NormalizePrice(psymbol,elefante.max+elefante.tamanho+2.0*SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_SIZE),true));
if(mydir==Sell) return(NormalizePrice(psymbol,elefante.min-elefante.tamanho-2.0*SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_SIZE),true));
}
return(0);
}
virtual string PrintString(void)
{
string ret=IntegerToString(elefante.enable)+" "+IntegerToString(gatilho.enable)+" "+IntegerToString(mydir);
return(ret);
}
};