446 lines
No EOL
39 KiB
MQL5
446 lines
No EOL
39 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| S2_Motor1_v0.mq5 |
|
|
//| DESENVOLVIMENTO |
|
|
//| OXFORD |
|
|
//| HEDGING HORN CAPITAL |
|
|
//| https://www.hhcapital.com.br |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2022, HEDGING HORN CAPITAL"
|
|
#property link "https://www.hhcapítal.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 <Expert/Expert.mqh>
|
|
#include <Trade/Trade.mqh>
|
|
#include <Trade/SymbolInfo.mqh>
|
|
#include "MarketBook.mqh"
|
|
#include "S1_Admissao1_v0.mqh"
|
|
#include "S3_Freios1_v0.mqh"
|
|
#include "S4_Cambio4x4_v0.mqh"
|
|
#include "S5_Direcao1_v0.mqh"
|
|
#include "S6_Transmissao1_v0.mqh"
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 1.2 - ENTRADAS DE USUARIO |
|
|
//+------------------------------------------------------------------+
|
|
//+------------------------------------------------------------------+
|
|
//| 1.2.1 - INPUTS DE GERENCIAMENTO DE INVENTARIO |
|
|
//+------------------------------------------------------------------+
|
|
input group "Gerenciamento de Inventário--------------------------------------------------------------------------------------------------"
|
|
input int inventario = 10; //Inventario máximo Q {1}[1, +inf[
|
|
input int rajada = 10; //Quantidade por ordem η {1}[1, +inf[
|
|
input double fi = 0.0002; //Fi: Running Penalty (injeção eletrônica)
|
|
input int lifetime = 10; //Tempo em minutos da duracao de uma ordem pendente
|
|
//+------------------------------------------------------------------+
|
|
//| 1.2.2 - INPUTS DE GERENCIAMENTO DE OPERACOES |
|
|
//+------------------------------------------------------------------+
|
|
input group "Gerenciamento de Operacões---------------------------------------------------------------------------------------------------"
|
|
input ushort horarioShort_inicial = 545; //Horário inicial 09:05 -> Τ0 em minutos {600}[600, 985]
|
|
input ushort horarioShort_final = 980; //Horário final 16:20 -> ΤF em minutos {700}[600, 985]
|
|
input ushort horarioShort_fechamento = 985; //Horário limite de after 16:25 -> ΤP em minutos {705}[600, 990]
|
|
input ulong T = 180; //Quantidade maxima de tempo para encerramento do trade
|
|
input int profundidadeBook = 10; //Profundidade do book a calcular o k {3}[1, +inf[
|
|
input double alpha = 0.0001; //Custo por zerar posição
|
|
input double premioOperacao = 10; //Premio por trade liquido ρ {0.64}[0.0, 1.0[
|
|
input double custoOperacao = 2.1; //Custo por operacao ζ {1.86}[0.0, 2.0[
|
|
input double tickMin = 5; //Tick minimo do ativo Δ {0.5}[0.01, +inf[
|
|
input bool chaveBook = false; //Chave que liga/desliga o book para usar na real ou backtest {false} [true=ligado,false=desligado]
|
|
input double desvioDiario = 8; //Desvios padroes limite para o preco do ativo no dia
|
|
input double lambdaC = 10; //Lambda de compra
|
|
input double lambdaV = 10; //Lambda de venda
|
|
input double KC = 100; //Fila media de compra
|
|
input double KV = 100; //Fila media de venda
|
|
//+------------------------------------------------------------------+
|
|
//| 1.2.3 - INPUTS DE GERENCIAMENTO DE RISCOS |
|
|
//+------------------------------------------------------------------+
|
|
input group "Gerenciamento de Riscos------------------------------------------------------------------------------------------------------"
|
|
input double alvoFinanceiro = 1000.0; //3º Order Risk M.: Alvo financeiro no dia sup(Χ)
|
|
input double stopFinanceiro = -1000.0; //3º Order Risk M.: Stop financeiro no dia inf(Χ)
|
|
//+------------------------------------------------------------------+
|
|
//| 1.3 - VARIAVEIS GLOBAIS |
|
|
//+------------------------------------------------------------------+
|
|
//+------------------------------------------------------------------+
|
|
//| 1.3.1 - VARIAVEIS FINANCEIRAS |
|
|
//+------------------------------------------------------------------+
|
|
double saldoInicialDia = 0.0;
|
|
double saldoFinalDia = 0.0;
|
|
double diferencaSaldo = 0.0;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 1.3.4 - VARIAVEIS OPERACIONAIS |
|
|
//+------------------------------------------------------------------+
|
|
|
|
int magic = 11111;
|
|
MqlDateTime horarioMQL_inicio,
|
|
horarioMQL_final,
|
|
horarioMQL_encerramento,
|
|
horarioMQL_atual,
|
|
horarioMQL_comprado,
|
|
horarioMQL_compra;
|
|
ushort horarioShort_atual;
|
|
datetime horarioDatetime_atual;
|
|
int diaAtual = 0;
|
|
CSymbolInfo simbolo;
|
|
CMarketBook Book(_Symbol);
|
|
CTrade negocio;
|
|
MqlTradeRequest request;
|
|
MqlTradeResult result;
|
|
MqlTradeTransaction transaction;
|
|
MqlTradeCheckResult check_result;
|
|
MqlBookInfo ArrayBook[];
|
|
MqlTick ArrayTick[];
|
|
double MA[];
|
|
double STDDEV[];
|
|
int handlerMA;
|
|
int handlerSTDDEV;
|
|
int periodoMA = 2;
|
|
int periodoSTDDEV = 2;
|
|
string handlerNormalizeDoubleSize;
|
|
int normalizeDoubleSize;
|
|
int intervaloTicks = 10;
|
|
double limiteInfDesvio = 0;
|
|
double limiteSupDesvio = 500;
|
|
fluido Fluidos;
|
|
slot SlotsC[];
|
|
slot SlotsV[];
|
|
bool chaveFechaPosicao = true;
|
|
|
|
//+===================================================================================================================================================================================+
|
|
//| 2 - SESSAO DE LOGICA CENTRAL / MOTOR
|
|
//+===================================================================================================================================================================================+
|
|
//+------------------------------------------------------------------+
|
|
//| 2.1 - FUNCAO DE INICIALIZACAO |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
|
|
Print("DESENVOLVIMENTO V0");
|
|
//Inicializa o saldo da conta
|
|
saldoInicialDia = AccountInfoDouble(ACCOUNT_BALANCE);
|
|
|
|
//Inicializa a contagem de dias
|
|
TimeToStruct(TimeCurrent(), horarioMQL_atual);
|
|
diaAtual = horarioMQL_atual.day;
|
|
|
|
//Inicializa o MarketBook
|
|
if(chaveBook == true) if(!MarketBookAdd(_Symbol)) Print("Falha para inicializar o book");
|
|
|
|
ArrayResize(ArrayTick, intervaloTicks, intervaloTicks);
|
|
|
|
//Inicializa o ArrayTick
|
|
if(CopyTicks(_Symbol,ArrayTick,COPY_TICKS_ALL,0,intervaloTicks) != -1)
|
|
{
|
|
ArraySetAsSeries(ArrayTick,true);
|
|
}
|
|
else Print("Falha para inicializar o ArrayTicks: ", GetLastError());
|
|
|
|
//NormalizeDouble
|
|
handlerNormalizeDoubleSize = DoubleToString(tickMin);
|
|
handlerNormalizeDoubleSize = StringReplace(handlerNormalizeDoubleSize,".","");
|
|
normalizeDoubleSize = (StringLen(handlerNormalizeDoubleSize))-1;
|
|
|
|
//Ajusta o tamanho dos arrays de slots de compra e venda
|
|
ArrayResize(SlotsC, inventario);
|
|
ArrayResize(SlotsV, inventario);
|
|
//inicializa os slots de compra e venda
|
|
for(int i=0; i<inventario ;i++)
|
|
{
|
|
SlotsC[i].status = 0;
|
|
SlotsV[i].status = 0;
|
|
SlotsC[i].ponta = 0;
|
|
SlotsV[i].ponta = 2;
|
|
}
|
|
|
|
//Cria os buffers dos indicadores de media e desvio padrao
|
|
handlerMA = iMA(_Symbol, PERIOD_M5, periodoMA, 0, MODE_EMA, PRICE_MEDIAN);
|
|
handlerSTDDEV = iStdDev(_Symbol, PERIOD_M5, periodoSTDDEV, 0, MODE_EMA, PRICE_MEDIAN);
|
|
ArraySetAsSeries(MA, true);
|
|
ArraySetAsSeries(STDDEV, true);
|
|
CopyBuffer(handlerMA,0,1,2,MA);
|
|
CopyBuffer(handlerSTDDEV,0,1,2,STDDEV);
|
|
Fluidos.media = MA[0];
|
|
Fluidos.sigmaHFT = STDDEV[0];
|
|
Fluidos.driftLFTTend = MA[0] - MA[1];
|
|
Fluidos.driftLFTVol = STDDEV[0] - STDDEV[1];
|
|
Fluidos.fi = fi;
|
|
Fluidos.alpha = alpha;
|
|
Fluidos.q = 0;
|
|
Fluidos.Q = inventario;
|
|
Fluidos.rajada = rajada;
|
|
Fluidos.t = 0;
|
|
Fluidos.T = T;
|
|
Fluidos.nBook = profundidadeBook;
|
|
Fluidos.iSlot = 0;
|
|
Fluidos.magic = magic;
|
|
Fluidos.tickMin = tickMin;
|
|
Fluidos.chaveBook = chaveBook;
|
|
Fluidos.desvioDiario = desvioDiario;
|
|
Fluidos.lambdaC = lambdaC;
|
|
Fluidos.lambdaV = lambdaV;
|
|
Fluidos.KC = KC;
|
|
Fluidos.KV = KV;
|
|
Fluidos.lifetime = lifetime;
|
|
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 2.2 - FUNCAO EVENTO TICK / CORACAO |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
//Atualiza os ticks e variaveis
|
|
AtualizaVariaveis();
|
|
|
|
Fluidos.precoAbertura = iOpen(_Symbol,PERIOD_D1,0);
|
|
|
|
//Chamar o motor
|
|
if(VerificaHorarioOrdens(horarioMQL_atual, horarioShort_inicial, horarioShort_final)) FazTrades();
|
|
else if(VerificaHorarioFechamento(horarioMQL_atual, horarioShort_fechamento))
|
|
{
|
|
if(chaveFechaPosicao == true) chaveFechaPosicao = FechaPosicao(negocio);
|
|
CancelaOrdensAbertas(negocio);
|
|
ArrayFree(SlotsC);
|
|
ArrayFree(SlotsV);
|
|
ArrayResize(SlotsC, inventario);
|
|
ArrayResize(SlotsV, inventario);
|
|
|
|
for(int i=0;i<ArraySize(SlotsC);i++)
|
|
{
|
|
SlotsC[i].status = 0;
|
|
SlotsV[i].status = 0;
|
|
}
|
|
}
|
|
else return;
|
|
|
|
return;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 2.3 - FUNCAO EVENTO BOOK |
|
|
//+------------------------------------------------------------------+
|
|
void OnBookEvent(const string &symbol)
|
|
{
|
|
if(Fluidos.chaveBook == true)
|
|
{
|
|
//Atualiza os melhores indices de bid e ask do book
|
|
if(MarketBookGet(_Symbol, ArrayBook))
|
|
{
|
|
Fluidos.iBid0 = Book.InfoGetInteger(MBOOK_BEST_BID_INDEX);
|
|
Fluidos.iAsk0 = Book.InfoGetInteger(MBOOK_BEST_ASK_INDEX);
|
|
}
|
|
else
|
|
{
|
|
Print("Falha ao obter o Book");
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 2.4 - FUNCAO EVENTO TRADE |
|
|
//+------------------------------------------------------------------+
|
|
void OnTrade()
|
|
{
|
|
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 2.5 - FUNCAO DE DESLIGAMENTO |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
//Da release nos indicadores
|
|
IndicatorRelease(handlerMA);
|
|
IndicatorRelease(handlerSTDDEV);
|
|
Print("OUTPUT PATH=",TerminalInfoString(TERMINAL_DATA_PATH));
|
|
|
|
//Falha na desinicializacao
|
|
printf("Deinit reason: %d", reason);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 2.6 - FUNCAO QUE ATUALIZA AS VARIAVEIS IMPORTANTES |
|
|
//+------------------------------------------------------------------+
|
|
void AtualizaVariaveis()
|
|
{
|
|
//Atualiza o horario
|
|
TimeToStruct(TimeCurrent(), horarioMQL_atual);
|
|
|
|
//Atualiza o book
|
|
if(!simbolo.RefreshRates()) return;
|
|
|
|
if(Fluidos.chaveBook == true)
|
|
{
|
|
if(MarketBookGet(_Symbol, ArrayBook))
|
|
{
|
|
//Atualiza os indices do topo do book
|
|
Fluidos.iBid0 = Book.InfoGetInteger(MBOOK_BEST_BID_INDEX);
|
|
Fluidos.iAsk0 = Book.InfoGetInteger(MBOOK_BEST_ASK_INDEX);
|
|
}
|
|
else
|
|
{
|
|
Print("Falha ao atualizar o Book");
|
|
}
|
|
}
|
|
|
|
ArrayResize(ArrayTick, intervaloTicks, 0);
|
|
//Atualiza os ticks
|
|
if(CopyTicks(Symbol(),ArrayTick,COPY_TICKS_ALL,0,intervaloTicks) != -1) ArraySetAsSeries(ArrayTick,true);
|
|
else Print("Falha para inicializar o ArrayTicks: ", GetLastError());
|
|
|
|
|
|
//Atualiza os buffers de media e desvio padrao
|
|
CopyBuffer(handlerMA,0,1,2,MA);
|
|
CopyBuffer(handlerSTDDEV,0,1,2,STDDEV);
|
|
Fluidos.media = (simbolo.Ask() + simbolo.Bid())/2;
|
|
Fluidos.sigmaHFT = STDDEV[0];
|
|
Fluidos.driftLFTTend = MA[0] - MA[1];
|
|
Fluidos.driftLFTVol = STDDEV[0] - STDDEV[1];
|
|
Fluidos.q = AtualizaQuantidade(Fluidos);
|
|
|
|
for(int i=0; i<inventario ;i++)
|
|
{
|
|
SlotsC[i].ponta = 0;
|
|
SlotsV[i].ponta = 2;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 2.7 - FUNCAO QUE FAZ NEGOCIACOES |
|
|
//+------------------------------------------------------------------+
|
|
void FazTrades()
|
|
{
|
|
chaveFechaPosicao = true;
|
|
//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(alvoFinanceiro, stopFinanceiro, diferencaSaldo, saldoInicialDia, saldoFinalDia, diaAtual, horarioMQL_atual, intervaloTicks, ArrayTick, Fluidos, simbolo) == false)
|
|
{
|
|
//Avanca os status dos slots
|
|
GerenciaSlots(ArrayBook, Fluidos, SlotsC, SlotsV, horarioMQL_atual);
|
|
|
|
//Verifica os Riscos de Nivel 2 para Compra
|
|
if(VerificaRiscosNivel2C(Fluidos) == false)
|
|
{
|
|
//Verifica os slots de compra, se estiverem disponiveis, mande ordens
|
|
DisparaSlotsCompra();
|
|
}
|
|
|
|
if(VerificaRiscosNivel2V(Fluidos) == false)
|
|
{
|
|
//Verifica os slots de venda, se estiverem disponiveis, mande ordens
|
|
DisparaSlotsVenda();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FechaPosicao(negocio);
|
|
CancelaOrdensAbertas(negocio);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 2.8 - FUNCAO QUE VARRE SLOTS DE COMPRA E ENVIA ORDENS |
|
|
//+------------------------------------------------------------------+
|
|
void DisparaSlotsCompra()
|
|
{
|
|
for(int i=0; i<ArraySize(SlotsC); i++)
|
|
{
|
|
//Para cada possibilidade de status
|
|
switch(SlotsC[i].status)
|
|
{
|
|
//Preenche ordens de slots ready
|
|
case 1 :
|
|
//Print("Preco envio: ",SlotsC[i].precoEnvio," Preco last: ", ArrayTick[0].last);
|
|
//Verifica se o preco de envio e menor que o preco atual (manda um novo box de ordem)
|
|
if(SlotsC[i].precoEnvio <= ArrayTick[0].last)
|
|
{
|
|
CompraLimite(SlotsC[i].precoEnvio, SlotsC[i].precoStop, SlotsC[i].qtd, magic, SlotsC, i, simbolo, request, result, check_result);
|
|
|
|
if(result.retcode == 10009)
|
|
{
|
|
//Avanca o status do slot para enviado
|
|
SlotsC[i].idOrdem = result.order;
|
|
OrderSelect(SlotsC[i].idOrdem);
|
|
TimeToStruct(OrderGetInteger(ORDER_TIME_SETUP),SlotsC[i].cronometro);
|
|
}
|
|
else
|
|
{
|
|
SlotsC[i].status = 0;
|
|
}
|
|
}
|
|
break;
|
|
//Altera ordem enviada com precoEnvio, precoStop ou precoAlvo novos (atualiza o box de ordem)
|
|
case 2 :
|
|
ModificaOrdemEnviada(SlotsC[i].idOrdem, SlotsC[i].precoEnvio, 0, SlotsC[i].precoStop, magic, negocio, simbolo, request, result, check_result);
|
|
break;
|
|
|
|
case 4 :
|
|
CancelaOrdemAberta(SlotsC[i].idOrdem, negocio);
|
|
break;
|
|
//Default
|
|
default :
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 2.9 - FUNCAO QUE VARRE SLOTS DE VENDA E ENVIA ORDENS |
|
|
//+------------------------------------------------------------------+
|
|
void DisparaSlotsVenda()
|
|
{
|
|
for(int i=0; i<ArraySize(SlotsV); i++)
|
|
{
|
|
//Para cada possibilidade de status
|
|
switch(SlotsV[i].status)
|
|
{
|
|
//Preenche ordens de slots ready
|
|
case 1 :
|
|
//Verifica se o preco de envio e maior que o preco atual (manda um novo box de ordem)
|
|
if(SlotsV[i].precoEnvio >= ArrayTick[0].last)
|
|
{
|
|
VendaLimite(SlotsV[i].precoEnvio, SlotsV[i].precoStop, SlotsV[i].qtd, magic, SlotsV, i, simbolo, request, result, check_result);
|
|
|
|
if(result.retcode == 10009)
|
|
{
|
|
//Avanca o status do slot para enviado
|
|
SlotsV[i].idOrdem = result.order;
|
|
OrderSelect(SlotsV[i].idOrdem);
|
|
TimeToStruct(OrderGetInteger(ORDER_TIME_SETUP),SlotsV[i].cronometro);
|
|
}
|
|
else
|
|
{
|
|
SlotsV[i].status = 0;
|
|
}
|
|
}
|
|
break;
|
|
//Altera ordem enviada com precoEnvio, precoStop ou precoAlvo novos (atualiza o box de ordem)
|
|
case 2 :
|
|
ModificaOrdemEnviada(SlotsV[i].idOrdem, SlotsV[i].precoEnvio, 0, SlotsV[i].precoStop, magic, negocio, simbolo, request, result, check_result);
|
|
break;
|
|
|
|
case 4 :
|
|
CancelaOrdemAberta(SlotsV[i].idOrdem, negocio);
|
|
break;
|
|
//Default
|
|
default :
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//+===================================================================================================================================================================================+
|
|
//| FIM DO PROGRAMA
|
|
//+===================================================================================================================================================================================+ |