oslib/osc/est/CStat.mqh
super.admin 07f69c4478 convert
2025-05-30 16:15:18 +02:00

356 lines
28 KiB
MQL5

//+------------------------------------------------------------------+
//| CStat.mqh|
//| Copyright 2020,oficina de software.|
//| http://www.metaquotes.net/marcoc.|
//+------------------------------------------------------------------+
#property copyright "2020, Oficina de Software."
#property link "http://www.os.net"
//---
class CStat{
private:
protected:
public:
bool calcCoefKelly(const double _payOut , const double _probWin, double &_coefKelly);
bool calcCoefKelly(const double _qtdLoss , const double _qtdWin ,
const double _lossAcum, const double _winAcum, double &_coefKelly);
bool calcPayOut (const double _lossAcum, const double _winAcum, double &_payOut );
bool calcProbWin (const double _qtdLoss , const double _qtdWin , double &_pWin );
double calcEntropiaCruzada(double &_distFact[] , double &_distPrevisao[]);
//
// recebe:
// v in vetor de valores (price)
// vol in vetor de pesos (volume)
// dy out vetor com os valores do eixo y (nivel de soma dos pesos) volumes de cada preco
// dx out vetor com os valores do eixo x (nivel dos valores) precos
//
bool calcDist(const double &v[], const double &vol[], double &dy[], double &dx[], int tick=5){
int lenV = ArraySize(v); // tamanho do vetor de valores
//int lenD = ArraySize(d); // tamanho do vetor de ocorrencias
// Print(":-| ",__FUNCTION__,": Encontrando o menor elemento...");
int min = (int)v[ArrayMinimum(v)];
// Print(":-| ",__FUNCTION__,": Encontrando o maior elemento...");
int max = (int)v[ArrayMaximum(v)];
// Print(":-| ",__FUNCTION__,": Redefinindo o tamanho do array da distribuicao...");
ArrayResize(dy,max-min+tick+1);
ArrayResize(dx,max-min+tick+1);
// Print(":-| ",__FUNCTION__,": Inicializando o array da distribuicao...");
ArrayInitialize(dy,0);
ArrayInitialize(dx,0);
// Print(":-| ",__FUNCTION__,": Calculando e alocando no array da distribuicao (eixo y)...");
for( int i=0; i<lenV; i++ ){
//Print("i:",i," v[i]:",v[i]," max:",max);
// contabilizando somente quando altera o dado
//if( v[i] != v[i-1] ){
dy[ (int)(v[i]-min) ] += vol[i] ;
//}
}
// Print(":-| ",__FUNCTION__,": Preenchendo o array com os valores a apresentar no eixo x...");
int lenX = ArraySize(dx);
for(int i=0; i<lenX; i++ ){
dx[i] = i+min-tick ;
}
return true;
}
// retorna o indice da primeira ocorrencia de V no array A ou -1 se não encontrar.
int ArraySearchSerial(const double &a[], const double v, const int sizeA){
for(int i=0; i<sizeA; i++){ if(a[i]==v) return i; }
return -1;
}
//
// recebe:
// v in vetor de valores (price)
// freq in vetor de frequencias (volume)
// dy out vetor com os valores do eixo y (nivel de soma dos pesos) volumes de cada preco
// dx out vetor com os valores do eixo x (nivel dos valores) precos
//
bool calcDist2(const double &v[], const double &freq[], double &dy[], double &dx[]){
int lenV = ArraySize(v); // tamanho do vetor de valores
ArrayInitialize(dy,0);
ArrayInitialize(dx,0);
int posicao = 0;
int lenDx = ArraySize(dx);
for( int i=0; i<lenV; i++ ){
//if(v[i] == 0.0) continue;
posicao = ArraySearchSerial(dx,v[i],lenDx);
if(posicao == -1){
ArrayResize(dx,++lenDx);
ArrayResize(dy, lenDx);
dx[lenDx-1] = v [i]; // valor acumulado pela primeira vez
dy[lenDx-1] = freq[i]; // volume acumulado pela primeira vez
}else{
dy[posicao] += freq[i]; // volume aumentando
}
}
return true;
}
// v in vetor de valores
// p in vetor de pesos
// med out media momento 1
// var out variancia momento 2
// sim out simetria (skewness) momento 3
// kur out kurtose momento 4
// dp out desvio padrao
// cv out coeficiente de variacao
bool describe(double &v[], double &p[], double &med, double &var,double &sim, double &kur, double &dp, double &cv ){
//1. calculando a media e a soma dos pesos...
int len = ArraySize(v);
double spv = 0; // soma dos pesos com os valores
double sp = 0; // soma dos pesos
for(int i=0; i<len; i++){
spv += v[i]*p[i];
sp += p[i];
}
med = spv/sp;
//2. calculando a soma dos desvios observados em relacao a media...
double se2 = 0; // soma dos erros quadrados
double se3 = 0; // soma dos erros cubicos
double se4 = 0; // soma dos erros quartos
for(int i=0; i<len; i++){
se2 += pow( (v[i]-med), 2 )*p[i];
se3 += pow( (v[i]-med), 3 )*p[i];
se4 += pow( (v[i]-med), 4 )*p[i];
}
//3. calculando a variancia...
var = se2/(sp-1.0);
//4. calculando o desvio padrao...
dp = sqrt(var);
//5. calculando o coeficiente de variacao
if(med==0)cv=0; else cv = dp/med;
//6. calculando a simetria...
sim = se3/(pow(dp,3)*sp);
//7. calculando a kurtose...
kur = se4/(pow(var,2)*sp);
return true;
}
//-----------------------------------------------------------------------------
// calcula o coefiente linear usando o metodo do minimos quadrados ordinarios
// entrada:
//-----------------------------------------------------------------------------
// y : in vetor de valores no eixo y
// x : in vetor de valores no eixo x
// b0: out eh o b0 na funcao y(i)=b0 + b1x(i) - eh o intercepto
// b1: out eh o b0 na funcao y(i)=b0 + b1x(i) - eh o coeficiente linear
// r2: out eh o coeficiente de determinacao da regressao: eh a proporcao da
// variabilidade de y que eh explicada pela variabilidade de x.
// varia de zero a 1 e quanto mais proximo de 1, melhor eh o ajuste
// do modelo aos dados.
//-----------------------------------------------------------------------------
bool calcRegLin(double& y[], double& x[], double& b0, double& b1, double& r2, string& msg){
// validando entrada...
int len = ArraySize(y);
int lenX = ArraySize(x);
if(len<3 ){msg=":-( modelo necessita mais de 2 eventos."; return false;}
if(len>lenX ){msg=":-( tamanho do eixo X:"+IntegerToString(lenX)+
" nao corresponde ao tamanho do eixo Y:"+IntegerToString(len);
return false;}
//MQO - minimos quadrados ordinarios
//SQT - soma dos quadrados totais
//SQE - soma dos quadrados estimados
//SQR - soma dos quadrados dos residuos
//SQT = SQE + SQR
double sxy = 0; // somatorio de x vezes y
double sx = 0; // somatorio de x
double sy = 0; // somatorio de y
double sx2 = 0; // somatorio do quadrado de x
double xbarra = 0;
double ybarra = 0;
for(int i=0; i<len; i++){
sxy += (x[i]*y[i]);
sx += x[i];
sy += y[i];
sx2 += pow(x[i],2);
}
if(sx2==0){msg=":-( somatorio de x2 eh zero. Nao eh possivel estimar a regressao";
Print("Eixo Y"); ArrayPrint(y);
Print("Eixo X"); ArrayPrint(x);
return false;}
// if(sx2==pow(sx,2)){msg=":-( somatorio de x2:"+ DoubleToString(sx)
// +" eh igual ao quadrado do somatorio de x:"+ DoubleToString(pow(sx2,2))
// +". Nao eh possivel estimar a regressao";
// Print("Eixo Y"); ArrayPrint(y);
// Print("Eixo X"); ArrayPrint(x);
// return false;}
// calculando o b1...
b1 = ( (len*sxy) - (sx*sy) )/( (len*sx2) - pow(sx,2) );
// calculando a media de x e y...
xbarra = sx/len;
ybarra = sy/len;
// calculando o b0...
b0 = ybarra - (b1*xbarra);
//calculando a soma dos quadrados...
double sqt = 0;//soma dos quadrados totais
double sqe = 0;//soma dos quadrados estimados
double sqr = 0;//soma dos quadrados dos residuos
for(int i=0; i<len; i++){
sqt += pow(y[i] - ybarra, 2);
sqe += pow(b0+b1*x[i] - ybarra, 2);
sqr += pow(y[i] - b0+b1*x[i] , 2);
}
if(sqt==0){msg=":-( SQT eh zero. Nao eh possivel calcular r2";
Print("Eixo Y"); ArrayPrint(y);
Print("Eixo X"); ArrayPrint(x);
return false;}
// calculando r2...
r2 = sqe/sqt;
return true;
}
//-----------------------------------------------------------------------------
void calcCorrel(double& v1[], double& v2[]){ }
bool testeNormal(const int n, const int pile, const int rep, double &v[]){
// 1. gerar pile numeros aleatorios no intervalo 0...n
// 2. calcular a media dos 5 e ordenar no vetor de tamanho rep
// 3. apresentar o histograma do vetor rep
ArrayResize(v,n); ArrayInitialize(v,0);
int acum = 0;
int med = 0;
//MathSrand( GetTickCount() );
MathSrand( n/2 );
for(int i=0; i<rep; i++ ){
// gerando pile numeros aleatorios no intervalo 0..n
acum = 0;
for(int j=0; j<pile; j++){
acum += ( rand()%n );
}
med = acum/pile; // calculando a media.
v[med]++; // acumulando a quantidade na posicao da media
}
return true;
}
};
//+---------------------------------------------------------------------------------------+
//| |
//| Calcula o Payout baseado no total acumulado de perdas e total acumuldo de ganhos. |
//| |
//+---------------------------------------------------------------------------------------+
bool CStat::calcPayOut(const double _lossAcum, const double _winAcum, double &_payOut){
// calculando o Payout...
if( _lossAcum != 0 ){
_payOut = _winAcum/MathAbs(_lossAcum);
}else{
_payOut = 1; // Quando ainda nao tem perda no dia, fica em 100% por enquanto ateh eu melhorar o entendimento.
}
return true;
}
//+------------------------------------------------------------------+
//| |
//| Calcula a probabilidade de acertos, baseado na quantidade de |
//| transacoes vencedoras a perdedoras. |
//| |
//+------------------------------------------------------------------+
bool CStat::calcProbWin(const double _qtdLoss, const double _qtdWin, double &_pWin){
if( _qtdWin>0 ){
_pWin = _qtdWin / (_qtdWin+_qtdLoss);
}else{
_pWin = 0;
}
return true;
}
//+------------------------------------------------------------------+
//| |
//| Calcula o coeficiente de Kelly. |
//| |
//| Definicao: Percentual maximo de capital a ser alocado a cada |
//| trade. |
//| |
//| Forrmula: |
//| K = ( P.B - (1-P) ) / B |
//| |
//| sendo: |
//| K = Coefiente de Kelly. |
//| P = Probabilidade de acerto. |
//| B = Payout. |
//| |
//+------------------------------------------------------------------+
bool CStat::calcCoefKelly(const double _payOut, const double _probWin, double &_coefKelly){
if( _payOut != 0 ){
_coefKelly = ( (_probWin*_payOut) - (1-_probWin) ) / _payOut;
}else{
_coefKelly = 0;
}
return true;
}
bool CStat::calcCoefKelly(const double _qtdLoss , const double _qtdWin ,
const double _lossAcum, const double _winAcum, double &_coefKelly){
double payOut;
calcPayOut(_lossAcum,_winAcum,payOut);
double probWin;
calcProbWin(_qtdLoss,_qtdWin,probWin);
return calcCoefKelly(payOut,probWin,_coefKelly);
}
double CStat::calcEntropiaCruzada(double &_distFact[] , double &_distPrevisao[]){
int len = ArraySize(_distFact);
double H = 0;
for( int i=0; i<len; i++ ){ H += _distFact[i]*log(_distPrevisao[i]); }
return -H;
}