385 lines
No EOL
33 KiB
MQL5
385 lines
No EOL
33 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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 <Math/Stat/Math.mqh>
|
|
#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<ArraySize(ArrayTick);i++)
|
|
{
|
|
precos[i] = ArrayTick[i].last;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Print("Falha ao obter o ArrayTick, falha para GetPrecosPassados");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 3.2.3 - FUNCAO QUE CALCULA O LIMITE INFERIOR DE TENDENCIA |
|
|
//+------------------------------------------------------------------+
|
|
double CalculaLimiteInfTend(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.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
|
|
//+===================================================================================================================================================================================+ |