firstHour/DEV_v0/S2_Motor_v4_4.mqh

484 lines
41 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 14:55:09 +02:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| S2_Motor_v4_4.mqh |
//| OXFORD |
//| HEDGING HORN CAPITAL |
//| https://www.hhcapital.com.br |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, HEDGING HORN CAPITAL"
#property link "https://www.hhcap<00>tal.com.br"
#property version "DESENV_v4_4"
#property description "HFT MARKET MAKING BASED ON OXFORD'S STUDIES. MINI INDICE."
//+===================================================================================================================================================================================+
//| 0 - SESSAO DE CABECALHO / ADMISSAO
//+===================================================================================================================================================================================+
//+------------------------------------------------------------------+
//| 0.1 - IMPORTACOES |
//+------------------------------------------------------------------+
#include <Expert/Expert.mqh>
#include <Trade/Trade.mqh>
#include <Trade/SymbolInfo.mqh>
#include "MarketBook.mqh"
#include "S0_Admissao_v4_4.mqh"
#include "S3_Freios_v4_4.mqh"
#include "S4_Cambio_v4_4.mqh"
#include "S5_Direcao_v4_4.mqh"
#include "S6_Transmissao_v4_4.mqh"
//+===================================================================================================================================================================================+
//| 2 - SESSAO DE FAZER NEGOCIACOES / MOTOR
//+===================================================================================================================================================================================+
//+------------------------------------------------------------------+
//| 2.1 - FUNCAO QUE FAZ NEGOCIACOES |
//+------------------------------------------------------------------+
void FazTrades(gerenciador &Gerenciador, operacao &Operacao, fluido &Fluidos, slot &SlotsC[], slot &SlotsV[], MqlTick &ArrayTick[], MqlBookInfo &ArrayBook[])
{
//Verifica os Riscos de Nivel 3 (Condicoes desfavoraveis para a estrategia no dia como: Stop Financeiro do dia ou limite de Tendencia do dia)
if(VerificaRiscosNivel3(Gerenciador, Operacao, Fluidos) == false)
{
//AtualizaPosicoes(Operacao, Fluidos, ArrayTick, ArrayBook);
//AtualizaOrdens(Operacao, Fluidos);
//ExecutaSlotsDisponiveis();
//== atualiza triggers de entrada
AtualizaTriggersEntrada ();
ExecutaOrdens();
GerenciaPosicoes();
Operacao.countFechaDia == 0;
}
else
{
if(Operacao.countFechaDia == 0)
{
FechaPosicoes(Operacao);
Print("Mandou fechar todas as posicoes pelo risco.");
CancelaOrdensAbertas(Operacao);
Print("Mandou cancelar todas as ordens abertas pelo risco.");
if((PositionsTotal() + OrdersTotal()) == 0) Operacao.countFechaDia = 1;
}
}
//ATUALIZA TELEMETRIA
Comment(
"===GERENCIAMENTO P&L===", "\n" +
"CAPITAL BRUTO FECHADO: ", Gerenciador.capitalFechado, "\n" +
"CAPITAL BRUTO ABERTO: ", Gerenciador.capitalAberto, "\n" +
"LUCRO BRUTO FECHADO: ", Gerenciador.lucroBrutoFechado, "\n" +
"LUCRO BRUTO ABERTO: ", Gerenciador.lucroBrutoAberto, "\n" +
"LUCRO BRUTO COMPOSTO: ", Gerenciador.lucroBrutoComposto, "\n" +
"LUCRO LIQUIDO: ", Gerenciador.lucroLiquido, "\n" +
"NUMERO DE CONTRATOS (compra+venda): ", Operacao.numeroContratos - (2*(Fluidos.rajada*Fluidos.niveis)), "\n" +
"CUSTO: ", (Operacao.numeroContratos - (2*Fluidos.rajada*Fluidos.niveis)) * (Fluidos.c*2), "\n" +
"INVENTARIO: ", Fluidos.q, "\n" +
"\n" +
"===GERENCIAMENTO DA OPERACAO===", "\n" +
"LC: ", NormalizeDouble(Fluidos.lambdaC,2), "\n" +
"LV: ", NormalizeDouble(Fluidos.lambdaV,2), "\n" +
"KC: ", Fluidos.KC, "\n" +
"KV: ", Fluidos.KV, "\n" +
"EC: ", NormalizeDouble(Fluidos.sigmaHFT/Fluidos.lambdaC, 2), "\n" +
"EV: ", NormalizeDouble(Fluidos.sigmaHFT/Fluidos.lambdaC, 2), "\n" +
"TC: ", NormalizeDouble((Fluidos.KV/Fluidos.lambdaC), 2), "\n" +
"TV: ", NormalizeDouble((Fluidos.KC/Fluidos.lambdaV), 2), "\n" +
"VOL: ", NormalizeDouble(Fluidos.sigmaLFT/600,2), "\n" +
"A: ", NormalizeDouble(Fluidos.assimetria,2), "\n" +
"C: ", NormalizeDouble(Fluidos.curtose,2), "\n" +
"IMBALANCE: ", NormalizeDouble(Fluidos.imbalance,4), "\n" +
"TENDENCIA: ", Fluidos.tendencia);
// Print(Fluidos.midPrice,"/",NormalizeDouble(Fluidos.media,0),"/",SlotsC[0].spreadEnvio,"/",SlotsC[0].spreadAlvo,"/",SlotsV[0].spreadEnvio,"/",SlotsV[0].spreadAlvo,"/",NormalizeDouble(Fluidos.lambdaC,0),"/",NormalizeDouble(Fluidos.lambdaV,0),"/",Fluidos.KC,"/",Fluidos.KV,"/",NormalizeDouble(Fluidos.imbalance,2),"/",Fluidos.tendencia,"/",NormalizeDouble(Fluidos.sigmaHFT,0));
return;
}
//+------------------------------------------------------------------+
//| 2.2 - FUNCAO QUE ATUALIZA POSICOES |
//+------------------------------------------------------------------+
void AtualizaTriggersEntrada(operacao &Operacao)
TimeToStruct(TimeCurrent(), Operacao.horarioMQL_atual);
ushort minutoAtual = (Operacao.horarioMQL_atual.hour * 60) + Operacao.horarioMQL_atual.min;
if(minutoAtual == (horarioCorteFimAnalise){
{
Operacao.horarioMQL_inicio.year = Operacao.horarioMQL_atual.year;
Operacao.horarioMQL_inicio.month = Operacao.horarioMQL_atual.month;
Operacao.horarioMQL_inicio.day = Operacao.horarioMQL_atual.day;
Operacao.horarioMQL_inicio.hour = (horarioCorteInicioAnalise - MathMod(horarioCorteInicioAnalise,60))/60;
Operacao.horarioMQL_inicio.min = MathMod(horarioCorteInicioAnalise,60);
Operacao.horarioMQL_inicio.sec = Operacao.horarioMQL_atual.sec;
Operacao.horarioMQL_inicio.day_of_week = Operacao.horarioMQL_atual.day_of_week;
Operacao.horarioMQL_inicio.day_of_year = Operacao.horarioMQL_atual.day_of_year;
Operacao.horarioMQL_final.year = Operacao.horarioMQL_atual.year;
Operacao.horarioMQL_final.month = Operacao.horarioMQL_atual.month;
Operacao.horarioMQL_final.day = Operacao.horarioMQL_atual.day;
Operacao.horarioMQL_final.hour = (horarioCorteFimAnalise - MathMod(horarioCorteFimAnalise,60))/60;
Operacao.horarioMQL_final.min = MathMod(horarioCorteFimAnalise,60);
Operacao.horarioMQL_final.sec = Operacao.horarioMQL_atual.sec;
Operacao.horarioMQL_final.day_of_week = Operacao.horarioMQL_atual.day_of_week;
Operacao.horarioMQL_final.day_of_year = Operacao.horarioMQL_atual.day_of_year;
int numeroBarras = Bars(_Symbol,PERIOD_M1, StructToTime(Operacao.horarioMQL_inicio) , StructToTime(Operacao.horarioMQL_final));
double faixaSuperior = 0.0;
double faixaInferior = 0.0;
for(int i = 0; i<numeroBarras ; i++)
{
if(faixaSuperior < iHigh(_Symbol, PERIOD_M1, i) faixaSuperior = iHigh(_Symbol, PERIOD_M1, i);
if(faixaInferior > iLow(_Symbol, PERIOD_M1, i) faixaInferior = iLow(_Symbol, PERIOD_M1, i);
}
}
else
{
//espera at<EFBFBD> as 10h
}
//+------------------------------------------------------------------+
//| 2.2 - FUNCAO QUE ATUALIZA POSICOES |
//+------------------------------------------------------------------+
void AtualizaPosicoes(operacao &Operacao, fluido &Fluidos, MqlTick &ArrayTick[], MqlBookInfo &ArrayBook[])
{
Fluidos.tendencia = GetTendencia(Fluidos, ArrayTick, ArrayBook);
for(int i=0; i<PositionsTotal(); i++)
{
ulong ticket = PositionGetTicket(i);
string symbol = PositionGetString(POSITION_SYMBOL);
ulong magicEA = PositionGetInteger(POSITION_MAGIC);
TimeToStruct(PositionGetInteger(POSITION_TIME),Operacao.cronometroPosicao);
TimeToStruct(TimeCurrent(), Operacao.horarioMQL_atual);
int duracaoPosicao = (Operacao.horarioMQL_atual.hour*60*60 + Operacao.horarioMQL_atual.min*60 + Operacao.horarioMQL_atual.sec) - (Operacao.cronometroPosicao.hour*60*60 + Operacao.cronometroPosicao.min*60 + Operacao.cronometroPosicao.sec);
TimeToStruct(PositionGetInteger(POSITION_TIME_UPDATE), Operacao.cronometroRefreshPosicao);
int refreshPosicao = (Operacao.horarioMQL_atual.hour*60*60 + Operacao.horarioMQL_atual.min*60 + Operacao.horarioMQL_atual.sec) - (Operacao.cronometroRefreshPosicao.hour*60*60 + Operacao.cronometroRefreshPosicao.min*60 + Operacao.cronometroRefreshPosicao.sec);
Operacao.tipoPosicao = PositionGetInteger(POSITION_TYPE);
double precoAlvoAnt = PositionGetDouble(POSITION_TP);
double precoStopAnt = PositionGetDouble(POSITION_SL);
Operacao.precoAlvo = PositionGetDouble(POSITION_TP);
Operacao.precoStop = PositionGetDouble(POSITION_SL);
Operacao.precoEnvio = PositionGetDouble(POSITION_PRICE_OPEN);
double spread = 0.0;
int depth = 0;
if(Operacao.chaveTheta == true)
{
if(Operacao.tipoPosicao == POSITION_TYPE_BUY)
{
spread = precoAlvoAnt - Operacao.precoEnvio;
depth = spread / Fluidos.tickMin;
Operacao.expiraPosicao = CalculaTempoExpiraPosicaoCompra(Operacao, Fluidos, depth);
}
else
{
spread = Operacao.precoEnvio - precoAlvoAnt;
depth = spread / Fluidos.tickMin;
Operacao.expiraPosicao = CalculaTempoExpiraPosicaoVenda(Operacao, Fluidos, depth);
}
}
if(symbol == _Symbol)
{
if(duracaoPosicao > Operacao.expiraPosicao)
{
//cancela posicao
FechaPosicao(Operacao, ticket);
Print("Mandou fechar a posicao por expiracao de tempo.");
}
else
{
CalculaPrecoTrailing(Operacao, Fluidos);
if(precoStopAnt != Operacao.precoStop)
{
if(Operacao.tipoPosicao == POSITION_TYPE_BUY)
{
if(precoStopAnt < Operacao.precoStop) ModificaStopPosicaoAberta(Operacao, ticket);
}
else
{
if(precoStopAnt > Operacao.precoStop) ModificaStopPosicaoAberta(Operacao, ticket);
}
}
if( MathMod(refreshPosicao, Fluidos.TPr) >= (Fluidos.TPr -2) )
{
//atualiza posicao
CalculaPrecoPosicao(Operacao, Fluidos);
if((Operacao.precoAlvo != precoAlvoAnt) || (Operacao.precoStop != precoStopAnt))
{
if(Operacao.tipoPosicao == POSITION_TYPE_BUY)
{
if(Operacao.precoAlvo < Operacao.precoStop) Operacao.precoAlvo = precoAlvoAnt;
ModificaPosicaoAberta(Operacao, ticket);
}
else if(Operacao.tipoPosicao == POSITION_TYPE_SELL)
{
if(Operacao.precoAlvo > Operacao.precoStop) Operacao.precoAlvo = precoAlvoAnt;
ModificaPosicaoAberta(Operacao, ticket);
}
}
}
}
}
}
}
//+------------------------------------------------------------------+
//| 2.3 - FUNCAO QUE ATUALIZA ORDENS |
//+------------------------------------------------------------------+
void AtualizaOrdens(operacao &Operacao, fluido &Fluidos)
{
ulong ticket = 0;
MqlDateTime horarioMQL_ordem;
string tendencia = "";
tendencia = GetTendencia(Fluidos, ArrayTick, ArrayBook);
for(int i=OrdersTotal()-1;i>=0;i--)
{
ticket = OrderGetTicket(i);
ushort horarioOrdem = 0;
ushort horarioShortAtual = 0;
OrderSelect(ticket);
double tamanho = OrderGetDouble(ORDER_VOLUME_INITIAL);
TimeToStruct(TimeCurrent(), Operacao.horarioMQL_atual);
TimeToStruct(OrderGetInteger(ORDER_TIME_SETUP), horarioMQL_ordem);
horarioOrdem = horarioMQL_ordem.hour*60*60 + horarioMQL_ordem.min*60 + horarioMQL_ordem.sec;
horarioShortAtual = Operacao.horarioMQL_atual.hour*60*60 + Operacao.horarioMQL_atual.min*60 + Operacao.horarioMQL_atual.sec;
// Print("horarioAtual: ", horarioShortAtual, " horarioOrdem: ", horarioOrdem, " Fluidos.lifetime: ", Fluidos.lifetimeOrdem);
if((horarioShortAtual - horarioOrdem) > Fluidos.TOr)
{
bool retCancelou = Operacao.negocio.OrderDelete(ticket);
if(retCancelou == true) Operacao.numeroContratos = Operacao.numeroContratos - tamanho;
// Print("Cancelou ordem aberta por expira<00><00>o.");
}
else
{
//SE FOR COMPRA
if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT)
{
//SE FOR BAIXA
if(tendencia == "BAIXA FORTE")
{
bool retCancelou = Operacao.negocio.OrderDelete(ticket);
if(retCancelou == true) Operacao.numeroContratos = Operacao.numeroContratos - tamanho;
// Print("Cancelou ordem de compra aberta por tend<00>ncia de baixa.");
}
}
else
{
//SE FOR ALTA
if(tendencia == "ALTA FORTE")
{
bool retCancelou = Operacao.negocio.OrderDelete(ticket);
if(retCancelou == true) Operacao.numeroContratos = Operacao.numeroContratos - tamanho;
// Print("Cancelou ordem de venda aberta por tend<00>ncia de alta.");
}
}
}
}
}
//+------------------------------------------------------------------+
//| 2.4 - FUNCAO QUE ATUALIZA E EXECUTA OS SLOTS DISPONVEIS DE ORDENS|
//+------------------------------------------------------------------+
void ExecutaSlotsDisponiveis()
{
//Avanca os status dos slots
for(int i=0; i<Fluidos.niveis; i++)
{
Fluidos.iSlot = i;
//C
TrocaMarcha(Operacao, Fluidos, SlotsC);
if(SlotsC[i].statusCambio == 1)
{
CalculaPrecoOrdem(Operacao, Fluidos, SlotsC, ArrayTick, ArrayBook);
CalculaQuantidade(Fluidos, SlotsC);
}
if(Fluidos.LC == true) ExecutaSlotsCompra(Operacao, Fluidos, SlotsC, ArrayTick, i);
//V
TrocaMarcha(Operacao, Fluidos, SlotsV);
if(SlotsV[i].statusCambio == 1)
{
CalculaPrecoOrdem(Operacao, Fluidos, SlotsV, ArrayTick, ArrayBook);
CalculaQuantidade(Fluidos, SlotsV);
}
if(Fluidos.LV == true) ExecutaSlotsVenda(Operacao, Fluidos, SlotsV, ArrayTick, i);
}
}
//+------------------------------------------------------------------+
//| 2.5 - FUNCAO QUE VARRE SLOTS DE COMPRA E ENVIA ORDENS |
//+------------------------------------------------------------------+
void ExecutaSlotsCompra(operacao &Operacao, fluido &Fluidos, slot &SlotsC[], MqlTick &ArrayTick[], int i)
{
//Print("status motor: ",SlotsC[i].statusMotor);
switch(SlotsC[i].statusMotor)
{
case 1 :
if(VerificaRiscosNivel2C(Operacao, Fluidos) == true) break;
if(SlotsC[i].precoEnvio < ArrayTick[0].last)
{
CompraLimite(Operacao, SlotsC, i);
// Print("Mandou ordem de compra limite.");
if(Operacao.result.retcode == 10009)
{
//SlotsC[i].idOrdem = Operacao.result.order;
OrderSelect(SlotsC[i].idOrdem);
TimeToStruct(TimeCurrent(),SlotsC[i].cronometro);
}
else
{
SlotsC[i].statusCambio = 0;
SlotsC[i].statusMotor = 0;
}
}
break;
case 3 :
CancelaOrdemAberta(Operacao, SlotsC[i].idOrdem);
// Print("Cancelou ordem de compra limite.");
break;
default :
break;
}
}
//+------------------------------------------------------------------+
//| 2.6 - FUNCAO QUE VARRE SLOTS DE VENDA E ENVIA ORDENS |
//+------------------------------------------------------------------+
void ExecutaSlotsVenda(operacao &Operacao, fluido &Fluidos, slot &SlotsV[], MqlTick &ArrayTick[], int i)
{
//Print("status motor: ",SlotsV[i].statusMotor);
switch(SlotsV[i].statusMotor)
{
case 1 :
if(VerificaRiscosNivel2V(Operacao, Fluidos) == true) break;
if(SlotsV[i].precoEnvio > ArrayTick[0].last)
{
VendaLimite(Operacao, SlotsV, i);
// Print("Mandou ordem de venda limite.");
if(Operacao.result.retcode == 10009)
{
//Avanca o status do slot para enviado
//SlotsV[i].idOrdem = Operacao.result.order;
OrderSelect(SlotsV[i].idOrdem);
TimeToStruct(TimeCurrent(), SlotsV[i].cronometro);
}
else
{
SlotsV[i].statusCambio = 0;
SlotsV[i].statusMotor = 0;
}
}
break;
case 3 :
CancelaOrdemAberta(Operacao, SlotsV[i].idOrdem);
// Print("Cancelou ordem de compra limite.");
break;
default :
break;
}
}
//+------------------------------------------------------------------+
//| 2.7 - FUNCAO QUE CALCULA O TEMPO LIMITE DE EXPIRACAO DE POSICAO C|
//+------------------------------------------------------------------+
int CalculaTempoExpiraPosicaoCompra(operacao &Operacao, fluido &Fluidos, int depth)
{
int tempo = 0;
//int c = 1;
tempo = Fluidos.ft * (depth * Fluidos.KV) / Fluidos.lambdaC;
return tempo;
}
//+------------------------------------------------------------------+
//| 2.8 - FUNCAO QUE CALCULA O TEMPO LIMITE DE EXPIRACAO DE POSICAO V|
//+------------------------------------------------------------------+
int CalculaTempoExpiraPosicaoVenda(operacao &Operacao, fluido &Fluidos, int depth)
{
int tempo = 0;
//int c = 1;
tempo = Fluidos.ft * (depth * Fluidos.KC) / Fluidos.lambdaV;
return tempo;
}
//+------------------------------------------------------------------+
//| 2.9 - FUNCAO QUE CALCULA O TEMPO LIMITE DE EXPIRACAO DE ORDEM C |
//+------------------------------------------------------------------+
int CalculaTempoExpiraOrdemCompra(operacao &Operacao, fluido &Fluidos, int depth)
{
int tempo = 0;
int c = 1;
//tempo = c * (depth * Fluidos.KC) / Fluidos.lambdaV;
tempo = 60;
return tempo;
}
//+------------------------------------------------------------------+
//| 2.10 - FUNCAO QUE CALCULA O TEMPO LIMITE DE EXPIRACAO DE ORDEM V |
//+------------------------------------------------------------------+
int CalculaTempoExpiraOrdemVenda(operacao &Operacao, fluido &Fluidos, int depth)
{
int tempo = 0;
int c = 1;
tempo = c * (depth * Fluidos.KV) / Fluidos.lambdaC;
tempo = 60;
return tempo;
}
//+===================================================================================================================================================================================+
//| FIM DO PROGRAMA
//+===================================================================================================================================================================================+