703 lines
61 KiB
MQL5
703 lines
61 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| ranking.mqh |
|
|
//| Rafael Morgado Silva |
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
|
|
class AssetData
|
|
{
|
|
public:
|
|
string ticker;
|
|
bool selected;
|
|
double price;
|
|
double rank;
|
|
double rent;
|
|
double r2;
|
|
double mvol;
|
|
double mtick;
|
|
double atr;
|
|
double sharp;
|
|
double vol;
|
|
double frac;
|
|
MyData mydata;
|
|
AssetData(void)
|
|
{
|
|
ticker="";
|
|
selected=false;
|
|
price=0;
|
|
rank=INT_MIN;
|
|
rent=0;
|
|
r2=0;
|
|
mvol=0;
|
|
mtick=0;
|
|
atr=0;
|
|
sharp=0;
|
|
vol=0;
|
|
frac=0;
|
|
}
|
|
void Reset(void)
|
|
{
|
|
selected=false;
|
|
price=0;
|
|
rank=INT_MIN;
|
|
rent=0;
|
|
r2=0;
|
|
mvol=0;
|
|
mtick=0;
|
|
atr=0;
|
|
sharp=0;
|
|
vol=0;
|
|
frac=0;
|
|
}
|
|
void operator=(const AssetData &r)
|
|
{
|
|
ticker=r.ticker;
|
|
selected=r.selected;
|
|
price=r.price;
|
|
rank=r.rank;
|
|
rent=r.rent;
|
|
r2=r.r2;
|
|
mvol=r.mvol;
|
|
mtick=r.mtick;
|
|
atr=r.atr;
|
|
sharp=r.sharp;
|
|
vol=r.vol;
|
|
mydata=r.mydata;
|
|
frac=r.frac;
|
|
}
|
|
void Save(int fhandle)
|
|
{
|
|
FileWrite(fhandle,ticker,selected,price,rank,rent,r2,mvol,mtick,atr,sharp,vol,frac);
|
|
}
|
|
void Load(int fhandle)
|
|
{
|
|
ticker=FileReadString(fhandle);
|
|
selected=FileReadBool(fhandle);
|
|
price=FileReadNumber(fhandle);
|
|
rank=FileReadNumber(fhandle);
|
|
rent=FileReadNumber(fhandle);
|
|
r2=FileReadNumber(fhandle);
|
|
mvol=FileReadNumber(fhandle);
|
|
mtick=FileReadNumber(fhandle);
|
|
atr=FileReadNumber(fhandle);
|
|
sharp=FileReadNumber(fhandle);
|
|
vol=FileReadNumber(fhandle);
|
|
frac=FileReadNumber(fhandle);
|
|
}
|
|
};
|
|
|
|
class Table
|
|
{
|
|
public:
|
|
//datetime LastUpdate;
|
|
bool UseLiqFilter;
|
|
bool UsePreFilter;
|
|
bool UseLowVolFilter;
|
|
AssetData data[];
|
|
RankTypes MyRank;
|
|
RankSelectTypes MyRankSelection;
|
|
MyTimer timer;
|
|
Table(void){MyRank=RTRent_atr;MyRankSelection=RSTCharge;UseLiqFilter=true;UsePreFilter=true;UseLowVolFilter=true;return;}
|
|
//void Read(string datafile,bool UseMC=false,int NumberMC=50)
|
|
void Read(bool UseMC=false,int NumberMC=50)
|
|
{//read data file
|
|
if (UseMC)
|
|
{
|
|
ArrayResize(data,NumberMC);
|
|
for(int i=0;i<NumberMC;i++)
|
|
{
|
|
int selected;
|
|
bool reselect=false;
|
|
do
|
|
{
|
|
if (UseNeutralization) selected=(int)round((ArraySize(MyTickers)-3)*rand()/32767);//sorteira um número entre 0 e (Mytickers-3)
|
|
else selected=(int)round((ArraySize(MyTickers)-1)*rand()/32767);//sorteira um número entre 0 e (Mytickers-1)
|
|
reselect=false;
|
|
for (int j=0;j<i;j++)
|
|
if ((data[j].ticker==MyTickers[selected])||(MyTickers[selected]=="")||
|
|
(UseNeutralization?((data[j].ticker==NeutralAsset1)||(data[j].ticker==NeutralAsset2)):false)
|
|
)
|
|
reselect=true;//seleciona de novo
|
|
}while(reselect);
|
|
data[i].ticker=MyTickers[selected];
|
|
}
|
|
if (UseNeutralization)
|
|
{
|
|
if (NeutralAsset1!="")
|
|
{
|
|
ArrayResize(data,ArraySize(data)+1);
|
|
data[ArraySize(data)-1].ticker=NeutralAsset1;
|
|
}
|
|
if (NeutralAsset2!="")
|
|
{
|
|
ArrayResize(data,ArraySize(data)+1);
|
|
data[ArraySize(data)-1].ticker=NeutralAsset2;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(int i=0;i<ArraySize(MyTickers);i++)
|
|
{
|
|
if ((!MQLInfoInteger(MQL_TESTER))&&(!MQLInfoInteger(MQL_OPTIMIZATION)))//online
|
|
{
|
|
bool is_custom;
|
|
MqlRates rt[];
|
|
if (CopyRates(MyTickers[i],PERIOD_D1,0,1,rt)==1)
|
|
{
|
|
if (TimeCurrent()<(rt[0].time+21*24*3600))//descarta ativos que não tiveram negociação nos últimos 21 dias
|
|
{
|
|
if (SymbolExist(MyTickers[i],is_custom))//essa condição falha na órama
|
|
{
|
|
ArrayResize(data,ArraySize(data)+1);
|
|
data[ArraySize(data)-1].ticker=MyTickers[i];
|
|
}else Print("Ativo ",MyTickers[i]," descartado, não existe");
|
|
}else Print("Ativo ",MyTickers[i]," descartado, não houve negociação nos últimos 21 dias");
|
|
}else Print("Ativo ",MyTickers[i]," descartado, não há histórico");
|
|
}
|
|
else
|
|
{
|
|
bool is_custom;
|
|
//MqlRates rt[];
|
|
if (SymbolExist(MyTickers[i],is_custom))
|
|
{
|
|
ArrayResize(data,ArraySize(data)+1);
|
|
data[ArraySize(data)-1].ticker=MyTickers[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!Forex1)
|
|
if (MQLInfoInteger(MQL_TESTER)||MQLInfoInteger(MQL_OPTIMIZATION))//fixa bug no tester
|
|
{
|
|
MqlRates rt[];
|
|
for (int i=0;i<ArraySize(data);i++)
|
|
CopyRates(data[i].ticker,PERIOD_CURRENT,0,1,rt);
|
|
}
|
|
|
|
/*int fhandle=FileOpen(datafile,FILE_TXT|FILE_READ|FILE_COMMON|FILE_SHARE_READ);//lê os tickers
|
|
int count=0;
|
|
if(fhandle!=INVALID_HANDLE)
|
|
{
|
|
count=0;
|
|
while(!FileIsEnding(fhandle))
|
|
{
|
|
FileReadString(fhandle);
|
|
count++;
|
|
}
|
|
FileClose(fhandle);
|
|
}
|
|
if (UseMC)
|
|
{
|
|
string tmptickers[];
|
|
ArrayResize(tmptickers,count);
|
|
fhandle=FileOpen(datafile,FILE_TXT|FILE_READ|FILE_COMMON|FILE_SHARE_READ);//tickers, precisa estar no common
|
|
if(fhandle!=INVALID_HANDLE)
|
|
{
|
|
for(int i=0;i<count;i++) tmptickers[i]=FileReadString(fhandle);
|
|
FileClose(fhandle);
|
|
}
|
|
ArrayResize(data,NumberMC);
|
|
for(int i=0;i<NumberMC;i++)
|
|
{
|
|
int selected;
|
|
bool reselect=false;
|
|
do
|
|
{
|
|
selected=(int)round((count-1)*rand()/32767);
|
|
reselect=false;
|
|
for (int j=0;j<i;j++)
|
|
if ((data[j].ticker==tmptickers[selected])||(tmptickers[selected]==""))
|
|
reselect=true;//seleciona de novo
|
|
}while(reselect);
|
|
data[i].ticker=tmptickers[selected];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ArrayResize(data,count);
|
|
fhandle=FileOpen(datafile,FILE_TXT|FILE_READ|FILE_COMMON|FILE_SHARE_READ);//tickers, precisa estar no common
|
|
if(fhandle!=INVALID_HANDLE)
|
|
{
|
|
for(int i=0;i<count;i++) data[i].ticker=FileReadString(fhandle);
|
|
FileClose(fhandle);
|
|
}
|
|
}
|
|
if (!Forex1)
|
|
if (MQLInfoInteger(MQL_TESTER)||MQLInfoInteger(MQL_OPTIMIZATION))//fixa bug no tester
|
|
{
|
|
MqlRates rt[];
|
|
for (int i=0;i<ArraySize(data);i++)
|
|
CopyRates(data[i].ticker,PERIOD_M1,0,1,rt);
|
|
}
|
|
*/
|
|
return;
|
|
}
|
|
void BubbleSort()
|
|
{
|
|
int i,j,count=ArraySize(data);
|
|
for(i=1;i<count; i++)
|
|
for(j=count-1;j>=i;j--)
|
|
if(data[j-1].rank<data[j].rank)
|
|
{
|
|
AssetData x;
|
|
x=data[j];
|
|
data[j]=data[j-1];
|
|
data[j-1]=x;
|
|
}
|
|
}
|
|
void BubbleSortByVolume()
|
|
{
|
|
int i,j,count=ArraySize(data);
|
|
for(i=1;i<count; i++)
|
|
for(j=count-1;j>=i;j--)
|
|
if((data[j-1].mvol*data[j-1].price)<(data[j].mvol*data[j].price))
|
|
//((MathPow(1.0+data[j-1].rent,250)-1.0)*data[j-1].r2)<((MathPow(1.0+data[j].rent,250)-1.0)*data[j].r2))
|
|
//(1.0/(data[j-1].mvol*data[j-1].price))<(1.0/(data[j].mvol*data[j].price)))
|
|
{
|
|
AssetData x;
|
|
x=data[j];
|
|
data[j]=data[j-1];
|
|
data[j-1]=x;
|
|
}
|
|
}
|
|
void Rank(ENUM_TIMEFRAMES timeframe, int period,ENUM_TIMEFRAMES timeframeatr,int patr,Periodicity Periodicidade)
|
|
{
|
|
for(int i=0;i<ArraySize(data); i++)
|
|
{
|
|
MqlRates rt[];
|
|
if(CopyRates(data[i].ticker,timeframe,0,1,rt)==1) data[i].price=rt[0].close;//SymbolInfoDouble(data[i].ticker,SYMBOL_LAST);
|
|
if(CopyRates(data[i].ticker,timeframe,0,period,rt)==period)
|
|
{
|
|
MSQ(rt,data[i].rent,data[i].r2,data[i].sharp,data[i].mvol,data[i].mtick,period);
|
|
data[i].atr=Atr(data[i].ticker,patr,timeframeatr);
|
|
data[i].vol=0;
|
|
if (data[i].atr>0)
|
|
{
|
|
switch(VolType)
|
|
{
|
|
case VTFixed_Lots: data[i].vol=CalcVol(data[i].ticker,INT_MIN,Risk);break;//Quantidade fixa de lotes
|
|
case VTFixed_Money: data[i].vol=CalcVol(data[i].ticker,data[i].price,Risk);break;//Capital dividido igualmente na carteira
|
|
case VTOptim_ATR: data[i].vol=CalcVol(data[i].ticker,Atr(data[i].ticker,patr,timeframeatr),Risk);break;//Otimização usando ATR
|
|
case VTOptim_Sigma: data[i].vol=CalcVol(data[i].ticker,Stddev(data[i].ticker,patr,timeframeatr),Risk);break;//Otimização usando sigma(Preço)
|
|
case VTOptim_SigmaRel: data[i].vol=CalcVol(data[i].ticker,Stdrel(data[i].ticker,patr,timeframeatr),Risk);break;//Otimização usando sigma(ln(Preço))
|
|
case VTOptim_ATRRel: data[i].vol=CalcVol(data[i].ticker,Atr(data[i].ticker,patr,timeframeatr)/data[i].price,Risk);break;//Otimização usando ATR/preço
|
|
case VTOptim_SigmaPrice:data[i].vol=CalcVol(data[i].ticker,Stddev(data[i].ticker,patr,timeframeatr)/data[i].price,Risk);break;//Otimização usando sigma(Preço)/preço
|
|
}
|
|
|
|
data[i].frac=data[i].vol*data[i].price/Money.Balance();//frac é a carga do ativo
|
|
switch(MyRank)
|
|
{
|
|
case RTRent: data[i].rank=(MathPow(1.0+data[i].rent,250)-1.0)*data[i].r2;break;//-(rt[0].close-rt[period-1].close)/rt[0].close;
|
|
case RTRent_atr: data[i].rank=((MathPow(1.0+data[i].rent,250)-1.0)*data[i].r2)/Atr(data[i].ticker,period,timeframe);break;//atr com period e timeframe
|
|
case RTRent_mvol: data[i].rank=(MathPow(1.0+data[i].rent,250)-1.0)*data[i].r2/Stddev(data[i].ticker,period,timeframe);break;//(data[i].mvol*data[i].price)
|
|
case RTRent_atr_mvol:data[i].rank=(MathPow(1.0+data[i].rent,250)-1.0)*data[i].r2/Stdrel(data[i].ticker,period,timeframe);break;//data[i].mtick//*data[i].mvol/data[i].atr;break;
|
|
case RTHighVolidx: data[i].rank=Atr(data[i].ticker,period,timeframe);break;
|
|
case RTLowVolidx:
|
|
{
|
|
double thisatr=Atr(data[i].ticker,period,timeframe);
|
|
data[i].rank=((thisatr!=0)?(1.0/thisatr):INT_MIN);
|
|
break;
|
|
}
|
|
case RTHighLiq: data[i].rank=data[i].mvol*data[i].price;break;
|
|
case RTLowLiq: data[i].rank=1.0/(data[i].mvol*data[i].price);break;
|
|
case RTHighNeg: data[i].rank=data[i].mtick;break;
|
|
case RTLowNeg: data[i].rank=1.0/(data[i].mtick);break;
|
|
case RTHighGap: data[i].rank=(rt[period-1].open-rt[period-2].close)/data[i].price;break;
|
|
case RTLowGap: data[i].rank=(-rt[period-1].open+rt[period-2].close)/data[i].price;break;
|
|
case RTHighGapLow: data[i].rank=(rt[period-1].open<=rt[period-2].low)?(rt[period-1].open-rt[period-2].low)/rt[period-2].low:INT_MIN;break;
|
|
case RTLowGapLow: data[i].rank=Elasticity(data[i].ticker,period,timeframe);break;//(-rt[period-1].open+rt[period-2].low)/rt[period-2].low;break;
|
|
case RTInvRent: data[i].rank=1.0/MathAbs((MathPow(1.0+data[i].rent,250)-1.0)*data[i].r2);break;
|
|
case RTAleatory: data[i].rank=rand();break;
|
|
case RTHighVolstd:
|
|
{
|
|
//double pricevector[];
|
|
//ArrayResize(pricevector,period);
|
|
//for (int j=0;j<period;j++) pricevector[j]=rt[j].close;
|
|
//double stddev=MathStandardDeviation(pricevector);
|
|
//data[i].rank=stddev;
|
|
data[i].rank=Stddev(data[i].ticker,period,timeframe);
|
|
break;
|
|
}
|
|
case RTLowVolstd:
|
|
{
|
|
//double pricevector[];
|
|
//ArrayResize(pricevector,period);
|
|
//for (int j=0;j<period;j++) pricevector[j]=rt[j].close;
|
|
double stddev=Stddev(data[i].ticker,period,timeframe);//MathStandardDeviation(pricevector);
|
|
data[i].rank=((stddev!=0)?(1.0/stddev):INT_MIN);
|
|
break;
|
|
}
|
|
case RTHighVolrel:
|
|
{
|
|
//double pricevector[];
|
|
//ArrayResize(pricevector,period);
|
|
//for (int j=0;j<period;j++) pricevector[j]=MathLog(rt[j].close);
|
|
//double stddev=MathStandardDeviation(pricevector);
|
|
data[i].rank=Stdrel(data[i].ticker,period,timeframe);//stddev;
|
|
break;
|
|
}
|
|
case RTLowVolrel:
|
|
{
|
|
//double pricevector[];
|
|
//ArrayResize(pricevector,period);
|
|
//for (int j=0;j<period;j++) pricevector[j]=MathLog(rt[j].close);
|
|
double stddev=Stdrel(data[i].ticker,period,timeframe);//MathStandardDeviation(pricevector);
|
|
data[i].rank=((stddev!=0)?(1.0/stddev):INT_MIN);
|
|
break;
|
|
}
|
|
case RTLowVolatrpr:
|
|
{
|
|
double thisatr=Atr(data[i].ticker,period,timeframe);
|
|
data[i].rank=((thisatr!=0)?(data[i].price/thisatr):INT_MIN);
|
|
break;
|
|
}
|
|
case RTLowVolstdpr:
|
|
{
|
|
double stddev=Stddev(data[i].ticker,period,timeframe);
|
|
data[i].rank=((stddev!=0)?(data[i].price/stddev):INT_MIN);
|
|
break;
|
|
}
|
|
case RTHighCorre:
|
|
{
|
|
data[i].rank=Pearson("IBOV",data[i].ticker,period,timeframe);//stddev;
|
|
break;
|
|
}
|
|
case RTLowCorre:
|
|
{
|
|
double corre=Pearson("IBOV",data[i].ticker,period,timeframe);//MathStandardDeviation(pricevector);
|
|
data[i].rank=((corre!=0)?(1.0/corre):INT_MIN);
|
|
break;
|
|
}
|
|
case RTHighPr: data[i].rank=data[i].price;break;
|
|
case RTLowPr: data[i].rank=1.0/(data[i].price);break;
|
|
}
|
|
}
|
|
else data[i].Reset();
|
|
}
|
|
else data[i].Reset();
|
|
}
|
|
//----Novo Filtro de liquidez
|
|
|
|
if (UseLiqFilter)
|
|
{
|
|
BubbleSortByVolume();
|
|
int j=0;
|
|
for(int i=0;i<ArraySize(data);i++)
|
|
{
|
|
if (data[i].rank!=INT_MIN)
|
|
{
|
|
if ((j>=70)&&(UseNeutralization?data[i].ticker!=NeutralAsset1:true)&&(UseNeutralization?data[i].ticker!=NeutralAsset2:true)) data[i].Reset();//
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------
|
|
|
|
BubbleSort();
|
|
//LastUpdate=Periodicidade*(datetime)floor(TimeCurrent()/Periodicidade);
|
|
return;
|
|
}
|
|
void Select(int nselect=0,double Capital=0/*,double FTLiqFrac=0.95,int FTPeriod=30,ENUM_TIMEFRAMES FTTimeframe=PERIOD_M5,string FTLiqSymbolref="IBOV"*/,double FTPreMin=4)
|
|
{
|
|
Filters TSPriceMin,TSLowVol;//TSLiquidity,
|
|
|
|
//TSLiquidity.myfilter=FTLiq;
|
|
//TSLiquidity.FTLiqFrac=FTLiqFrac;
|
|
//TSLiquidity.FTPeriod=FTPeriod;
|
|
//TSLiquidity.FTTimeframe=FTTimeframe;
|
|
//TSLiquidity.FTLiqSymbolref=FTLiqSymbolref;
|
|
|
|
TSPriceMin.myfilter=FTPre;
|
|
TSPriceMin.FTPreMin=FTPreMin;
|
|
|
|
TSLowVol.myfilter=FTRent;
|
|
TSLowVol.FTTimeframe=PERIOD_D1;
|
|
TSLowVol.FTPeriod=120;
|
|
|
|
int count=0;
|
|
double MyCharge=0;
|
|
for(int i=0;i<ArraySize(data); i++)
|
|
{
|
|
//TSLiquidity.symbol=data[i].ticker;
|
|
TSPriceMin.symbol=data[i].ticker;
|
|
TSLowVol.symbol=data[i].ticker;
|
|
|
|
if ( //(UseLiqFilter?(!TSLiquidity.Filter(None)):true)
|
|
//&&
|
|
(UsePreFilter?(!TSPriceMin.Filter(None) ):true)
|
|
&&(UseLowVolFilter?(!TSLowVol.Filter(None) ):true)
|
|
//&&((data[i].vol*data[i].price)<(0.25*Capital))//filtro de carga
|
|
&&(data[i].rank!=INT_MIN) )
|
|
{
|
|
switch (MyRankSelection)
|
|
{
|
|
case RSTFixed:
|
|
{
|
|
if (count<nselect)
|
|
{
|
|
count++;
|
|
data[i].selected=true;
|
|
}
|
|
else data[i].selected=false;
|
|
break;
|
|
}
|
|
case RSTPositive:if (data[i].rank>0) data[i].selected=true;else data[i].selected=false;break;
|
|
case RSTCharge:
|
|
{
|
|
if (MyCharge<(0.9*Capital))
|
|
{
|
|
data[i].selected=true;
|
|
MyCharge+=data[i].vol*data[i].price;
|
|
//if (MyCharge>Capital)//TODO, ou pode ser resolvido com o Renorm
|
|
}
|
|
else data[i].selected=false;
|
|
break;
|
|
}
|
|
case RSTAll:data[i].selected=true;break;
|
|
}
|
|
if (UseNeutralization&&((data[i].ticker==NeutralAsset1)||(data[i].ticker==NeutralAsset2)))
|
|
{
|
|
if (data[i].ticker!="") data[i].selected=true;
|
|
else data[i].selected=false;
|
|
}
|
|
}
|
|
else data[i].selected=false;
|
|
|
|
string prefix=StringSubstr(data[i].ticker,0,4);
|
|
if (data[i].selected)
|
|
for (int j=0;j<i;j++)//para evitar selecionar dois ativos da mesma empresa, como petr3 e petr4
|
|
if (data[j].selected)
|
|
if (StringSubstr(data[j].ticker,0,4)==prefix)
|
|
data[i].selected=false;
|
|
|
|
}
|
|
return;
|
|
}
|
|
|
|
void Renorm(double Capital)//renormaliza de acordo com o capital, recalculando os volumes e as frações
|
|
{
|
|
double factor=0;
|
|
for(int i=0;i<ArraySize(data); i++)
|
|
if ((data[i].selected)&&(UseNeutralization?data[i].ticker!=NeutralAsset1:true)&&(UseNeutralization?data[i].ticker!=NeutralAsset2:true))
|
|
factor+=data[i].vol*data[i].price;
|
|
if (factor!=0)
|
|
for(int i=0;i<ArraySize(data); i++)//if (data[i].selected) Renormaliza para todos, mesmo os nao selecionados
|
|
{
|
|
if((UseNeutralization?data[i].ticker!=NeutralAsset1:true)&&(UseNeutralization?data[i].ticker!=NeutralAsset2:true))
|
|
{
|
|
data[i].vol=TradeSizeOptimized(data[i].ticker,data[i].vol*Capital/factor,false);
|
|
data[i].frac=data[i].vol*data[i].price/Capital;
|
|
}
|
|
//else
|
|
//{
|
|
// if (NeutralMethod==0) data[i].vol=TradeSizeOptimized(data[i].ticker,Capital/data[i].price);//montante total
|
|
//if (data[i].ticker==NeutralAsset1) data[i].vol=TradeSizeOptimized(data[i].ticker,data[i].vol/2.0);//dolar
|
|
// data[i].frac=data[i].vol*data[i].price/Capital;
|
|
//}
|
|
}
|
|
if (UseNeutralization)
|
|
{
|
|
int size=21;//parâmetro que pode ser ajustado
|
|
double carteira[];
|
|
ArrayResize(carteira,size);
|
|
ArrayFill(carteira,0,size,1);
|
|
double carteiramin[],carteiramax[];
|
|
ArrayResize(carteiramin,size);
|
|
ArrayFill(carteiramin,0,size,0);
|
|
ArrayResize(carteiramax,size);
|
|
ArrayFill(carteiramax,0,size,0);
|
|
for(int i=0;i<ArraySize(data); i++)//calcula a carteira
|
|
{
|
|
if ((data[i].selected)&&(data[i].ticker!=NeutralAsset1)&&(data[i].ticker!=NeutralAsset2))
|
|
{
|
|
double tmp[];
|
|
double max[],min[];
|
|
CopyClose(data[i].ticker,PERIOD_D1,0,size,tmp);//PERIOD_D1 pode ser mudado
|
|
CopyHigh(data[i].ticker,PERIOD_D1,0,size,max);//PERIOD_D1 pode ser mudado
|
|
CopyLow(data[i].ticker,PERIOD_D1,0,size,min);//PERIOD_D1 pode ser mudado
|
|
for (int j=0;j<size;j++)
|
|
{
|
|
carteira[j]+=tmp[j]*data[i].vol;
|
|
carteiramin[j]+=min[j]*data[i].vol;
|
|
carteiramax[j]+=max[j]*data[i].vol;
|
|
}
|
|
}
|
|
}
|
|
double neutral1[],neutral2[];
|
|
ArrayResize(neutral1,size);
|
|
ArrayResize(neutral2,size);
|
|
ArrayFill(neutral1,0,size,1);
|
|
ArrayFill(neutral2,0,size,1);
|
|
if (NeutralAsset1!="") CopyClose(NeutralAsset1,PERIOD_D1,0,size,neutral1);//PERIOD_D1 pode ser mudado
|
|
if (NeutralAsset2!="") CopyClose(NeutralAsset2,PERIOD_D1,0,size,neutral2);//PERIOD_D1 pode ser mudado
|
|
double carteiramed=0,neutral1med=0,neutral2med=0;
|
|
double carteiraatr=0;
|
|
for (int j=0;j<size;j++)
|
|
{
|
|
carteiramed+=log(carteira[j]);
|
|
neutral1med+=log(neutral1[j]);
|
|
neutral2med+=log(neutral2[j]);
|
|
carteiraatr+=(carteiramax[j]-carteiramin[j]);
|
|
}
|
|
carteiramed/=(double)size;
|
|
neutral1med/=(double)size;
|
|
neutral2med/=(double)size;
|
|
carteiraatr/=(double)size;
|
|
double sumxy1=0,sumxx1=0,beta1=0,pearson1=0;
|
|
double sumxy2=0,sumxx2=0,beta2=0,pearson2=0;
|
|
double sumyy=0;
|
|
for (int j=0;j<size;j++)
|
|
{
|
|
sumxy1+=(log(carteira[j])-carteiramed)*(log(neutral1[j])-neutral1med);
|
|
sumxy2+=(log(carteira[j])-carteiramed)*(log(neutral2[j])-neutral2med);
|
|
sumxx1+=(log(neutral1[j])-neutral1med)*(log(neutral1[j])-neutral1med);
|
|
sumxx2+=(log(neutral2[j])-neutral2med)*(log(neutral2[j])-neutral2med);
|
|
sumyy+=(log(carteira[j])-carteiramed)*(log(carteira[j])-carteiramed);
|
|
}
|
|
beta1=sumxy1/sumxx1;
|
|
beta2=sumxy2/sumxx2;
|
|
pearson1=sumxy1/MathSqrt(sumxx1*sumyy);
|
|
pearson2=sumxy2/MathSqrt(sumxx2*sumyy);
|
|
//double correction=0.1;
|
|
for(int i=0;i<ArraySize(data); i++)
|
|
{
|
|
if ((data[i].ticker==NeutralAsset1)&&(NeutralAsset1!=""))
|
|
{
|
|
double atr=Atr(data[i].ticker,size,PERIOD_D1);
|
|
if (NeutralMethod==0) data[i].vol=TradeSizeOptimized(data[i].ticker,data[i].vol*atr/(Risk*data[i].price),false);//montante total
|
|
else if (NeutralMethod==1) data[i].vol=TradeSizeOptimized(data[i].ticker,beta1*data[i].vol*atr/(Risk*data[i].price),false);//beta
|
|
else if (NeutralMethod==2) data[i].vol=TradeSizeOptimized(data[i].ticker,pearson1*data[i].vol*atr/(Risk*data[i].price),false);//pearson
|
|
//else if (NeutralMethod==3) data[i].vol=CalcVol(data[i].ticker,atr,correction*carteiraatr/carteira[size-1]);//risco
|
|
//else if (NeutralMethod==4) data[i].vol=CalcVol(data[i].ticker,atr,correction*beta1*carteiraatr/carteira[size-1]);//TradeSizeOptimized(data[i].ticker,beta1*data[i].vol);//pearson risco
|
|
//else if (NeutralMethod==5) data[i].vol=CalcVol(data[i].ticker,atr,correction*pearson1*carteiraatr/carteira[size-1]);//TradeSizeOptimized(data[i].ticker,pearson1*data[i].vol);//pearson risco
|
|
else if (NeutralMethod==3) continue;
|
|
else if (NeutralMethod==4) data[i].vol=TradeSizeOptimized(data[i].ticker,beta1*data[i].vol,false);//pearson risco
|
|
else if (NeutralMethod==5) data[i].vol=TradeSizeOptimized(data[i].ticker,pearson1*data[i].vol,false);//pearson risco
|
|
|
|
//data[i].vol=CalcVol(data[i].ticker,Atr(data[i].ticker,size,PERIOD_D1));
|
|
//if (NeutralMethod==0) data[i].vol=TradeSizeOptimized(data[i].ticker,Capital/data[i].price);//montante total
|
|
//else if (NeutralMethod==1) data[i].vol=TradeSizeOptimized(data[i].ticker,beta1*Capital/data[i].price);//montante total
|
|
//else if (NeutralMethod==2) data[i].vol=TradeSizeOptimized(data[i].ticker,pearson1*Capital/data[i].price);//montante total
|
|
//else if (NeutralMethod==3) continue;
|
|
data[i].frac=data[i].vol*data[i].price/Capital;
|
|
}
|
|
if ((data[i].ticker==NeutralAsset2)&&(NeutralAsset2!=""))
|
|
{
|
|
double atr=Atr(data[i].ticker,size,PERIOD_D1);
|
|
if (NeutralMethod==0) data[i].vol=TradeSizeOptimized(data[i].ticker,data[i].vol*atr/(Risk*data[i].price),false);//montante total
|
|
else if (NeutralMethod==1) data[i].vol=TradeSizeOptimized(data[i].ticker,beta2*data[i].vol*atr/(Risk*data[i].price),false);//montante total
|
|
else if (NeutralMethod==2) data[i].vol=TradeSizeOptimized(data[i].ticker,pearson2*data[i].vol*atr/(Risk*data[i].price),false);//montante total
|
|
//else if (NeutralMethod==3) data[i].vol=CalcVol(data[i].ticker,atr,correction*carteiraatr/carteira[size-1]);//risco
|
|
//else if (NeutralMethod==4) data[i].vol=CalcVol(data[i].ticker,atr,correction*beta2*carteiraatr/carteira[size-1]);//TradeSizeOptimized(data[i].ticker,beta1*data[i].vol);//pearson risco
|
|
//else if (NeutralMethod==5) data[i].vol=CalcVol(data[i].ticker,atr,correction*pearson2*carteiraatr/carteira[size-1]);//TradeSizeOptimized(data[i].ticker,pearson1*data[i].vol);//pearson risco
|
|
else if (NeutralMethod==3) continue;
|
|
else if (NeutralMethod==4) data[i].vol=TradeSizeOptimized(data[i].ticker,beta2*data[i].vol,false);//pearson risco
|
|
else if (NeutralMethod==5) data[i].vol=TradeSizeOptimized(data[i].ticker,pearson2*data[i].vol,false);//pearson risco
|
|
|
|
//if (NeutralMethod==0) data[i].vol=TradeSizeOptimized(data[i].ticker,Capital/data[i].price);//montante total
|
|
//else if (NeutralMethod==1) data[i].vol=TradeSizeOptimized(data[i].ticker,beta2*Capital/data[i].price);//montante total
|
|
//else if (NeutralMethod==2) data[i].vol=TradeSizeOptimized(data[i].ticker,pearson2*Capital/data[i].price);//montante total
|
|
//else if (NeutralMethod==3) continue;
|
|
data[i].frac=data[i].vol*data[i].price/Capital;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
void Redim(double Capital)//redimensiona de acordo com o capital, recalculando o volumes a partir das frações
|
|
{
|
|
for(int i=0;i<ArraySize(data); i++)//if (data[i].selected) Redimensiona para todos, mesmo os nao selecionados
|
|
data[i].vol=TradeSizeOptimized(data[i].ticker,data[i].frac*Capital/data[i].price,false);
|
|
return;
|
|
}
|
|
|
|
void PrintTable(void)
|
|
{
|
|
for(int i=0;i<ArraySize(data); i++)
|
|
{
|
|
if (data[i].selected)
|
|
{
|
|
MyPrint(data[i].ticker," ",
|
|
//data[i].selected," ",
|
|
//DoubleToString(data[i].rank,2)," ",
|
|
//DoubleToString(100*data[i].rent,2)," ",
|
|
//DoubleToString(data[i].sharp,2)," ",
|
|
//DoubleToString(data[i].atr,2)," ",
|
|
DoubleToString(data[i].price,2)," ",
|
|
DoubleToString(data[i].vol,2)//," ",
|
|
//DoubleToString(data[i].mvol,2)
|
|
);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
void SaveTable(string filename)
|
|
{
|
|
int fhandle=FileOpen(filename,FILE_WRITE|FILE_READ|FILE_CSV|FILE_TXT);//para usar 1 arquivo só de saída
|
|
//int fhandle=FileOpen(filename,FILE_WRITE|FILE_CSV|FILE_TXT);
|
|
if (fhandle!=INVALID_HANDLE)
|
|
{
|
|
FileSeek(fhandle,0,SEEK_END);
|
|
//FileWrite(fhandle,"Data","Ticker","Select","Rank","Rent","Sharp","Atr","Price","Vol","MeanVol","Fraction");
|
|
for(int i=0;i<ArraySize(data); i++)
|
|
{
|
|
if (data[i].selected)
|
|
FileWrite(fhandle,
|
|
TimeLocal(),
|
|
data[i].ticker,
|
|
data[i].selected,
|
|
DoubleToString(data[i].rank,2),
|
|
DoubleToString(100*data[i].rent,2),
|
|
DoubleToString(data[i].sharp,2),
|
|
DoubleToString(data[i].atr,2),
|
|
DoubleToString(data[i].price,2),
|
|
DoubleToString(data[i].vol,2),
|
|
DoubleToString(data[i].mvol,2),
|
|
DoubleToString(data[i].frac,4));
|
|
}
|
|
FileClose(fhandle);
|
|
}
|
|
}
|
|
void SaveConfig(string cfgname)
|
|
{
|
|
int fhandlec=FileOpen(cfgname,FILE_CSV|FILE_WRITE);
|
|
if(fhandlec!=INVALID_HANDLE)
|
|
{
|
|
MyPrint("Saving config file");
|
|
FileWrite(fhandlec,timer.LastUpdate,timer.Periodicidade,UseLiqFilter,UsePreFilter,UseLowVolFilter,MyRank,MyRankSelection,ArraySize(data));
|
|
for (int i=0;i<ArraySize(data);i++) data[i].Save(fhandlec);
|
|
FileClose(fhandlec);
|
|
}
|
|
}
|
|
void LoadConfig(string cfgname)
|
|
{
|
|
int fhandlec=FileOpen(cfgname,FILE_CSV|FILE_READ);
|
|
if (fhandlec!=INVALID_HANDLE)
|
|
{
|
|
MyPrint("Loading config");
|
|
timer.LastUpdate=FileReadDatetime(fhandlec);
|
|
timer.Periodicidade=(Periodicity)FileReadNumber(fhandlec);
|
|
UseLiqFilter=FileReadBool(fhandlec);
|
|
UsePreFilter=FileReadBool(fhandlec);
|
|
UseLowVolFilter=FileReadBool(fhandlec);
|
|
MyRank=(RankTypes)FileReadNumber(fhandlec);
|
|
MyRankSelection=(RankSelectTypes)FileReadNumber(fhandlec);
|
|
int datasize=(int)FileReadNumber(fhandlec);
|
|
|
|
if (datasize>0)
|
|
{
|
|
ArrayResize(data,datasize);
|
|
for (int i=0;i<datasize;i++)
|
|
data[i].Load(fhandlec);
|
|
}
|
|
FileClose(fhandlec);
|
|
PrintTable();
|
|
}
|
|
}
|
|
};
|
|
|
|
|