//+------------------------------------------------------------------+ //| S3_Freios_v4_3.mq5 | //| OXFORD | //| HEDGING HORN CAPITAL | //| https://www.hhcapital.com.br | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, HEDGING HORN CAPITAL" #property link "https://www.hhcapital.com.br" #property version "DESENV_v4_3" #property description "HFT MARKET MAKING BASED ON OXFORD'S STUDIES. MINI INDICE." //+===================================================================================================================================================================================+ //| 0 - SESSAO DE CABECALHO / ADMISSAO //+===================================================================================================================================================================================+ //+------------------------------------------------------------------+ //| 0.1 - IMPORTACOES | //+------------------------------------------------------------------+ #include #include "S0_Admissao_v4_3.mqh"; //+===================================================================================================================================================================================+ //| 3.1 - SESSAO DE HORARIOS / CRONOMETRO //+===================================================================================================================================================================================+ //+------------------------------------------------------------------+ //| 3.1.1 - FUNCAO DE ATUALIZAR HORARIO DE PREGAO | //+------------------------------------------------------------------+ bool VerificaHorarioOrdens(operacao &Operacao) { //Captura o horario atual e coloca em Struct MqlDateTime TimeToStruct(TimeCurrent(), Operacao.horarioMQL_atual); ushort horarioShort_atual = 0; //Converte o horario atual Struct em ushort horarioShort_atual = Operacao.horarioMQL_atual.hour * 60 + Operacao.horarioMQL_atual.min; //Verifica se esta dentro da sessao de trade do dia if((horarioShort_atual > Operacao.horarioShort_inicial) && (horarioShort_atual < Operacao.horarioShort_final)) { return true; } else return false; } //+------------------------------------------------------------------+ //| 3.1.2 - FUNCAO DE ATUALIZAR HORARIO DE FECHAMENTO | //+------------------------------------------------------------------+ bool VerificaHorarioFechamento(operacao &Operacao) { //Captura o horario atual e coloca em Struct MqlDateTime TimeToStruct(TimeCurrent(), Operacao.horarioMQL_atual); ushort horarioShort_atual = 0; //Converte o horario atual Struct em ushort horarioShort_atual = Operacao.horarioMQL_atual.hour * 60 + Operacao.horarioMQL_atual.min; if(horarioShort_atual > Operacao.horarioShort_fechamento) { return true; } else return false; } //+===================================================================================================================================================================================+ //| 3.2 - SESSAO DE RISCOS DE MERCADO/PORTFOLIO / FREIO DE MAO //+===================================================================================================================================================================================+ //+------------------------------------------------------------------+ //| 3.2.1 - FUNCAO QUE VERIFICA OS RISCOS DE MERCADO NIVEL 3 | //+------------------------------------------------------------------+ bool VerificaRiscosNivel3(operacao &Operacao, fluido &Fluidos) { if(VerificaRiscoSaldo(Operacao, Fluidos) == false) { if(VerificaRiscoVol(Operacao, Fluidos) == false) { return false; } else return true; } else return true; } //+------------------------------------------------------------------+ //| 3.2.2 - FUNCAO QUE VERIFICA RISCO NIVEL 3 DE SALDO | //+------------------------------------------------------------------+ bool VerificaRiscoSaldo(operacao &Operacao, fluido &Fluidos) { //PREPARACAO //Calcula a diferenca de saldo na conta Operacao.saldoAtualDia = 2*AccountInfoDouble(ACCOUNT_BALANCE) - AccountInfoDouble(ACCOUNT_EQUITY); //CONDICOES if(Operacao.chaveRiscoSaldo == true) { Operacao.diferencaSaldo = Operacao.saldoAtualDia - Operacao.saldoInicialDia; // Print("P&L dia: ", Operacao.diferencaSaldo); if(Operacao.chaveFiAutomatico == true) { if(Operacao.diferencaSaldo > 0) { Fluidos.fi = (1+(Operacao.diferencaSaldo / Operacao.alvoFinanceiro) * Fluidos.passoFi) * Fluidos.fiInicial; } } //Verifica se atingiu o drawdown maximo do dia (VAR) if( (Operacao.diferencaSaldo < Operacao.stopFinanceiro) || (Operacao.diferencaSaldo > Operacao.alvoFinanceiro) ) { return true; } else return false; } else return false; } //+------------------------------------------------------------------+ //| 3.2.2 - FUNCAO QUE VERIFICA OS RISCOS DE MERCADO NIVEL 3 | //+------------------------------------------------------------------+ bool VerificaRiscoVol(operacao &Operacao, fluido &Fluidos) { if(Operacao.chaveRiscoVolCurto == true) { if(Fluidos.sigmaHFT > Fluidos.limiteSupDesvioCurto) { return true; } else return false; } else return false; } //+------------------------------------------------------------------+ //| 3.2.4 - FUNCAO QUE CALCULA A MEDIA DE PRECOS | //+------------------------------------------------------------------+ void GetPrecosPassados(fluido &Fluidos, MqlTick &ArrayTick[], double &Precos[]) { if(CopyTicks(Symbol(), ArrayTick, COPY_TICKS_TRADE, 0, Fluidos.intervaloTicks) != -1) { ArraySetAsSeries(ArrayTick,true); for(int i=0;i 0) { t = NormalizeDouble((horarioAtual - horarioInicio),2) / NormalizeDouble((horarioFim - horarioInicio),2); result = Fluidos.precoAbertura - (sqrt(t) * 100 * Fluidos.tickMin * Fluidos.desvioDiario); } return result; } //+------------------------------------------------------------------+ //| 3.2.4 - FUNCAO QUE CALCULA O LIMITE SUPERIOR DE TENDENCIA | //+------------------------------------------------------------------+ double CalculaLimiteSupTend(operacao &Operacao, fluido &Fluidos) { int horarioAtual = Operacao.horarioMQL_atual.hour * 60 + Operacao.horarioMQL_atual.min; int horarioInicio = 540; int horarioFim = 1020; double t = 0.0; double result = 0.0; if((horarioFim - horarioInicio) > 0) { t = NormalizeDouble((horarioAtual - horarioInicio), 2) / NormalizeDouble((horarioFim - horarioInicio), 2); result = Fluidos.precoAbertura + (sqrt(t) * 100 * Fluidos.tickMin * Fluidos.desvioDiario); } return result; } //+===================================================================================================================================================================================+ //| 3.3 - SESSAO DE LIMITES / FREIO MOTOR //+===================================================================================================================================================================================+ //+------------------------------------------------------------------+ //| 3.3.1 - FUNCAO QUE VERIFICA OS RISCOS DE MERCADO NIVEL 2 COMPRA | //+------------------------------------------------------------------+ bool VerificaRiscosNivel2C(operacao &Operacao, fluido &Fluidos) { if(VerificaLimiteCompra(Operacao, Fluidos)) return false; else return true; } //+------------------------------------------------------------------+ //| 3.3.2 - FUNCAO QUE VERIFICA OS RISCOS DE MERCADO NIVEL 2 VENDA | //+------------------------------------------------------------------+ bool VerificaRiscosNivel2V(operacao &Operacao, fluido &Fluidos) { if(VerificaLimiteVenda(Operacao, Fluidos)) return false; else return true; } //+------------------------------------------------------------------+ //| 3.3.3 - FUNCAO QUE VERIFICA LIMITE DE ORDENS DE COMPRA | //+------------------------------------------------------------------+ bool VerificaLimiteCompra(operacao &Operacao, fluido &Fluidos) { double limite_Compra = Fluidos.Q; double qtdCompraEnviada = 0.0; double qtdCompraExecutada = 0.0; limite_Compra = limite_Compra - Fluidos.rajada*OrdensCompraLimitadasAbertas(Operacao, Fluidos, qtdCompraEnviada, qtdCompraExecutada) - Fluidos.rajada*PosicoesCompraAbertas(Operacao, Fluidos); // Print("Limite compra: ", limite_Compra); if(limite_Compra > 0) return true; else return false; } //+------------------------------------------------------------------+ //| 3.3.4 - FUNCAO QUE VERIFICA LIMITE DE ORDENS VENDA | //+------------------------------------------------------------------+ bool VerificaLimiteVenda(operacao &Operacao, fluido &Fluidos) { double limite_Venda = Fluidos.Q; double qtdVendaEnviada = 0.0; double qtdVendaExecutada = 0.0; limite_Venda = limite_Venda - Fluidos.rajada*OrdensVendaLimitadasAbertas(Operacao, Fluidos, qtdVendaEnviada, qtdVendaExecutada) - Fluidos.rajada*PosicoesVendaAbertas(Operacao, Fluidos); if(limite_Venda > 0) return true; else return false; } //+------------------------------------------------------------------+ //| 3.3.5 - FUNCAO QUE VERIFICA LIMITE EM VOLUME DE ORDENS DE COMPRA | //+------------------------------------------------------------------+ int VerificaLimiteVolumeCompra(const int loteEnvio, double qtdCompraEnviada) { double limite = loteEnvio; int returnCode = 1; if(qtdCompraEnviada == 0.0) return 0; if(qtdCompraEnviada == limite) return 1; return returnCode; } //+------------------------------------------------------------------+ //| 3.3.6 - FUNCAO QUE VERIFICA LIMITE EM VOLUME DE ORDENS VENDA | //+------------------------------------------------------------------+ int VerificaLimiteVolumeVenda(const int loteEnvio, double qtdVendaEnviada) { double limite = loteEnvio; int returnCode = 1; if(qtdVendaEnviada == 0.0) return 0; if(qtdVendaEnviada == limite) return 1; return returnCode; } //+--------------------------------------------------------------------------+ //| 3.3.7 - FUNCAO DE CALCULO DO NUMERO DE ORDENS COMPRA LIMITADAS ABERTAS | //+--------------------------------------------------------------------------+ int OrdensCompraLimitadasAbertas(operacao &Operacao, fluido &Fluidos, double &qtdCompraEnviada, double &qtdCompraExecutada) { int ordens = 0; //Percorre todas as ordens for(int i=OrdersTotal()-1; i>=0; i--) { ulong ticket = OrderGetTicket(i); string symbol = OrderGetString(ORDER_SYMBOL); ulong magicEA = OrderGetInteger(ORDER_MAGIC); //Verifica para cada ordem, se eh do simbolo corrente e do mesmo robo if((symbol == _Symbol) && (magicEA == Operacao.magic)) { //Verifica se a ordem eh do tipo buy limit if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT) { ordens = ordens + 1; qtdCompraEnviada = OrderGetDouble(ORDER_VOLUME_INITIAL); qtdCompraExecutada = qtdCompraEnviada - OrderGetDouble(ORDER_VOLUME_CURRENT); } } } return ordens; } //+--------------------------------------------------------------------------+ //| 3.3.8 - FUNCAO DE CALCULO DO NUMERO DE ORDENS VENDA LIMITADAS ABERTAS | //+--------------------------------------------------------------------------+ int OrdensVendaLimitadasAbertas(operacao &Operacao, fluido &Fluidos, double &qtdVendaEnviada, double &qtdVendaExecutada) { int ordens = 0; //Percorre todas as ordens for(int i=OrdersTotal()-1; i>=0; i--) { ulong ticket = OrderGetTicket(i); string symbol = OrderGetString(ORDER_SYMBOL); ulong magicEA = OrderGetInteger(ORDER_MAGIC); //Verifica para cada ordem, se eh do simbolo corrente e do mesmo robo if((symbol == _Symbol) && (magicEA == Operacao.magic)) { //Verifica se a ordem eh do tipo sell limit if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT) { ordens = ordens + 1; qtdVendaEnviada = OrderGetDouble(ORDER_VOLUME_INITIAL); qtdVendaExecutada = qtdVendaEnviada - OrderGetDouble(ORDER_VOLUME_CURRENT); } } } return ordens; } //+------------------------------------------------------------------+ //| 3.3.9 - FUNCAO DE CALCULO DO q | //+------------------------------------------------------------------+ int AtualizaQuantidade(operacao &Operacao, fluido &Fluidos) { int q = 0; q = Fluidos.rajada*PosicoesCompraAbertas(Operacao, Fluidos) - Fluidos.rajada*PosicoesVendaAbertas(Operacao, Fluidos); return q; } //+------------------------------------------------------------------+ //| 3.3.10 - FUNCAO DE VERIFICACAO DE POSICAO DE COMPRA | //+------------------------------------------------------------------+ int PosicoesCompraAbertas(operacao &Operacao, fluido &Fluidos) { int positions = 0; //Percorre todas as posicoes for(int i=PositionsTotal()-1; i>=0; i--) { ulong ticket = PositionGetTicket(i); string symbol = PositionGetString(POSITION_SYMBOL); ulong magicEA = PositionGetInteger(POSITION_MAGIC); //Verifica para cada posicao, se eh do simbolo corrente e do mesmo robo if((symbol == _Symbol) && (magicEA == Operacao.magic)) { //Verifica se a posicao eh do tipo buy if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { positions = positions + 1; } } } return positions; } //+------------------------------------------------------------------+ //| 3.3.11 - FUNCAO DE VERIFICACAO DE POSICAO DE VENDAS | //+------------------------------------------------------------------+ int PosicoesVendaAbertas(operacao &Operacao, fluido &Fluidos) { int positions = 0; //Percorre todas as posicoes for(int i = PositionsTotal()-1; i>=0; i--) { ulong ticket = PositionGetTicket(i); string symbol = PositionGetString(POSITION_SYMBOL); ulong magicEA = PositionGetInteger(POSITION_MAGIC); //Verifica para cada posicao, se eh do simbolo corrente e do mesmo robo if((symbol == _Symbol) && (magicEA == Operacao.magic)) { //Verifica se a posicao eh do tipo sell if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) { positions = positions + 1; } } } return positions; } //+===================================================================================================================================================================================+ //| FIM DO PROGRAMA //+===================================================================================================================================================================================+