//+------------------------------------------------------------------+ //| S3_Freios1_v0.mq5 | //| DESENVOLVIMENTO | //| 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 "DEV_v0" #property description "HFT MARKET MAKING BASED ON OXFORD'S STUDIES. MINI INDICE." //INDICE //+===================================================================================================================================================================================+ //| 1 - SESSAO DE CABECALHO / ADMISSAO //+===================================================================================================================================================================================+ //+------------------------------------------------------------------+ //| 1.1 - IMPORTACOES | //+------------------------------------------------------------------+ #include #include "S1_Admissao1_v0.mqh"; //+===================================================================================================================================================================================+ //| 3.1 - SESSAO DE HORARIOS / CRONOMETRO //+===================================================================================================================================================================================+ //+------------------------------------------------------------------+ //| 3.1.1 - FUNCAO DE ATUALIZAR HORARIO DE PREGAO | //+------------------------------------------------------------------+ bool VerificaHorarioOrdens(MqlDateTime &horarioMQL_atual, ushort horarioShort_inicial, ushort horarioShort_final) { //Captura o horario atual e coloca em Struct MqlDateTime TimeToStruct(TimeCurrent(), horarioMQL_atual); ushort horarioShort_atual = 0; //Converte o horario atual Struct em ushort horarioShort_atual = horarioMQL_atual.hour * 60 + horarioMQL_atual.min; //Verifica se esta dentro da sessao de trade do dia if((horarioShort_atual > horarioShort_inicial) && (horarioShort_atual < horarioShort_final)) { return true; } else return false; } //+------------------------------------------------------------------+ //| 3.1.2 - FUNCAO DE ATUALIZAR HORARIO DE FECHAMENTO | //+------------------------------------------------------------------+ bool VerificaHorarioFechamento(MqlDateTime &horarioMQL_atual, ushort horarioShort_fechamento) { //Captura o horario atual e coloca em Struct MqlDateTime TimeToStruct(TimeCurrent(), horarioMQL_atual); ushort horarioShort_atual = 0; //Converte o horario atual Struct em ushort horarioShort_atual = horarioMQL_atual.hour * 60 + horarioMQL_atual.min; if(horarioShort_atual > 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(double alvoFinanceiro, double stopFinanceiro, double diferencaSaldo, double saldoInicialDia, double saldoFinalDia, int diaAtual, MqlDateTime &horarioMQL_atual, int intervaloTicks, MqlTick &ArrayTick[], fluido &Fluidos, CSymbolInfo &simbolo) { //Calcula a diferenca de saldo na conta saldoFinalDia = AccountInfoDouble(ACCOUNT_BALANCE); // Print("DiaAtual ", diaAtual, "Horario_atual.day ", horario_atual.day * horario_atual.mon); if(diaAtual == horarioMQL_atual.day) { diferencaSaldo = saldoFinalDia - saldoInicialDia; } else { // Print("Dia anterior: ", diaAtual," Resultado: ", diferencaSaldo); diaAtual = horarioMQL_atual.day; saldoInicialDia = AccountInfoDouble(ACCOUNT_BALANCE); diferencaSaldo = 0.0; } //Verifica se atingiu o drawdown maximo do dia (VAR) if((diferencaSaldo < alvoFinanceiro) && (diferencaSaldo > stopFinanceiro)) { //Calcula os indicadores const int n = intervaloTicks; double precos[]; ArrayResize(precos, n); GetPrecosPassados(precos, ArrayTick, intervaloTicks); double limiteInfTend = CalculaLimiteInfTend(horarioMQL_atual, Fluidos); double limiteSupTend = CalculaLimiteSupTend(horarioMQL_atual, Fluidos); //Verifica se atingiu os limites de tendencia do dia (Drift cutout) if((simbolo.Last() > limiteInfTend) && (precos[0] < limiteSupTend)) return false; else return true; return true; } else return true; } //+------------------------------------------------------------------+ //| 3.2.2 - FUNCAO QUE CALCULA A MEDIA DE PRECOS | //+------------------------------------------------------------------+ void GetPrecosPassados(double &precos[], MqlTick &ArrayTick[], int intervaloTicks) { if(CopyTicks(Symbol(),ArrayTick,COPY_TICKS_TRADE,0,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(MqlDateTime &horarioMQL_atual, fluido &Fluidos) { int horarioAtual = horarioMQL_atual.hour*60 + 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(fluido &Fluidos) { if(VerificaLimiteCompra(Fluidos)) return false; else return true; } //+------------------------------------------------------------------+ //| 3.3.2 - FUNCAO QUE VERIFICA OS RISCOS DE MERCADO NIVEL 2 VENDA | //+------------------------------------------------------------------+ bool VerificaRiscosNivel2V(fluido &Fluidos) { if(VerificaLimiteVenda(Fluidos)) return false; else return true; } //+------------------------------------------------------------------+ //| 3.3.3 - FUNCAO QUE VERIFICA LIMITE DE ORDENS DE COMPRA | //+------------------------------------------------------------------+ bool VerificaLimiteCompra(fluido &Fluidos) { double limite_Compra = Fluidos.Q; double qtdCompraEnviada = 0.0; double qtdCompraExecutada = 0.0; limite_Compra = limite_Compra - OrdensCompraLimitadasAbertas(Fluidos, qtdCompraEnviada, qtdCompraExecutada) - PosicoesCompraAbertas(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(fluido &Fluidos) { double limite_Venda = Fluidos.Q; double qtdVendaEnviada = 0.0; double qtdVendaExecutada = 0.0; limite_Venda = limite_Venda - OrdensVendaLimitadasAbertas(Fluidos, qtdVendaEnviada, qtdVendaExecutada) - PosicoesVendaAbertas(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(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 == Fluidos.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(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 == Fluidos.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(fluido &Fluidos) { int q = 0; q = PosicoesCompraAbertas(Fluidos) - PosicoesVendaAbertas(Fluidos); return q; } //+------------------------------------------------------------------+ //| 3.3.10 - FUNCAO DE VERIFICACAO DE POSICAO DE COMPRA | //+------------------------------------------------------------------+ int PosicoesCompraAbertas(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 == Fluidos.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(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 == Fluidos.magic)) { //Verifica se a posicao eh do tipo sell if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) { positions = positions + 1; } } } return positions; } //+===================================================================================================================================================================================+ //| FIM DO PROGRAMA //+===================================================================================================================================================================================+